potree.js 3.9 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343443444434544346443474434844349443504435144352443534435444355443564435744358443594436044361443624436344364443654436644367443684436944370443714437244373443744437544376443774437844379443804438144382443834438444385443864438744388443894439044391443924439344394443954439644397443984439944400444014440244403444044440544406444074440844409444104441144412444134441444415444164441744418444194442044421444224442344424444254442644427444284442944430444314443244433444344443544436444374443844439444404444144442444434444444445444464444744448444494445044451444524445344454444554445644457444584445944460444614446244463444644446544466444674446844469444704447144472444734447444475444764447744478444794448044481444824448344484444854448644487444884448944490444914449244493444944449544496444974449844499445004450144502445034450444505445064450744508445094451044511445124451344514445154451644517445184451944520445214452244523445244452544526445274452844529445304453144532445334453444535445364453744538445394454044541445424454344544445454454644547445484454944550445514455244553445544455544556445574455844559445604456144562445634456444565445664456744568445694457044571445724457344574445754457644577445784457944580445814458244583445844458544586445874458844589445904459144592445934459444595445964459744598445994460044601446024460344604446054460644607446084460944610446114461244613446144461544616446174461844619446204462144622446234462444625446264462744628446294463044631446324463344634446354463644637446384463944640446414464244643446444464544646446474464844649446504465144652446534465444655446564465744658446594466044661446624466344664446654466644667446684466944670446714467244673446744467544676446774467844679446804468144682446834468444685446864468744688446894469044691446924469344694446954469644697446984469944700447014470244703447044470544706447074470844709447104471144712447134471444715447164471744718447194472044721447224472344724447254472644727447284472944730447314473244733447344473544736447374473844739447404474144742447434474444745447464474744748447494475044751447524475344754447554475644757447584475944760447614476244763447644476544766447674476844769447704477144772447734477444775447764477744778447794478044781447824478344784447854478644787447884478944790447914479244793447944479544796447974479844799448004480144802448034480444805448064480744808448094481044811448124481344814448154481644817448184481944820448214482244823448244482544826448274482844829448304483144832448334483444835448364483744838448394484044841448424484344844448454484644847448484484944850448514485244853448544485544856448574485844859448604486144862448634486444865448664486744868448694487044871448724487344874448754487644877448784487944880448814488244883448844488544886448874488844889448904489144892448934489444895448964489744898448994490044901449024490344904449054490644907449084490944910449114491244913449144491544916449174491844919449204492144922449234492444925449264492744928449294493044931449324493344934449354493644937449384493944940449414494244943449444494544946449474494844949449504495144952449534495444955449564495744958449594496044961449624496344964449654496644967449684496944970449714497244973449744497544976449774497844979449804498144982449834498444985449864498744988449894499044991449924499344994449954499644997449984499945000450014500245003450044500545006450074500845009450104501145012450134501445015450164501745018450194502045021450224502345024450254502645027450284502945030450314503245033450344503545036450374503845039450404504145042450434504445045450464504745048450494505045051450524505345054450554505645057450584505945060450614506245063450644506545066450674506845069450704507145072450734507445075450764507745078450794508045081450824508345084450854508645087450884508945090450914509245093450944509545096450974509845099451004510145102451034510445105451064510745108451094511045111451124511345114451154511645117451184511945120451214512245123451244512545126451274512845129451304513145132451334513445135451364513745138451394514045141451424514345144451454514645147451484514945150451514515245153451544515545156451574515845159451604516145162451634516445165451664516745168451694517045171451724517345174451754517645177451784517945180451814518245183451844518545186451874518845189451904519145192451934519445195451964519745198451994520045201452024520345204452054520645207452084520945210452114521245213452144521545216452174521845219452204522145222452234522445225452264522745228452294523045231452324523345234452354523645237452384523945240452414524245243452444524545246452474524845249452504525145252452534525445255452564525745258452594526045261452624526345264452654526645267452684526945270452714527245273452744527545276452774527845279452804528145282452834528445285452864528745288452894529045291452924529345294452954529645297452984529945300453014530245303453044530545306453074530845309453104531145312453134531445315453164531745318453194532045321453224532345324453254532645327453284532945330453314533245333453344533545336453374533845339453404534145342453434534445345453464534745348453494535045351453524535345354453554535645357453584535945360453614536245363453644536545366453674536845369453704537145372453734537445375453764537745378453794538045381453824538345384453854538645387453884538945390453914539245393453944539545396453974539845399454004540145402454034540445405454064540745408454094541045411454124541345414454154541645417454184541945420454214542245423454244542545426454274542845429454304543145432454334543445435454364543745438454394544045441454424544345444454454544645447454484544945450454514545245453454544545545456454574545845459454604546145462454634546445465454664546745468454694547045471454724547345474454754547645477454784547945480454814548245483454844548545486454874548845489454904549145492454934549445495454964549745498454994550045501455024550345504455054550645507455084550945510455114551245513455144551545516455174551845519455204552145522455234552445525455264552745528455294553045531455324553345534455354553645537455384553945540455414554245543455444554545546455474554845549455504555145552455534555445555455564555745558455594556045561455624556345564455654556645567455684556945570455714557245573455744557545576455774557845579455804558145582455834558445585455864558745588455894559045591455924559345594455954559645597455984559945600456014560245603456044560545606456074560845609456104561145612456134561445615456164561745618456194562045621456224562345624456254562645627456284562945630456314563245633456344563545636456374563845639456404564145642456434564445645456464564745648456494565045651456524565345654456554565645657456584565945660456614566245663456644566545666456674566845669456704567145672456734567445675456764567745678456794568045681456824568345684456854568645687456884568945690456914569245693456944569545696456974569845699457004570145702457034570445705457064570745708457094571045711457124571345714457154571645717457184571945720457214572245723457244572545726457274572845729457304573145732457334573445735457364573745738457394574045741457424574345744457454574645747457484574945750457514575245753457544575545756457574575845759457604576145762457634576445765457664576745768457694577045771457724577345774457754577645777457784577945780457814578245783457844578545786457874578845789457904579145792457934579445795457964579745798457994580045801458024580345804458054580645807458084580945810458114581245813458144581545816458174581845819458204582145822458234582445825458264582745828458294583045831458324583345834458354583645837458384583945840458414584245843458444584545846458474584845849458504585145852458534585445855458564585745858458594586045861458624586345864458654586645867458684586945870458714587245873458744587545876458774587845879458804588145882458834588445885458864588745888458894589045891458924589345894458954589645897458984589945900459014590245903459044590545906459074590845909459104591145912459134591445915459164591745918459194592045921459224592345924459254592645927459284592945930459314593245933459344593545936459374593845939459404594145942459434594445945459464594745948459494595045951459524595345954459554595645957459584595945960459614596245963459644596545966459674596845969459704597145972459734597445975459764597745978459794598045981459824598345984459854598645987459884598945990459914599245993459944599545996459974599845999460004600146002460034600446005460064600746008460094601046011460124601346014460154601646017460184601946020460214602246023460244602546026460274602846029460304603146032460334603446035460364603746038460394604046041460424604346044460454604646047460484604946050460514605246053460544605546056460574605846059460604606146062460634606446065460664606746068460694607046071460724607346074460754607646077460784607946080460814608246083460844608546086460874608846089460904609146092460934609446095460964609746098460994610046101461024610346104461054610646107461084610946110461114611246113461144611546116461174611846119461204612146122461234612446125461264612746128461294613046131461324613346134461354613646137461384613946140461414614246143461444614546146461474614846149461504615146152461534615446155461564615746158461594616046161461624616346164461654616646167461684616946170461714617246173461744617546176461774617846179461804618146182461834618446185461864618746188461894619046191461924619346194461954619646197461984619946200462014620246203462044620546206462074620846209462104621146212462134621446215462164621746218462194622046221462224622346224462254622646227462284622946230462314623246233462344623546236462374623846239462404624146242462434624446245462464624746248462494625046251462524625346254462554625646257462584625946260462614626246263462644626546266462674626846269462704627146272462734627446275462764627746278462794628046281462824628346284462854628646287462884628946290462914629246293462944629546296462974629846299463004630146302463034630446305463064630746308463094631046311463124631346314463154631646317463184631946320463214632246323463244632546326463274632846329463304633146332463334633446335463364633746338463394634046341463424634346344463454634646347463484634946350463514635246353463544635546356463574635846359463604636146362463634636446365463664636746368463694637046371463724637346374463754637646377463784637946380463814638246383463844638546386463874638846389463904639146392463934639446395463964639746398463994640046401464024640346404464054640646407464084640946410464114641246413464144641546416464174641846419464204642146422464234642446425464264642746428464294643046431464324643346434464354643646437464384643946440464414644246443464444644546446464474644846449464504645146452464534645446455464564645746458464594646046461464624646346464464654646646467464684646946470464714647246473464744647546476464774647846479464804648146482464834648446485464864648746488464894649046491464924649346494464954649646497464984649946500465014650246503465044650546506465074650846509465104651146512465134651446515465164651746518465194652046521465224652346524465254652646527465284652946530465314653246533465344653546536465374653846539465404654146542465434654446545465464654746548465494655046551465524655346554465554655646557465584655946560465614656246563465644656546566465674656846569465704657146572465734657446575465764657746578465794658046581465824658346584465854658646587465884658946590465914659246593465944659546596465974659846599466004660146602466034660446605466064660746608466094661046611466124661346614466154661646617466184661946620466214662246623466244662546626466274662846629466304663146632466334663446635466364663746638466394664046641466424664346644466454664646647466484664946650466514665246653466544665546656466574665846659466604666146662466634666446665466664666746668466694667046671466724667346674466754667646677466784667946680466814668246683466844668546686466874668846689466904669146692466934669446695466964669746698466994670046701467024670346704467054670646707467084670946710467114671246713467144671546716467174671846719467204672146722467234672446725467264672746728467294673046731467324673346734467354673646737467384673946740467414674246743467444674546746467474674846749467504675146752467534675446755467564675746758467594676046761467624676346764467654676646767467684676946770467714677246773467744677546776467774677846779467804678146782467834678446785467864678746788467894679046791467924679346794467954679646797467984679946800468014680246803468044680546806468074680846809468104681146812468134681446815468164681746818468194682046821468224682346824468254682646827468284682946830468314683246833468344683546836468374683846839468404684146842468434684446845468464684746848468494685046851468524685346854468554685646857468584685946860468614686246863468644686546866468674686846869468704687146872468734687446875468764687746878468794688046881468824688346884468854688646887468884688946890468914689246893468944689546896468974689846899469004690146902469034690446905469064690746908469094691046911469124691346914469154691646917469184691946920469214692246923469244692546926469274692846929469304693146932469334693446935469364693746938469394694046941469424694346944469454694646947469484694946950469514695246953469544695546956469574695846959469604696146962469634696446965469664696746968469694697046971469724697346974469754697646977469784697946980469814698246983469844698546986469874698846989469904699146992469934699446995469964699746998469994700047001470024700347004470054700647007470084700947010470114701247013470144701547016470174701847019470204702147022470234702447025470264702747028470294703047031470324703347034470354703647037470384703947040470414704247043470444704547046470474704847049470504705147052470534705447055470564705747058470594706047061470624706347064470654706647067470684706947070470714707247073470744707547076470774707847079470804708147082470834708447085470864708747088470894709047091470924709347094470954709647097470984709947100471014710247103471044710547106471074710847109471104711147112471134711447115471164711747118471194712047121471224712347124471254712647127471284712947130471314713247133471344713547136471374713847139471404714147142471434714447145471464714747148471494715047151471524715347154471554715647157471584715947160471614716247163471644716547166471674716847169471704717147172471734717447175471764717747178471794718047181471824718347184471854718647187471884718947190471914719247193471944719547196471974719847199472004720147202472034720447205472064720747208472094721047211472124721347214472154721647217472184721947220472214722247223472244722547226472274722847229472304723147232472334723447235472364723747238472394724047241472424724347244472454724647247472484724947250472514725247253472544725547256472574725847259472604726147262472634726447265472664726747268472694727047271472724727347274472754727647277472784727947280472814728247283472844728547286472874728847289472904729147292472934729447295472964729747298472994730047301473024730347304473054730647307473084730947310473114731247313473144731547316473174731847319473204732147322473234732447325473264732747328473294733047331473324733347334473354733647337473384733947340473414734247343473444734547346473474734847349473504735147352473534735447355473564735747358473594736047361473624736347364473654736647367473684736947370473714737247373473744737547376473774737847379473804738147382473834738447385473864738747388473894739047391473924739347394473954739647397473984739947400474014740247403474044740547406474074740847409474104741147412474134741447415474164741747418474194742047421474224742347424474254742647427474284742947430474314743247433474344743547436474374743847439474404744147442474434744447445474464744747448474494745047451474524745347454474554745647457474584745947460474614746247463474644746547466474674746847469474704747147472474734747447475474764747747478474794748047481474824748347484474854748647487474884748947490474914749247493474944749547496474974749847499475004750147502475034750447505475064750747508475094751047511475124751347514475154751647517475184751947520475214752247523475244752547526475274752847529475304753147532475334753447535475364753747538475394754047541475424754347544475454754647547475484754947550475514755247553475544755547556475574755847559475604756147562475634756447565475664756747568475694757047571475724757347574475754757647577475784757947580475814758247583475844758547586475874758847589475904759147592475934759447595475964759747598475994760047601476024760347604476054760647607476084760947610476114761247613476144761547616476174761847619476204762147622476234762447625476264762747628476294763047631476324763347634476354763647637476384763947640476414764247643476444764547646476474764847649476504765147652476534765447655476564765747658476594766047661476624766347664476654766647667476684766947670476714767247673476744767547676476774767847679476804768147682476834768447685476864768747688476894769047691476924769347694476954769647697476984769947700477014770247703477044770547706477074770847709477104771147712477134771447715477164771747718477194772047721477224772347724477254772647727477284772947730477314773247733477344773547736477374773847739477404774147742477434774447745477464774747748477494775047751477524775347754477554775647757477584775947760477614776247763477644776547766477674776847769477704777147772477734777447775477764777747778477794778047781477824778347784477854778647787477884778947790477914779247793477944779547796477974779847799478004780147802478034780447805478064780747808478094781047811478124781347814478154781647817478184781947820478214782247823478244782547826478274782847829478304783147832478334783447835478364783747838478394784047841478424784347844478454784647847478484784947850478514785247853478544785547856478574785847859478604786147862478634786447865478664786747868478694787047871478724787347874478754787647877478784787947880478814788247883478844788547886478874788847889478904789147892478934789447895478964789747898478994790047901479024790347904479054790647907479084790947910479114791247913479144791547916479174791847919479204792147922479234792447925479264792747928479294793047931479324793347934479354793647937479384793947940479414794247943479444794547946479474794847949479504795147952479534795447955479564795747958479594796047961479624796347964479654796647967479684796947970479714797247973479744797547976479774797847979479804798147982479834798447985479864798747988479894799047991479924799347994479954799647997479984799948000480014800248003480044800548006480074800848009480104801148012480134801448015480164801748018480194802048021480224802348024480254802648027480284802948030480314803248033480344803548036480374803848039480404804148042480434804448045480464804748048480494805048051480524805348054480554805648057480584805948060480614806248063480644806548066480674806848069480704807148072480734807448075480764807748078480794808048081480824808348084480854808648087480884808948090480914809248093480944809548096480974809848099481004810148102481034810448105481064810748108481094811048111481124811348114481154811648117481184811948120481214812248123481244812548126481274812848129481304813148132481334813448135481364813748138481394814048141481424814348144481454814648147481484814948150481514815248153481544815548156481574815848159481604816148162481634816448165481664816748168481694817048171481724817348174481754817648177481784817948180481814818248183481844818548186481874818848189481904819148192481934819448195481964819748198481994820048201482024820348204482054820648207482084820948210482114821248213482144821548216482174821848219482204822148222482234822448225482264822748228482294823048231482324823348234482354823648237482384823948240482414824248243482444824548246482474824848249482504825148252482534825448255482564825748258482594826048261482624826348264482654826648267482684826948270482714827248273482744827548276482774827848279482804828148282482834828448285482864828748288482894829048291482924829348294482954829648297482984829948300483014830248303483044830548306483074830848309483104831148312483134831448315483164831748318483194832048321483224832348324483254832648327483284832948330483314833248333483344833548336483374833848339483404834148342483434834448345483464834748348483494835048351483524835348354483554835648357483584835948360483614836248363483644836548366483674836848369483704837148372483734837448375483764837748378483794838048381483824838348384483854838648387483884838948390483914839248393483944839548396483974839848399484004840148402484034840448405484064840748408484094841048411484124841348414484154841648417484184841948420484214842248423484244842548426484274842848429484304843148432484334843448435484364843748438484394844048441484424844348444484454844648447484484844948450484514845248453484544845548456484574845848459484604846148462484634846448465484664846748468484694847048471484724847348474484754847648477484784847948480484814848248483484844848548486484874848848489484904849148492484934849448495484964849748498484994850048501485024850348504485054850648507485084850948510485114851248513485144851548516485174851848519485204852148522485234852448525485264852748528485294853048531485324853348534485354853648537485384853948540485414854248543485444854548546485474854848549485504855148552485534855448555485564855748558485594856048561485624856348564485654856648567485684856948570485714857248573485744857548576485774857848579485804858148582485834858448585485864858748588485894859048591485924859348594485954859648597485984859948600486014860248603486044860548606486074860848609486104861148612486134861448615486164861748618486194862048621486224862348624486254862648627486284862948630486314863248633486344863548636486374863848639486404864148642486434864448645486464864748648486494865048651486524865348654486554865648657486584865948660486614866248663486644866548666486674866848669486704867148672486734867448675486764867748678486794868048681486824868348684486854868648687486884868948690486914869248693486944869548696486974869848699487004870148702487034870448705487064870748708487094871048711487124871348714487154871648717487184871948720487214872248723487244872548726487274872848729487304873148732487334873448735487364873748738487394874048741487424874348744487454874648747487484874948750487514875248753487544875548756487574875848759487604876148762487634876448765487664876748768487694877048771487724877348774487754877648777487784877948780487814878248783487844878548786487874878848789487904879148792487934879448795487964879748798487994880048801488024880348804488054880648807488084880948810488114881248813488144881548816488174881848819488204882148822488234882448825488264882748828488294883048831488324883348834488354883648837488384883948840488414884248843488444884548846488474884848849488504885148852488534885448855488564885748858488594886048861488624886348864488654886648867488684886948870488714887248873488744887548876488774887848879488804888148882488834888448885488864888748888488894889048891488924889348894488954889648897488984889948900489014890248903489044890548906489074890848909489104891148912489134891448915489164891748918489194892048921489224892348924489254892648927489284892948930489314893248933489344893548936489374893848939489404894148942489434894448945489464894748948489494895048951489524895348954489554895648957489584895948960489614896248963489644896548966489674896848969489704897148972489734897448975489764897748978489794898048981489824898348984489854898648987489884898948990489914899248993489944899548996489974899848999490004900149002490034900449005490064900749008490094901049011490124901349014490154901649017490184901949020490214902249023490244902549026490274902849029490304903149032490334903449035490364903749038490394904049041490424904349044490454904649047490484904949050490514905249053490544905549056490574905849059490604906149062490634906449065490664906749068490694907049071490724907349074490754907649077490784907949080490814908249083490844908549086490874908849089490904909149092490934909449095490964909749098490994910049101491024910349104491054910649107491084910949110491114911249113491144911549116491174911849119491204912149122491234912449125491264912749128491294913049131491324913349134491354913649137491384913949140491414914249143491444914549146491474914849149491504915149152491534915449155491564915749158491594916049161491624916349164491654916649167491684916949170491714917249173491744917549176491774917849179491804918149182491834918449185491864918749188491894919049191491924919349194491954919649197491984919949200492014920249203492044920549206492074920849209492104921149212492134921449215492164921749218492194922049221492224922349224492254922649227492284922949230492314923249233492344923549236492374923849239492404924149242492434924449245492464924749248492494925049251492524925349254492554925649257492584925949260492614926249263492644926549266492674926849269492704927149272492734927449275492764927749278492794928049281492824928349284492854928649287492884928949290492914929249293492944929549296492974929849299493004930149302493034930449305493064930749308493094931049311493124931349314493154931649317493184931949320493214932249323493244932549326493274932849329493304933149332493334933449335493364933749338493394934049341493424934349344493454934649347493484934949350493514935249353493544935549356493574935849359493604936149362493634936449365493664936749368493694937049371493724937349374493754937649377493784937949380493814938249383493844938549386493874938849389493904939149392493934939449395493964939749398493994940049401494024940349404494054940649407494084940949410494114941249413494144941549416494174941849419494204942149422494234942449425494264942749428494294943049431494324943349434494354943649437494384943949440494414944249443494444944549446494474944849449494504945149452494534945449455494564945749458494594946049461494624946349464494654946649467494684946949470494714947249473494744947549476494774947849479494804948149482494834948449485494864948749488494894949049491494924949349494494954949649497494984949949500495014950249503495044950549506495074950849509495104951149512495134951449515495164951749518495194952049521495224952349524495254952649527495284952949530495314953249533495344953549536495374953849539495404954149542495434954449545495464954749548495494955049551495524955349554495554955649557495584955949560495614956249563495644956549566495674956849569495704957149572495734957449575495764957749578495794958049581495824958349584495854958649587495884958949590495914959249593495944959549596495974959849599496004960149602496034960449605496064960749608496094961049611496124961349614496154961649617496184961949620496214962249623496244962549626496274962849629496304963149632496334963449635496364963749638496394964049641496424964349644496454964649647496484964949650496514965249653496544965549656496574965849659496604966149662496634966449665496664966749668496694967049671496724967349674496754967649677496784967949680496814968249683496844968549686496874968849689496904969149692496934969449695496964969749698496994970049701497024970349704497054970649707497084970949710497114971249713497144971549716497174971849719497204972149722497234972449725497264972749728497294973049731497324973349734497354973649737497384973949740497414974249743497444974549746497474974849749497504975149752497534975449755497564975749758497594976049761497624976349764497654976649767497684976949770497714977249773497744977549776497774977849779497804978149782497834978449785497864978749788497894979049791497924979349794497954979649797497984979949800498014980249803498044980549806498074980849809498104981149812498134981449815498164981749818498194982049821498224982349824498254982649827498284982949830498314983249833498344983549836498374983849839498404984149842498434984449845498464984749848498494985049851498524985349854498554985649857498584985949860498614986249863498644986549866498674986849869498704987149872498734987449875498764987749878498794988049881498824988349884498854988649887498884988949890498914989249893498944989549896498974989849899499004990149902499034990449905499064990749908499094991049911499124991349914499154991649917499184991949920499214992249923499244992549926499274992849929499304993149932499334993449935499364993749938499394994049941499424994349944499454994649947499484994949950499514995249953499544995549956499574995849959499604996149962499634996449965499664996749968499694997049971499724997349974499754997649977499784997949980499814998249983499844998549986499874998849989499904999149992499934999449995499964999749998499995000050001500025000350004500055000650007500085000950010500115001250013500145001550016500175001850019500205002150022500235002450025500265002750028500295003050031500325003350034500355003650037500385003950040500415004250043500445004550046500475004850049500505005150052500535005450055500565005750058500595006050061500625006350064500655006650067500685006950070500715007250073500745007550076500775007850079500805008150082500835008450085500865008750088500895009050091500925009350094500955009650097500985009950100501015010250103501045010550106501075010850109501105011150112501135011450115501165011750118501195012050121501225012350124501255012650127501285012950130501315013250133501345013550136501375013850139501405014150142501435014450145501465014750148501495015050151501525015350154501555015650157501585015950160501615016250163501645016550166501675016850169501705017150172501735017450175501765017750178501795018050181501825018350184501855018650187501885018950190501915019250193501945019550196501975019850199502005020150202502035020450205502065020750208502095021050211502125021350214502155021650217502185021950220502215022250223502245022550226502275022850229502305023150232502335023450235502365023750238502395024050241502425024350244502455024650247502485024950250502515025250253502545025550256502575025850259502605026150262502635026450265502665026750268502695027050271502725027350274502755027650277502785027950280502815028250283502845028550286502875028850289502905029150292502935029450295502965029750298502995030050301503025030350304503055030650307503085030950310503115031250313503145031550316503175031850319503205032150322503235032450325503265032750328503295033050331503325033350334503355033650337503385033950340503415034250343503445034550346503475034850349503505035150352503535035450355503565035750358503595036050361503625036350364503655036650367503685036950370503715037250373503745037550376503775037850379503805038150382503835038450385503865038750388503895039050391503925039350394503955039650397503985039950400504015040250403504045040550406504075040850409504105041150412504135041450415504165041750418504195042050421504225042350424504255042650427504285042950430504315043250433504345043550436504375043850439504405044150442504435044450445504465044750448504495045050451504525045350454504555045650457504585045950460504615046250463504645046550466504675046850469504705047150472504735047450475504765047750478504795048050481504825048350484504855048650487504885048950490504915049250493504945049550496504975049850499505005050150502505035050450505505065050750508505095051050511505125051350514505155051650517505185051950520505215052250523505245052550526505275052850529505305053150532505335053450535505365053750538505395054050541505425054350544505455054650547505485054950550505515055250553505545055550556505575055850559505605056150562505635056450565505665056750568505695057050571505725057350574505755057650577505785057950580505815058250583505845058550586505875058850589505905059150592505935059450595505965059750598505995060050601506025060350604506055060650607506085060950610506115061250613506145061550616506175061850619506205062150622506235062450625506265062750628506295063050631506325063350634506355063650637506385063950640506415064250643506445064550646506475064850649506505065150652506535065450655506565065750658506595066050661506625066350664506655066650667506685066950670506715067250673506745067550676506775067850679506805068150682506835068450685506865068750688506895069050691506925069350694506955069650697506985069950700507015070250703507045070550706507075070850709507105071150712507135071450715507165071750718507195072050721507225072350724507255072650727507285072950730507315073250733507345073550736507375073850739507405074150742507435074450745507465074750748507495075050751507525075350754507555075650757507585075950760507615076250763507645076550766507675076850769507705077150772507735077450775507765077750778507795078050781507825078350784507855078650787507885078950790507915079250793507945079550796507975079850799508005080150802508035080450805508065080750808508095081050811508125081350814508155081650817508185081950820508215082250823508245082550826508275082850829508305083150832508335083450835508365083750838508395084050841508425084350844508455084650847508485084950850508515085250853508545085550856508575085850859508605086150862508635086450865508665086750868508695087050871508725087350874508755087650877508785087950880508815088250883508845088550886508875088850889508905089150892508935089450895508965089750898508995090050901509025090350904509055090650907509085090950910509115091250913509145091550916509175091850919509205092150922509235092450925509265092750928509295093050931509325093350934509355093650937509385093950940509415094250943509445094550946509475094850949509505095150952509535095450955509565095750958509595096050961509625096350964509655096650967509685096950970509715097250973509745097550976509775097850979509805098150982509835098450985509865098750988509895099050991509925099350994509955099650997509985099951000510015100251003510045100551006510075100851009510105101151012510135101451015510165101751018510195102051021510225102351024510255102651027510285102951030510315103251033510345103551036510375103851039510405104151042510435104451045510465104751048510495105051051510525105351054510555105651057510585105951060510615106251063510645106551066510675106851069510705107151072510735107451075510765107751078510795108051081510825108351084510855108651087510885108951090510915109251093510945109551096510975109851099511005110151102511035110451105511065110751108511095111051111511125111351114511155111651117511185111951120511215112251123511245112551126511275112851129511305113151132511335113451135511365113751138511395114051141511425114351144511455114651147511485114951150511515115251153511545115551156511575115851159511605116151162511635116451165511665116751168511695117051171511725117351174511755117651177511785117951180511815118251183511845118551186511875118851189511905119151192511935119451195511965119751198511995120051201512025120351204512055120651207512085120951210512115121251213512145121551216512175121851219512205122151222512235122451225512265122751228512295123051231512325123351234512355123651237512385123951240512415124251243512445124551246512475124851249512505125151252512535125451255512565125751258512595126051261512625126351264512655126651267512685126951270512715127251273512745127551276512775127851279512805128151282512835128451285512865128751288512895129051291512925129351294512955129651297512985129951300513015130251303513045130551306513075130851309513105131151312513135131451315513165131751318513195132051321513225132351324513255132651327513285132951330513315133251333513345133551336513375133851339513405134151342513435134451345513465134751348513495135051351513525135351354513555135651357513585135951360513615136251363513645136551366513675136851369513705137151372513735137451375513765137751378513795138051381513825138351384513855138651387513885138951390513915139251393513945139551396513975139851399514005140151402514035140451405514065140751408514095141051411514125141351414514155141651417514185141951420514215142251423514245142551426514275142851429514305143151432514335143451435514365143751438514395144051441514425144351444514455144651447514485144951450514515145251453514545145551456514575145851459514605146151462514635146451465514665146751468514695147051471514725147351474514755147651477514785147951480514815148251483514845148551486514875148851489514905149151492514935149451495514965149751498514995150051501515025150351504515055150651507515085150951510515115151251513515145151551516515175151851519515205152151522515235152451525515265152751528515295153051531515325153351534515355153651537515385153951540515415154251543515445154551546515475154851549515505155151552515535155451555515565155751558515595156051561515625156351564515655156651567515685156951570515715157251573515745157551576515775157851579515805158151582515835158451585515865158751588515895159051591515925159351594515955159651597515985159951600516015160251603516045160551606516075160851609516105161151612516135161451615516165161751618516195162051621516225162351624516255162651627516285162951630516315163251633516345163551636516375163851639516405164151642516435164451645516465164751648516495165051651516525165351654516555165651657516585165951660516615166251663516645166551666516675166851669516705167151672516735167451675516765167751678516795168051681516825168351684516855168651687516885168951690516915169251693516945169551696516975169851699517005170151702517035170451705517065170751708517095171051711517125171351714517155171651717517185171951720517215172251723517245172551726517275172851729517305173151732517335173451735517365173751738517395174051741517425174351744517455174651747517485174951750517515175251753517545175551756517575175851759517605176151762517635176451765517665176751768517695177051771517725177351774517755177651777517785177951780517815178251783517845178551786517875178851789517905179151792517935179451795517965179751798517995180051801518025180351804518055180651807518085180951810518115181251813518145181551816518175181851819518205182151822518235182451825518265182751828518295183051831518325183351834518355183651837518385183951840518415184251843518445184551846518475184851849518505185151852518535185451855518565185751858518595186051861518625186351864518655186651867518685186951870518715187251873518745187551876518775187851879518805188151882518835188451885518865188751888518895189051891518925189351894518955189651897518985189951900519015190251903519045190551906519075190851909519105191151912519135191451915519165191751918519195192051921519225192351924519255192651927519285192951930519315193251933519345193551936519375193851939519405194151942519435194451945519465194751948519495195051951519525195351954519555195651957519585195951960519615196251963519645196551966519675196851969519705197151972519735197451975519765197751978519795198051981519825198351984519855198651987519885198951990519915199251993519945199551996519975199851999520005200152002520035200452005520065200752008520095201052011520125201352014520155201652017520185201952020520215202252023520245202552026520275202852029520305203152032520335203452035520365203752038520395204052041520425204352044520455204652047520485204952050520515205252053520545205552056520575205852059520605206152062520635206452065520665206752068520695207052071520725207352074520755207652077520785207952080520815208252083520845208552086520875208852089520905209152092520935209452095520965209752098520995210052101521025210352104521055210652107521085210952110521115211252113521145211552116521175211852119521205212152122521235212452125521265212752128521295213052131521325213352134521355213652137521385213952140521415214252143521445214552146521475214852149521505215152152521535215452155521565215752158521595216052161521625216352164521655216652167521685216952170521715217252173521745217552176521775217852179521805218152182521835218452185521865218752188521895219052191521925219352194521955219652197521985219952200522015220252203522045220552206522075220852209522105221152212522135221452215522165221752218522195222052221522225222352224522255222652227522285222952230522315223252233522345223552236522375223852239522405224152242522435224452245522465224752248522495225052251522525225352254522555225652257522585225952260522615226252263522645226552266522675226852269522705227152272522735227452275522765227752278522795228052281522825228352284522855228652287522885228952290522915229252293522945229552296522975229852299523005230152302523035230452305523065230752308523095231052311523125231352314523155231652317523185231952320523215232252323523245232552326523275232852329523305233152332523335233452335523365233752338523395234052341523425234352344523455234652347523485234952350523515235252353523545235552356523575235852359523605236152362523635236452365523665236752368523695237052371523725237352374523755237652377523785237952380523815238252383523845238552386523875238852389523905239152392523935239452395523965239752398523995240052401524025240352404524055240652407524085240952410524115241252413524145241552416524175241852419524205242152422524235242452425524265242752428524295243052431524325243352434524355243652437524385243952440524415244252443524445244552446524475244852449524505245152452524535245452455524565245752458524595246052461524625246352464524655246652467524685246952470524715247252473524745247552476524775247852479524805248152482524835248452485524865248752488524895249052491524925249352494524955249652497524985249952500525015250252503525045250552506525075250852509525105251152512525135251452515525165251752518525195252052521525225252352524525255252652527525285252952530525315253252533525345253552536525375253852539525405254152542525435254452545525465254752548525495255052551525525255352554525555255652557525585255952560525615256252563525645256552566525675256852569525705257152572525735257452575525765257752578525795258052581525825258352584525855258652587525885258952590525915259252593525945259552596525975259852599526005260152602526035260452605526065260752608526095261052611526125261352614526155261652617526185261952620526215262252623526245262552626526275262852629526305263152632526335263452635526365263752638526395264052641526425264352644526455264652647526485264952650526515265252653526545265552656526575265852659526605266152662526635266452665526665266752668526695267052671526725267352674526755267652677526785267952680526815268252683526845268552686526875268852689526905269152692526935269452695526965269752698526995270052701527025270352704527055270652707527085270952710527115271252713527145271552716527175271852719527205272152722527235272452725527265272752728527295273052731527325273352734527355273652737527385273952740527415274252743527445274552746527475274852749527505275152752527535275452755527565275752758527595276052761527625276352764527655276652767527685276952770527715277252773527745277552776527775277852779527805278152782527835278452785527865278752788527895279052791527925279352794527955279652797527985279952800528015280252803528045280552806528075280852809528105281152812528135281452815528165281752818528195282052821528225282352824528255282652827528285282952830528315283252833528345283552836528375283852839528405284152842528435284452845528465284752848528495285052851528525285352854528555285652857528585285952860528615286252863528645286552866528675286852869528705287152872528735287452875528765287752878528795288052881528825288352884528855288652887528885288952890528915289252893528945289552896528975289852899529005290152902529035290452905529065290752908529095291052911529125291352914529155291652917529185291952920529215292252923529245292552926529275292852929529305293152932529335293452935529365293752938529395294052941529425294352944529455294652947529485294952950529515295252953529545295552956529575295852959529605296152962529635296452965529665296752968529695297052971529725297352974529755297652977529785297952980529815298252983529845298552986529875298852989529905299152992529935299452995529965299752998529995300053001530025300353004530055300653007530085300953010530115301253013530145301553016530175301853019530205302153022530235302453025530265302753028530295303053031530325303353034530355303653037530385303953040530415304253043530445304553046530475304853049530505305153052530535305453055530565305753058530595306053061530625306353064530655306653067530685306953070530715307253073530745307553076530775307853079530805308153082530835308453085530865308753088530895309053091530925309353094530955309653097530985309953100531015310253103531045310553106531075310853109531105311153112531135311453115531165311753118531195312053121531225312353124531255312653127531285312953130531315313253133531345313553136531375313853139531405314153142531435314453145531465314753148531495315053151531525315353154531555315653157531585315953160531615316253163531645316553166531675316853169531705317153172531735317453175531765317753178531795318053181531825318353184531855318653187531885318953190531915319253193531945319553196531975319853199532005320153202532035320453205532065320753208532095321053211532125321353214532155321653217532185321953220532215322253223532245322553226532275322853229532305323153232532335323453235532365323753238532395324053241532425324353244532455324653247532485324953250532515325253253532545325553256532575325853259532605326153262532635326453265532665326753268532695327053271532725327353274532755327653277532785327953280532815328253283532845328553286532875328853289532905329153292532935329453295532965329753298532995330053301533025330353304533055330653307533085330953310533115331253313533145331553316533175331853319533205332153322533235332453325533265332753328533295333053331533325333353334533355333653337533385333953340533415334253343533445334553346533475334853349533505335153352533535335453355533565335753358533595336053361533625336353364533655336653367533685336953370533715337253373533745337553376533775337853379533805338153382533835338453385533865338753388533895339053391533925339353394533955339653397533985339953400534015340253403534045340553406534075340853409534105341153412534135341453415534165341753418534195342053421534225342353424534255342653427534285342953430534315343253433534345343553436534375343853439534405344153442534435344453445534465344753448534495345053451534525345353454534555345653457534585345953460534615346253463534645346553466534675346853469534705347153472534735347453475534765347753478534795348053481534825348353484534855348653487534885348953490534915349253493534945349553496534975349853499535005350153502535035350453505535065350753508535095351053511535125351353514535155351653517535185351953520535215352253523535245352553526535275352853529535305353153532535335353453535535365353753538535395354053541535425354353544535455354653547535485354953550535515355253553535545355553556535575355853559535605356153562535635356453565535665356753568535695357053571535725357353574535755357653577535785357953580535815358253583535845358553586535875358853589535905359153592535935359453595535965359753598535995360053601536025360353604536055360653607536085360953610536115361253613536145361553616536175361853619536205362153622536235362453625536265362753628536295363053631536325363353634536355363653637536385363953640536415364253643536445364553646536475364853649536505365153652536535365453655536565365753658536595366053661536625366353664536655366653667536685366953670536715367253673536745367553676536775367853679536805368153682536835368453685536865368753688536895369053691536925369353694536955369653697536985369953700537015370253703537045370553706537075370853709537105371153712537135371453715537165371753718537195372053721537225372353724537255372653727537285372953730537315373253733537345373553736537375373853739537405374153742537435374453745537465374753748537495375053751537525375353754537555375653757537585375953760537615376253763537645376553766537675376853769537705377153772537735377453775537765377753778537795378053781537825378353784537855378653787537885378953790537915379253793537945379553796537975379853799538005380153802538035380453805538065380753808538095381053811538125381353814538155381653817538185381953820538215382253823538245382553826538275382853829538305383153832538335383453835538365383753838538395384053841538425384353844538455384653847538485384953850538515385253853538545385553856538575385853859538605386153862538635386453865538665386753868538695387053871538725387353874538755387653877538785387953880538815388253883538845388553886538875388853889538905389153892538935389453895538965389753898538995390053901539025390353904539055390653907539085390953910539115391253913539145391553916539175391853919539205392153922539235392453925539265392753928539295393053931539325393353934539355393653937539385393953940539415394253943539445394553946539475394853949539505395153952539535395453955539565395753958539595396053961539625396353964539655396653967539685396953970539715397253973539745397553976539775397853979539805398153982539835398453985539865398753988539895399053991539925399353994539955399653997539985399954000540015400254003540045400554006540075400854009540105401154012540135401454015540165401754018540195402054021540225402354024540255402654027540285402954030540315403254033540345403554036540375403854039540405404154042540435404454045540465404754048540495405054051540525405354054540555405654057540585405954060540615406254063540645406554066540675406854069540705407154072540735407454075540765407754078540795408054081540825408354084540855408654087540885408954090540915409254093540945409554096540975409854099541005410154102541035410454105541065410754108541095411054111541125411354114541155411654117541185411954120541215412254123541245412554126541275412854129541305413154132541335413454135541365413754138541395414054141541425414354144541455414654147541485414954150541515415254153541545415554156541575415854159541605416154162541635416454165541665416754168541695417054171541725417354174541755417654177541785417954180541815418254183541845418554186541875418854189541905419154192541935419454195541965419754198541995420054201542025420354204542055420654207542085420954210542115421254213542145421554216542175421854219542205422154222542235422454225542265422754228542295423054231542325423354234542355423654237542385423954240542415424254243542445424554246542475424854249542505425154252542535425454255542565425754258542595426054261542625426354264542655426654267542685426954270542715427254273542745427554276542775427854279542805428154282542835428454285542865428754288542895429054291542925429354294542955429654297542985429954300543015430254303543045430554306543075430854309543105431154312543135431454315543165431754318543195432054321543225432354324543255432654327543285432954330543315433254333543345433554336543375433854339543405434154342543435434454345543465434754348543495435054351543525435354354543555435654357543585435954360543615436254363543645436554366543675436854369543705437154372543735437454375543765437754378543795438054381543825438354384543855438654387543885438954390543915439254393543945439554396543975439854399544005440154402544035440454405544065440754408544095441054411544125441354414544155441654417544185441954420544215442254423544245442554426544275442854429544305443154432544335443454435544365443754438544395444054441544425444354444544455444654447544485444954450544515445254453544545445554456544575445854459544605446154462544635446454465544665446754468544695447054471544725447354474544755447654477544785447954480544815448254483544845448554486544875448854489544905449154492544935449454495544965449754498544995450054501545025450354504545055450654507545085450954510545115451254513545145451554516545175451854519545205452154522545235452454525545265452754528545295453054531545325453354534545355453654537545385453954540545415454254543545445454554546545475454854549545505455154552545535455454555545565455754558545595456054561545625456354564545655456654567545685456954570545715457254573545745457554576545775457854579545805458154582545835458454585545865458754588545895459054591545925459354594545955459654597545985459954600546015460254603546045460554606546075460854609546105461154612546135461454615546165461754618546195462054621546225462354624546255462654627546285462954630546315463254633546345463554636546375463854639546405464154642546435464454645546465464754648546495465054651546525465354654546555465654657546585465954660546615466254663546645466554666546675466854669546705467154672546735467454675546765467754678546795468054681546825468354684546855468654687546885468954690546915469254693546945469554696546975469854699547005470154702547035470454705547065470754708547095471054711547125471354714547155471654717547185471954720547215472254723547245472554726547275472854729547305473154732547335473454735547365473754738547395474054741547425474354744547455474654747547485474954750547515475254753547545475554756547575475854759547605476154762547635476454765547665476754768547695477054771547725477354774547755477654777547785477954780547815478254783547845478554786547875478854789547905479154792547935479454795547965479754798547995480054801548025480354804548055480654807548085480954810548115481254813548145481554816548175481854819548205482154822548235482454825548265482754828548295483054831548325483354834548355483654837548385483954840548415484254843548445484554846548475484854849548505485154852548535485454855548565485754858548595486054861548625486354864548655486654867548685486954870548715487254873548745487554876548775487854879548805488154882548835488454885548865488754888548895489054891548925489354894548955489654897548985489954900549015490254903549045490554906549075490854909549105491154912549135491454915549165491754918549195492054921549225492354924549255492654927549285492954930549315493254933549345493554936549375493854939549405494154942549435494454945549465494754948549495495054951549525495354954549555495654957549585495954960549615496254963549645496554966549675496854969549705497154972549735497454975549765497754978549795498054981549825498354984549855498654987549885498954990549915499254993549945499554996549975499854999550005500155002550035500455005550065500755008550095501055011550125501355014550155501655017550185501955020550215502255023550245502555026550275502855029550305503155032550335503455035550365503755038550395504055041550425504355044550455504655047550485504955050550515505255053550545505555056550575505855059550605506155062550635506455065550665506755068550695507055071550725507355074550755507655077550785507955080550815508255083550845508555086550875508855089550905509155092550935509455095550965509755098550995510055101551025510355104551055510655107551085510955110551115511255113551145511555116551175511855119551205512155122551235512455125551265512755128551295513055131551325513355134551355513655137551385513955140551415514255143551445514555146551475514855149551505515155152551535515455155551565515755158551595516055161551625516355164551655516655167551685516955170551715517255173551745517555176551775517855179551805518155182551835518455185551865518755188551895519055191551925519355194551955519655197551985519955200552015520255203552045520555206552075520855209552105521155212552135521455215552165521755218552195522055221552225522355224552255522655227552285522955230552315523255233552345523555236552375523855239552405524155242552435524455245552465524755248552495525055251552525525355254552555525655257552585525955260552615526255263552645526555266552675526855269552705527155272552735527455275552765527755278552795528055281552825528355284552855528655287552885528955290552915529255293552945529555296552975529855299553005530155302553035530455305553065530755308553095531055311553125531355314553155531655317553185531955320553215532255323553245532555326553275532855329553305533155332553335533455335553365533755338553395534055341553425534355344553455534655347553485534955350553515535255353553545535555356553575535855359553605536155362553635536455365553665536755368553695537055371553725537355374553755537655377553785537955380553815538255383553845538555386553875538855389553905539155392553935539455395553965539755398553995540055401554025540355404554055540655407554085540955410554115541255413554145541555416554175541855419554205542155422554235542455425554265542755428554295543055431554325543355434554355543655437554385543955440554415544255443554445544555446554475544855449554505545155452554535545455455554565545755458554595546055461554625546355464554655546655467554685546955470554715547255473554745547555476554775547855479554805548155482554835548455485554865548755488554895549055491554925549355494554955549655497554985549955500555015550255503555045550555506555075550855509555105551155512555135551455515555165551755518555195552055521555225552355524555255552655527555285552955530555315553255533555345553555536555375553855539555405554155542555435554455545555465554755548555495555055551555525555355554555555555655557555585555955560555615556255563555645556555566555675556855569555705557155572555735557455575555765557755578555795558055581555825558355584555855558655587555885558955590555915559255593555945559555596555975559855599556005560155602556035560455605556065560755608556095561055611556125561355614556155561655617556185561955620556215562255623556245562555626556275562855629556305563155632556335563455635556365563755638556395564055641556425564355644556455564655647556485564955650556515565255653556545565555656556575565855659556605566155662556635566455665556665566755668556695567055671556725567355674556755567655677556785567955680556815568255683556845568555686556875568855689556905569155692556935569455695556965569755698556995570055701557025570355704557055570655707557085570955710557115571255713557145571555716557175571855719557205572155722557235572455725557265572755728557295573055731557325573355734557355573655737557385573955740557415574255743557445574555746557475574855749557505575155752557535575455755557565575755758557595576055761557625576355764557655576655767557685576955770557715577255773557745577555776557775577855779557805578155782557835578455785557865578755788557895579055791557925579355794557955579655797557985579955800558015580255803558045580555806558075580855809558105581155812558135581455815558165581755818558195582055821558225582355824558255582655827558285582955830558315583255833558345583555836558375583855839558405584155842558435584455845558465584755848558495585055851558525585355854558555585655857558585585955860558615586255863558645586555866558675586855869558705587155872558735587455875558765587755878558795588055881558825588355884558855588655887558885588955890558915589255893558945589555896558975589855899559005590155902559035590455905559065590755908559095591055911559125591355914559155591655917559185591955920559215592255923559245592555926559275592855929559305593155932559335593455935559365593755938559395594055941559425594355944559455594655947559485594955950559515595255953559545595555956559575595855959559605596155962559635596455965559665596755968559695597055971559725597355974559755597655977559785597955980559815598255983559845598555986559875598855989559905599155992559935599455995559965599755998559995600056001560025600356004560055600656007560085600956010560115601256013560145601556016560175601856019560205602156022560235602456025560265602756028560295603056031560325603356034560355603656037560385603956040560415604256043560445604556046560475604856049560505605156052560535605456055560565605756058560595606056061560625606356064560655606656067560685606956070560715607256073560745607556076560775607856079560805608156082560835608456085560865608756088560895609056091560925609356094560955609656097560985609956100561015610256103561045610556106561075610856109561105611156112561135611456115561165611756118561195612056121561225612356124561255612656127561285612956130561315613256133561345613556136561375613856139561405614156142561435614456145561465614756148561495615056151561525615356154561555615656157561585615956160561615616256163561645616556166561675616856169561705617156172561735617456175561765617756178561795618056181561825618356184561855618656187561885618956190561915619256193561945619556196561975619856199562005620156202562035620456205562065620756208562095621056211562125621356214562155621656217562185621956220562215622256223562245622556226562275622856229562305623156232562335623456235562365623756238562395624056241562425624356244562455624656247562485624956250562515625256253562545625556256562575625856259562605626156262562635626456265562665626756268562695627056271562725627356274562755627656277562785627956280562815628256283562845628556286562875628856289562905629156292562935629456295562965629756298562995630056301563025630356304563055630656307563085630956310563115631256313563145631556316563175631856319563205632156322563235632456325563265632756328563295633056331563325633356334563355633656337563385633956340563415634256343563445634556346563475634856349563505635156352563535635456355563565635756358563595636056361563625636356364563655636656367563685636956370563715637256373563745637556376563775637856379563805638156382563835638456385563865638756388563895639056391563925639356394563955639656397563985639956400564015640256403564045640556406564075640856409564105641156412564135641456415564165641756418564195642056421564225642356424564255642656427564285642956430564315643256433564345643556436564375643856439564405644156442564435644456445564465644756448564495645056451564525645356454564555645656457564585645956460564615646256463564645646556466564675646856469564705647156472564735647456475564765647756478564795648056481564825648356484564855648656487564885648956490564915649256493564945649556496564975649856499565005650156502565035650456505565065650756508565095651056511565125651356514565155651656517565185651956520565215652256523565245652556526565275652856529565305653156532565335653456535565365653756538565395654056541565425654356544565455654656547565485654956550565515655256553565545655556556565575655856559565605656156562565635656456565565665656756568565695657056571565725657356574565755657656577565785657956580565815658256583565845658556586565875658856589565905659156592565935659456595565965659756598565995660056601566025660356604566055660656607566085660956610566115661256613566145661556616566175661856619566205662156622566235662456625566265662756628566295663056631566325663356634566355663656637566385663956640566415664256643566445664556646566475664856649566505665156652566535665456655566565665756658566595666056661566625666356664566655666656667566685666956670566715667256673566745667556676566775667856679566805668156682566835668456685566865668756688566895669056691566925669356694566955669656697566985669956700567015670256703567045670556706567075670856709567105671156712567135671456715567165671756718567195672056721567225672356724567255672656727567285672956730567315673256733567345673556736567375673856739567405674156742567435674456745567465674756748567495675056751567525675356754567555675656757567585675956760567615676256763567645676556766567675676856769567705677156772567735677456775567765677756778567795678056781567825678356784567855678656787567885678956790567915679256793567945679556796567975679856799568005680156802568035680456805568065680756808568095681056811568125681356814568155681656817568185681956820568215682256823568245682556826568275682856829568305683156832568335683456835568365683756838568395684056841568425684356844568455684656847568485684956850568515685256853568545685556856568575685856859568605686156862568635686456865568665686756868568695687056871568725687356874568755687656877568785687956880568815688256883568845688556886568875688856889568905689156892568935689456895568965689756898568995690056901569025690356904569055690656907569085690956910569115691256913569145691556916569175691856919569205692156922569235692456925569265692756928569295693056931569325693356934569355693656937569385693956940569415694256943569445694556946569475694856949569505695156952569535695456955569565695756958569595696056961569625696356964569655696656967569685696956970569715697256973569745697556976569775697856979569805698156982569835698456985569865698756988569895699056991569925699356994569955699656997569985699957000570015700257003570045700557006570075700857009570105701157012570135701457015570165701757018570195702057021570225702357024570255702657027570285702957030570315703257033570345703557036570375703857039570405704157042570435704457045570465704757048570495705057051570525705357054570555705657057570585705957060570615706257063570645706557066570675706857069570705707157072570735707457075570765707757078570795708057081570825708357084570855708657087570885708957090570915709257093570945709557096570975709857099571005710157102571035710457105571065710757108571095711057111571125711357114571155711657117571185711957120571215712257123571245712557126571275712857129571305713157132571335713457135571365713757138571395714057141571425714357144571455714657147571485714957150571515715257153571545715557156571575715857159571605716157162571635716457165571665716757168571695717057171571725717357174571755717657177571785717957180571815718257183571845718557186571875718857189571905719157192571935719457195571965719757198571995720057201572025720357204572055720657207572085720957210572115721257213572145721557216572175721857219572205722157222572235722457225572265722757228572295723057231572325723357234572355723657237572385723957240572415724257243572445724557246572475724857249572505725157252572535725457255572565725757258572595726057261572625726357264572655726657267572685726957270572715727257273572745727557276572775727857279572805728157282572835728457285572865728757288572895729057291572925729357294572955729657297572985729957300573015730257303573045730557306573075730857309573105731157312573135731457315573165731757318573195732057321573225732357324573255732657327573285732957330573315733257333573345733557336573375733857339573405734157342573435734457345573465734757348573495735057351573525735357354573555735657357573585735957360573615736257363573645736557366573675736857369573705737157372573735737457375573765737757378573795738057381573825738357384573855738657387573885738957390573915739257393573945739557396573975739857399574005740157402574035740457405574065740757408574095741057411574125741357414574155741657417574185741957420574215742257423574245742557426574275742857429574305743157432574335743457435574365743757438574395744057441574425744357444574455744657447574485744957450574515745257453574545745557456574575745857459574605746157462574635746457465574665746757468574695747057471574725747357474574755747657477574785747957480574815748257483574845748557486574875748857489574905749157492574935749457495574965749757498574995750057501575025750357504575055750657507575085750957510575115751257513575145751557516575175751857519575205752157522575235752457525575265752757528575295753057531575325753357534575355753657537575385753957540575415754257543575445754557546575475754857549575505755157552575535755457555575565755757558575595756057561575625756357564575655756657567575685756957570575715757257573575745757557576575775757857579575805758157582575835758457585575865758757588575895759057591575925759357594575955759657597575985759957600576015760257603576045760557606576075760857609576105761157612576135761457615576165761757618576195762057621576225762357624576255762657627576285762957630576315763257633576345763557636576375763857639576405764157642576435764457645576465764757648576495765057651576525765357654576555765657657576585765957660576615766257663576645766557666576675766857669576705767157672576735767457675576765767757678576795768057681576825768357684576855768657687576885768957690576915769257693576945769557696576975769857699577005770157702577035770457705577065770757708577095771057711577125771357714577155771657717577185771957720577215772257723577245772557726577275772857729577305773157732577335773457735577365773757738577395774057741577425774357744577455774657747577485774957750577515775257753577545775557756577575775857759577605776157762577635776457765577665776757768577695777057771577725777357774577755777657777577785777957780577815778257783577845778557786577875778857789577905779157792577935779457795577965779757798577995780057801578025780357804578055780657807578085780957810578115781257813578145781557816578175781857819578205782157822578235782457825578265782757828578295783057831578325783357834578355783657837578385783957840578415784257843578445784557846578475784857849578505785157852578535785457855578565785757858578595786057861578625786357864578655786657867578685786957870578715787257873578745787557876578775787857879578805788157882578835788457885578865788757888578895789057891578925789357894578955789657897578985789957900579015790257903579045790557906579075790857909579105791157912579135791457915579165791757918579195792057921579225792357924579255792657927579285792957930579315793257933579345793557936579375793857939579405794157942579435794457945579465794757948579495795057951579525795357954579555795657957579585795957960579615796257963579645796557966579675796857969579705797157972579735797457975579765797757978579795798057981579825798357984579855798657987579885798957990579915799257993579945799557996579975799857999580005800158002580035800458005580065800758008580095801058011580125801358014580155801658017580185801958020580215802258023580245802558026580275802858029580305803158032580335803458035580365803758038580395804058041580425804358044580455804658047580485804958050580515805258053580545805558056580575805858059580605806158062580635806458065580665806758068580695807058071580725807358074580755807658077580785807958080580815808258083580845808558086580875808858089580905809158092580935809458095580965809758098580995810058101581025810358104581055810658107581085810958110581115811258113581145811558116581175811858119581205812158122581235812458125581265812758128581295813058131581325813358134581355813658137581385813958140581415814258143581445814558146581475814858149581505815158152581535815458155581565815758158581595816058161581625816358164581655816658167581685816958170581715817258173581745817558176581775817858179581805818158182581835818458185581865818758188581895819058191581925819358194581955819658197581985819958200582015820258203582045820558206582075820858209582105821158212582135821458215582165821758218582195822058221582225822358224582255822658227582285822958230582315823258233582345823558236582375823858239582405824158242582435824458245582465824758248582495825058251582525825358254582555825658257582585825958260582615826258263582645826558266582675826858269582705827158272582735827458275582765827758278582795828058281582825828358284582855828658287582885828958290582915829258293582945829558296582975829858299583005830158302583035830458305583065830758308583095831058311583125831358314583155831658317583185831958320583215832258323583245832558326583275832858329583305833158332583335833458335583365833758338583395834058341583425834358344583455834658347583485834958350583515835258353583545835558356583575835858359583605836158362583635836458365583665836758368583695837058371583725837358374583755837658377583785837958380583815838258383583845838558386583875838858389583905839158392583935839458395583965839758398583995840058401584025840358404584055840658407584085840958410584115841258413584145841558416584175841858419584205842158422584235842458425584265842758428584295843058431584325843358434584355843658437584385843958440584415844258443584445844558446584475844858449584505845158452584535845458455584565845758458584595846058461584625846358464584655846658467584685846958470584715847258473584745847558476584775847858479584805848158482584835848458485584865848758488584895849058491584925849358494584955849658497584985849958500585015850258503585045850558506585075850858509585105851158512585135851458515585165851758518585195852058521585225852358524585255852658527585285852958530585315853258533585345853558536585375853858539585405854158542585435854458545585465854758548585495855058551585525855358554585555855658557585585855958560585615856258563585645856558566585675856858569585705857158572585735857458575585765857758578585795858058581585825858358584585855858658587585885858958590585915859258593585945859558596585975859858599586005860158602586035860458605586065860758608586095861058611586125861358614586155861658617586185861958620586215862258623586245862558626586275862858629586305863158632586335863458635586365863758638586395864058641586425864358644586455864658647586485864958650586515865258653586545865558656586575865858659586605866158662586635866458665586665866758668586695867058671586725867358674586755867658677586785867958680586815868258683586845868558686586875868858689586905869158692586935869458695586965869758698586995870058701587025870358704587055870658707587085870958710587115871258713587145871558716587175871858719587205872158722587235872458725587265872758728587295873058731587325873358734587355873658737587385873958740587415874258743587445874558746587475874858749587505875158752587535875458755587565875758758587595876058761587625876358764587655876658767587685876958770587715877258773587745877558776587775877858779587805878158782587835878458785587865878758788587895879058791587925879358794587955879658797587985879958800588015880258803588045880558806588075880858809588105881158812588135881458815588165881758818588195882058821588225882358824588255882658827588285882958830588315883258833588345883558836588375883858839588405884158842588435884458845588465884758848588495885058851588525885358854588555885658857588585885958860588615886258863588645886558866588675886858869588705887158872588735887458875588765887758878588795888058881588825888358884588855888658887588885888958890588915889258893588945889558896588975889858899589005890158902589035890458905589065890758908589095891058911589125891358914589155891658917589185891958920589215892258923589245892558926589275892858929589305893158932589335893458935589365893758938589395894058941589425894358944589455894658947589485894958950589515895258953589545895558956589575895858959589605896158962589635896458965589665896758968589695897058971589725897358974589755897658977589785897958980589815898258983589845898558986589875898858989589905899158992589935899458995589965899758998589995900059001590025900359004590055900659007590085900959010590115901259013590145901559016590175901859019590205902159022590235902459025590265902759028590295903059031590325903359034590355903659037590385903959040590415904259043590445904559046590475904859049590505905159052590535905459055590565905759058590595906059061590625906359064590655906659067590685906959070590715907259073590745907559076590775907859079590805908159082590835908459085590865908759088590895909059091590925909359094590955909659097590985909959100591015910259103591045910559106591075910859109591105911159112591135911459115591165911759118591195912059121591225912359124591255912659127591285912959130591315913259133591345913559136591375913859139591405914159142591435914459145591465914759148591495915059151591525915359154591555915659157591585915959160591615916259163591645916559166591675916859169591705917159172591735917459175591765917759178591795918059181591825918359184591855918659187591885918959190591915919259193591945919559196591975919859199592005920159202592035920459205592065920759208592095921059211592125921359214592155921659217592185921959220592215922259223592245922559226592275922859229592305923159232592335923459235592365923759238592395924059241592425924359244592455924659247592485924959250592515925259253592545925559256592575925859259592605926159262592635926459265592665926759268592695927059271592725927359274592755927659277592785927959280592815928259283592845928559286592875928859289592905929159292592935929459295592965929759298592995930059301593025930359304593055930659307593085930959310593115931259313593145931559316593175931859319593205932159322593235932459325593265932759328593295933059331593325933359334593355933659337593385933959340593415934259343593445934559346593475934859349593505935159352593535935459355593565935759358593595936059361593625936359364593655936659367593685936959370593715937259373593745937559376593775937859379593805938159382593835938459385593865938759388593895939059391593925939359394593955939659397593985939959400594015940259403594045940559406594075940859409594105941159412594135941459415594165941759418594195942059421594225942359424594255942659427594285942959430594315943259433594345943559436594375943859439594405944159442594435944459445594465944759448594495945059451594525945359454594555945659457594585945959460594615946259463594645946559466594675946859469594705947159472594735947459475594765947759478594795948059481594825948359484594855948659487594885948959490594915949259493594945949559496594975949859499595005950159502595035950459505595065950759508595095951059511595125951359514595155951659517595185951959520595215952259523595245952559526595275952859529595305953159532595335953459535595365953759538595395954059541595425954359544595455954659547595485954959550595515955259553595545955559556595575955859559595605956159562595635956459565595665956759568595695957059571595725957359574595755957659577595785957959580595815958259583595845958559586595875958859589595905959159592595935959459595595965959759598595995960059601596025960359604596055960659607596085960959610596115961259613596145961559616596175961859619596205962159622596235962459625596265962759628596295963059631596325963359634596355963659637596385963959640596415964259643596445964559646596475964859649596505965159652596535965459655596565965759658596595966059661596625966359664596655966659667596685966959670596715967259673596745967559676596775967859679596805968159682596835968459685596865968759688596895969059691596925969359694596955969659697596985969959700597015970259703597045970559706597075970859709597105971159712597135971459715597165971759718597195972059721597225972359724597255972659727597285972959730597315973259733597345973559736597375973859739597405974159742597435974459745597465974759748597495975059751597525975359754597555975659757597585975959760597615976259763597645976559766597675976859769597705977159772597735977459775597765977759778597795978059781597825978359784597855978659787597885978959790597915979259793597945979559796597975979859799598005980159802598035980459805598065980759808598095981059811598125981359814598155981659817598185981959820598215982259823598245982559826598275982859829598305983159832598335983459835598365983759838598395984059841598425984359844598455984659847598485984959850598515985259853598545985559856598575985859859598605986159862598635986459865598665986759868598695987059871598725987359874598755987659877598785987959880598815988259883598845988559886598875988859889598905989159892598935989459895598965989759898598995990059901599025990359904599055990659907599085990959910599115991259913599145991559916599175991859919599205992159922599235992459925599265992759928599295993059931599325993359934599355993659937599385993959940599415994259943599445994559946599475994859949599505995159952599535995459955599565995759958599595996059961599625996359964599655996659967599685996959970599715997259973599745997559976599775997859979599805998159982599835998459985599865998759988599895999059991599925999359994599955999659997599985999960000600016000260003600046000560006600076000860009600106001160012600136001460015600166001760018600196002060021600226002360024600256002660027600286002960030600316003260033600346003560036600376003860039600406004160042600436004460045600466004760048600496005060051600526005360054600556005660057600586005960060600616006260063600646006560066600676006860069600706007160072600736007460075600766007760078600796008060081600826008360084600856008660087600886008960090600916009260093600946009560096600976009860099601006010160102601036010460105601066010760108601096011060111601126011360114601156011660117601186011960120601216012260123601246012560126601276012860129601306013160132601336013460135601366013760138601396014060141601426014360144601456014660147601486014960150601516015260153601546015560156601576015860159601606016160162601636016460165601666016760168601696017060171601726017360174601756017660177601786017960180601816018260183601846018560186601876018860189601906019160192601936019460195601966019760198601996020060201602026020360204602056020660207602086020960210602116021260213602146021560216602176021860219602206022160222602236022460225602266022760228602296023060231602326023360234602356023660237602386023960240602416024260243602446024560246602476024860249602506025160252602536025460255602566025760258602596026060261602626026360264602656026660267602686026960270602716027260273602746027560276602776027860279602806028160282602836028460285602866028760288602896029060291602926029360294602956029660297602986029960300603016030260303603046030560306603076030860309603106031160312603136031460315603166031760318603196032060321603226032360324603256032660327603286032960330603316033260333603346033560336603376033860339603406034160342603436034460345603466034760348603496035060351603526035360354603556035660357603586035960360603616036260363603646036560366603676036860369603706037160372603736037460375603766037760378603796038060381603826038360384603856038660387603886038960390603916039260393603946039560396603976039860399604006040160402604036040460405604066040760408604096041060411604126041360414604156041660417604186041960420604216042260423604246042560426604276042860429604306043160432604336043460435604366043760438604396044060441604426044360444604456044660447604486044960450604516045260453604546045560456604576045860459604606046160462604636046460465604666046760468604696047060471604726047360474604756047660477604786047960480604816048260483604846048560486604876048860489604906049160492604936049460495604966049760498604996050060501605026050360504605056050660507605086050960510605116051260513605146051560516605176051860519605206052160522605236052460525605266052760528605296053060531605326053360534605356053660537605386053960540605416054260543605446054560546605476054860549605506055160552605536055460555605566055760558605596056060561605626056360564605656056660567605686056960570605716057260573605746057560576605776057860579605806058160582605836058460585605866058760588605896059060591605926059360594605956059660597605986059960600606016060260603606046060560606606076060860609606106061160612606136061460615606166061760618606196062060621606226062360624606256062660627606286062960630606316063260633606346063560636606376063860639606406064160642606436064460645606466064760648606496065060651606526065360654606556065660657606586065960660606616066260663606646066560666606676066860669606706067160672606736067460675606766067760678606796068060681606826068360684606856068660687606886068960690606916069260693606946069560696606976069860699607006070160702607036070460705607066070760708607096071060711607126071360714607156071660717607186071960720607216072260723607246072560726607276072860729607306073160732607336073460735607366073760738607396074060741607426074360744607456074660747607486074960750607516075260753607546075560756607576075860759607606076160762607636076460765607666076760768607696077060771607726077360774607756077660777607786077960780607816078260783607846078560786607876078860789607906079160792607936079460795607966079760798607996080060801608026080360804608056080660807608086080960810608116081260813608146081560816608176081860819608206082160822608236082460825608266082760828608296083060831608326083360834608356083660837608386083960840608416084260843608446084560846608476084860849608506085160852608536085460855608566085760858608596086060861608626086360864608656086660867608686086960870608716087260873608746087560876608776087860879608806088160882608836088460885608866088760888608896089060891608926089360894608956089660897608986089960900609016090260903609046090560906609076090860909609106091160912609136091460915609166091760918609196092060921609226092360924609256092660927609286092960930609316093260933609346093560936609376093860939609406094160942609436094460945609466094760948609496095060951609526095360954609556095660957609586095960960609616096260963609646096560966609676096860969609706097160972609736097460975609766097760978609796098060981609826098360984609856098660987609886098960990609916099260993609946099560996609976099860999610006100161002610036100461005610066100761008610096101061011610126101361014610156101661017610186101961020610216102261023610246102561026610276102861029610306103161032610336103461035610366103761038610396104061041610426104361044610456104661047610486104961050610516105261053610546105561056610576105861059610606106161062610636106461065610666106761068610696107061071610726107361074610756107661077610786107961080610816108261083610846108561086610876108861089610906109161092610936109461095610966109761098610996110061101611026110361104611056110661107611086110961110611116111261113611146111561116611176111861119611206112161122611236112461125611266112761128611296113061131611326113361134611356113661137611386113961140611416114261143611446114561146611476114861149611506115161152611536115461155611566115761158611596116061161611626116361164611656116661167611686116961170611716117261173611746117561176611776117861179611806118161182611836118461185611866118761188611896119061191611926119361194611956119661197611986119961200612016120261203612046120561206612076120861209612106121161212612136121461215612166121761218612196122061221612226122361224612256122661227612286122961230612316123261233612346123561236612376123861239612406124161242612436124461245612466124761248612496125061251612526125361254612556125661257612586125961260612616126261263612646126561266612676126861269612706127161272612736127461275612766127761278612796128061281612826128361284612856128661287612886128961290612916129261293612946129561296612976129861299613006130161302613036130461305613066130761308613096131061311613126131361314613156131661317613186131961320613216132261323613246132561326613276132861329613306133161332613336133461335613366133761338613396134061341613426134361344613456134661347613486134961350613516135261353613546135561356613576135861359613606136161362613636136461365613666136761368613696137061371613726137361374613756137661377613786137961380613816138261383613846138561386613876138861389613906139161392613936139461395613966139761398613996140061401614026140361404614056140661407614086140961410614116141261413614146141561416614176141861419614206142161422614236142461425614266142761428614296143061431614326143361434614356143661437614386143961440614416144261443614446144561446614476144861449614506145161452614536145461455614566145761458614596146061461614626146361464614656146661467614686146961470614716147261473614746147561476614776147861479614806148161482614836148461485614866148761488614896149061491614926149361494614956149661497614986149961500615016150261503615046150561506615076150861509615106151161512615136151461515615166151761518615196152061521615226152361524615256152661527615286152961530615316153261533615346153561536615376153861539615406154161542615436154461545615466154761548615496155061551615526155361554615556155661557615586155961560615616156261563615646156561566615676156861569615706157161572615736157461575615766157761578615796158061581615826158361584615856158661587615886158961590615916159261593615946159561596615976159861599616006160161602616036160461605616066160761608616096161061611616126161361614616156161661617616186161961620616216162261623616246162561626616276162861629616306163161632616336163461635616366163761638616396164061641616426164361644616456164661647616486164961650616516165261653616546165561656616576165861659616606166161662616636166461665616666166761668616696167061671616726167361674616756167661677616786167961680616816168261683616846168561686616876168861689616906169161692616936169461695616966169761698616996170061701617026170361704617056170661707617086170961710617116171261713617146171561716617176171861719617206172161722617236172461725617266172761728617296173061731617326173361734617356173661737617386173961740617416174261743617446174561746617476174861749617506175161752617536175461755617566175761758617596176061761617626176361764617656176661767617686176961770617716177261773617746177561776617776177861779617806178161782617836178461785617866178761788617896179061791617926179361794617956179661797617986179961800618016180261803618046180561806618076180861809618106181161812618136181461815618166181761818618196182061821618226182361824618256182661827618286182961830618316183261833618346183561836618376183861839618406184161842618436184461845618466184761848618496185061851618526185361854618556185661857618586185961860618616186261863618646186561866618676186861869618706187161872618736187461875618766187761878618796188061881618826188361884618856188661887618886188961890618916189261893618946189561896618976189861899619006190161902619036190461905619066190761908619096191061911619126191361914619156191661917619186191961920619216192261923619246192561926619276192861929619306193161932619336193461935619366193761938619396194061941619426194361944619456194661947619486194961950619516195261953619546195561956619576195861959619606196161962619636196461965619666196761968619696197061971619726197361974619756197661977619786197961980619816198261983619846198561986619876198861989619906199161992619936199461995619966199761998619996200062001620026200362004620056200662007620086200962010620116201262013620146201562016620176201862019620206202162022620236202462025620266202762028620296203062031620326203362034620356203662037620386203962040620416204262043620446204562046620476204862049620506205162052620536205462055620566205762058620596206062061620626206362064620656206662067620686206962070620716207262073620746207562076620776207862079620806208162082620836208462085620866208762088620896209062091620926209362094620956209662097620986209962100621016210262103621046210562106621076210862109621106211162112621136211462115621166211762118621196212062121621226212362124621256212662127621286212962130621316213262133621346213562136621376213862139621406214162142621436214462145621466214762148621496215062151621526215362154621556215662157621586215962160621616216262163621646216562166621676216862169621706217162172621736217462175621766217762178621796218062181621826218362184621856218662187621886218962190621916219262193621946219562196621976219862199622006220162202622036220462205622066220762208622096221062211622126221362214622156221662217622186221962220622216222262223622246222562226622276222862229622306223162232622336223462235622366223762238622396224062241622426224362244622456224662247622486224962250622516225262253622546225562256622576225862259622606226162262622636226462265622666226762268622696227062271622726227362274622756227662277622786227962280622816228262283622846228562286622876228862289622906229162292622936229462295622966229762298622996230062301623026230362304623056230662307623086230962310623116231262313623146231562316623176231862319623206232162322623236232462325623266232762328623296233062331623326233362334623356233662337623386233962340623416234262343623446234562346623476234862349623506235162352623536235462355623566235762358623596236062361623626236362364623656236662367623686236962370623716237262373623746237562376623776237862379623806238162382623836238462385623866238762388623896239062391623926239362394623956239662397623986239962400624016240262403624046240562406624076240862409624106241162412624136241462415624166241762418624196242062421624226242362424624256242662427624286242962430624316243262433624346243562436624376243862439624406244162442624436244462445624466244762448624496245062451624526245362454624556245662457624586245962460624616246262463624646246562466624676246862469624706247162472624736247462475624766247762478624796248062481624826248362484624856248662487624886248962490624916249262493624946249562496624976249862499625006250162502625036250462505625066250762508625096251062511625126251362514625156251662517625186251962520625216252262523625246252562526625276252862529625306253162532625336253462535625366253762538625396254062541625426254362544625456254662547625486254962550625516255262553625546255562556625576255862559625606256162562625636256462565625666256762568625696257062571625726257362574625756257662577625786257962580625816258262583625846258562586625876258862589625906259162592625936259462595625966259762598625996260062601626026260362604626056260662607626086260962610626116261262613626146261562616626176261862619626206262162622626236262462625626266262762628626296263062631626326263362634626356263662637626386263962640626416264262643626446264562646626476264862649626506265162652626536265462655626566265762658626596266062661626626266362664626656266662667626686266962670626716267262673626746267562676626776267862679626806268162682626836268462685626866268762688626896269062691626926269362694626956269662697626986269962700627016270262703627046270562706627076270862709627106271162712627136271462715627166271762718627196272062721627226272362724627256272662727627286272962730627316273262733627346273562736627376273862739627406274162742627436274462745627466274762748627496275062751627526275362754627556275662757627586275962760627616276262763627646276562766627676276862769627706277162772627736277462775627766277762778627796278062781627826278362784627856278662787627886278962790627916279262793627946279562796627976279862799628006280162802628036280462805628066280762808628096281062811628126281362814628156281662817628186281962820628216282262823628246282562826628276282862829628306283162832628336283462835628366283762838628396284062841628426284362844628456284662847628486284962850628516285262853628546285562856628576285862859628606286162862628636286462865628666286762868628696287062871628726287362874628756287662877628786287962880628816288262883628846288562886628876288862889628906289162892628936289462895628966289762898628996290062901629026290362904629056290662907629086290962910629116291262913629146291562916629176291862919629206292162922629236292462925629266292762928629296293062931629326293362934629356293662937629386293962940629416294262943629446294562946629476294862949629506295162952629536295462955629566295762958629596296062961629626296362964629656296662967629686296962970629716297262973629746297562976629776297862979629806298162982629836298462985629866298762988629896299062991629926299362994629956299662997629986299963000630016300263003630046300563006630076300863009630106301163012630136301463015630166301763018630196302063021630226302363024630256302663027630286302963030630316303263033630346303563036630376303863039630406304163042630436304463045630466304763048630496305063051630526305363054630556305663057630586305963060630616306263063630646306563066630676306863069630706307163072630736307463075630766307763078630796308063081630826308363084630856308663087630886308963090630916309263093630946309563096630976309863099631006310163102631036310463105631066310763108631096311063111631126311363114631156311663117631186311963120631216312263123631246312563126631276312863129631306313163132631336313463135631366313763138631396314063141631426314363144631456314663147631486314963150631516315263153631546315563156631576315863159631606316163162631636316463165631666316763168631696317063171631726317363174631756317663177631786317963180631816318263183631846318563186631876318863189631906319163192631936319463195631966319763198631996320063201632026320363204632056320663207632086320963210632116321263213632146321563216632176321863219632206322163222632236322463225632266322763228632296323063231632326323363234632356323663237632386323963240632416324263243632446324563246632476324863249632506325163252632536325463255632566325763258632596326063261632626326363264632656326663267632686326963270632716327263273632746327563276632776327863279632806328163282632836328463285632866328763288632896329063291632926329363294632956329663297632986329963300633016330263303633046330563306633076330863309633106331163312633136331463315633166331763318633196332063321633226332363324633256332663327633286332963330633316333263333633346333563336633376333863339633406334163342633436334463345633466334763348633496335063351633526335363354633556335663357633586335963360633616336263363633646336563366633676336863369633706337163372633736337463375633766337763378633796338063381633826338363384633856338663387633886338963390633916339263393633946339563396633976339863399634006340163402634036340463405634066340763408634096341063411634126341363414634156341663417634186341963420634216342263423634246342563426634276342863429634306343163432634336343463435634366343763438634396344063441634426344363444634456344663447634486344963450634516345263453634546345563456634576345863459634606346163462634636346463465634666346763468634696347063471634726347363474634756347663477634786347963480634816348263483634846348563486634876348863489634906349163492634936349463495634966349763498634996350063501635026350363504635056350663507635086350963510635116351263513635146351563516635176351863519635206352163522635236352463525635266352763528635296353063531635326353363534635356353663537635386353963540635416354263543635446354563546635476354863549635506355163552635536355463555635566355763558635596356063561635626356363564635656356663567635686356963570635716357263573635746357563576635776357863579635806358163582635836358463585635866358763588635896359063591635926359363594635956359663597635986359963600636016360263603636046360563606636076360863609636106361163612636136361463615636166361763618636196362063621636226362363624636256362663627636286362963630636316363263633636346363563636636376363863639636406364163642636436364463645636466364763648636496365063651636526365363654636556365663657636586365963660636616366263663636646366563666636676366863669636706367163672636736367463675636766367763678636796368063681636826368363684636856368663687636886368963690636916369263693636946369563696636976369863699637006370163702637036370463705637066370763708637096371063711637126371363714637156371663717637186371963720637216372263723637246372563726637276372863729637306373163732637336373463735637366373763738637396374063741637426374363744637456374663747637486374963750637516375263753637546375563756637576375863759637606376163762637636376463765637666376763768637696377063771637726377363774637756377663777637786377963780637816378263783637846378563786637876378863789637906379163792637936379463795637966379763798637996380063801638026380363804638056380663807638086380963810638116381263813638146381563816638176381863819638206382163822638236382463825638266382763828638296383063831638326383363834638356383663837638386383963840638416384263843638446384563846638476384863849638506385163852638536385463855638566385763858638596386063861638626386363864638656386663867638686386963870638716387263873638746387563876638776387863879638806388163882638836388463885638866388763888638896389063891638926389363894638956389663897638986389963900639016390263903639046390563906639076390863909639106391163912639136391463915639166391763918639196392063921639226392363924639256392663927639286392963930639316393263933639346393563936639376393863939639406394163942639436394463945639466394763948639496395063951639526395363954639556395663957639586395963960639616396263963639646396563966639676396863969639706397163972639736397463975639766397763978639796398063981639826398363984639856398663987639886398963990639916399263993639946399563996639976399863999640006400164002640036400464005640066400764008640096401064011640126401364014640156401664017640186401964020640216402264023640246402564026640276402864029640306403164032640336403464035640366403764038640396404064041640426404364044640456404664047640486404964050640516405264053640546405564056640576405864059640606406164062640636406464065640666406764068640696407064071640726407364074640756407664077640786407964080640816408264083640846408564086640876408864089640906409164092640936409464095640966409764098640996410064101641026410364104641056410664107641086410964110641116411264113641146411564116641176411864119641206412164122641236412464125641266412764128641296413064131641326413364134641356413664137641386413964140641416414264143641446414564146641476414864149641506415164152641536415464155641566415764158641596416064161641626416364164641656416664167641686416964170641716417264173641746417564176641776417864179641806418164182641836418464185641866418764188641896419064191641926419364194641956419664197641986419964200642016420264203642046420564206642076420864209642106421164212642136421464215642166421764218642196422064221642226422364224642256422664227642286422964230642316423264233642346423564236642376423864239642406424164242642436424464245642466424764248642496425064251642526425364254642556425664257642586425964260642616426264263642646426564266642676426864269642706427164272642736427464275642766427764278642796428064281642826428364284642856428664287642886428964290642916429264293642946429564296642976429864299643006430164302643036430464305643066430764308643096431064311643126431364314643156431664317643186431964320643216432264323643246432564326643276432864329643306433164332643336433464335643366433764338643396434064341643426434364344643456434664347643486434964350643516435264353643546435564356643576435864359643606436164362643636436464365643666436764368643696437064371643726437364374643756437664377643786437964380643816438264383643846438564386643876438864389643906439164392643936439464395643966439764398643996440064401644026440364404644056440664407644086440964410644116441264413644146441564416644176441864419644206442164422644236442464425644266442764428644296443064431644326443364434644356443664437644386443964440644416444264443644446444564446644476444864449644506445164452644536445464455644566445764458644596446064461644626446364464644656446664467644686446964470644716447264473644746447564476644776447864479644806448164482644836448464485644866448764488644896449064491644926449364494644956449664497644986449964500645016450264503645046450564506645076450864509645106451164512645136451464515645166451764518645196452064521645226452364524645256452664527645286452964530645316453264533645346453564536645376453864539645406454164542645436454464545645466454764548645496455064551645526455364554645556455664557645586455964560645616456264563645646456564566645676456864569645706457164572645736457464575645766457764578645796458064581645826458364584645856458664587645886458964590645916459264593645946459564596645976459864599646006460164602646036460464605646066460764608646096461064611646126461364614646156461664617646186461964620646216462264623646246462564626646276462864629646306463164632646336463464635646366463764638646396464064641646426464364644646456464664647646486464964650646516465264653646546465564656646576465864659646606466164662646636466464665646666466764668646696467064671646726467364674646756467664677646786467964680646816468264683646846468564686646876468864689646906469164692646936469464695646966469764698646996470064701647026470364704647056470664707647086470964710647116471264713647146471564716647176471864719647206472164722647236472464725647266472764728647296473064731647326473364734647356473664737647386473964740647416474264743647446474564746647476474864749647506475164752647536475464755647566475764758647596476064761647626476364764647656476664767647686476964770647716477264773647746477564776647776477864779647806478164782647836478464785647866478764788647896479064791647926479364794647956479664797647986479964800648016480264803648046480564806648076480864809648106481164812648136481464815648166481764818648196482064821648226482364824648256482664827648286482964830648316483264833648346483564836648376483864839648406484164842648436484464845648466484764848648496485064851648526485364854648556485664857648586485964860648616486264863648646486564866648676486864869648706487164872648736487464875648766487764878648796488064881648826488364884648856488664887648886488964890648916489264893648946489564896648976489864899649006490164902649036490464905649066490764908649096491064911649126491364914649156491664917649186491964920649216492264923649246492564926649276492864929649306493164932649336493464935649366493764938649396494064941649426494364944649456494664947649486494964950649516495264953649546495564956649576495864959649606496164962649636496464965649666496764968649696497064971649726497364974649756497664977649786497964980649816498264983649846498564986649876498864989649906499164992649936499464995649966499764998649996500065001650026500365004650056500665007650086500965010650116501265013650146501565016650176501865019650206502165022650236502465025650266502765028650296503065031650326503365034650356503665037650386503965040650416504265043650446504565046650476504865049650506505165052650536505465055650566505765058650596506065061650626506365064650656506665067650686506965070650716507265073650746507565076650776507865079650806508165082650836508465085650866508765088650896509065091650926509365094650956509665097650986509965100651016510265103651046510565106651076510865109651106511165112651136511465115651166511765118651196512065121651226512365124651256512665127651286512965130651316513265133651346513565136651376513865139651406514165142651436514465145651466514765148651496515065151651526515365154651556515665157651586515965160651616516265163651646516565166651676516865169651706517165172651736517465175651766517765178651796518065181651826518365184651856518665187651886518965190651916519265193651946519565196651976519865199652006520165202652036520465205652066520765208652096521065211652126521365214652156521665217652186521965220652216522265223652246522565226652276522865229652306523165232652336523465235652366523765238652396524065241652426524365244652456524665247652486524965250652516525265253652546525565256652576525865259652606526165262652636526465265652666526765268652696527065271652726527365274652756527665277652786527965280652816528265283652846528565286652876528865289652906529165292652936529465295652966529765298652996530065301653026530365304653056530665307653086530965310653116531265313653146531565316653176531865319653206532165322653236532465325653266532765328653296533065331653326533365334653356533665337653386533965340653416534265343653446534565346653476534865349653506535165352653536535465355653566535765358653596536065361653626536365364653656536665367653686536965370653716537265373653746537565376653776537865379653806538165382653836538465385653866538765388653896539065391653926539365394653956539665397653986539965400654016540265403654046540565406654076540865409654106541165412654136541465415654166541765418654196542065421654226542365424654256542665427654286542965430654316543265433654346543565436654376543865439654406544165442654436544465445654466544765448654496545065451654526545365454654556545665457654586545965460654616546265463654646546565466654676546865469654706547165472654736547465475654766547765478654796548065481654826548365484654856548665487654886548965490654916549265493654946549565496654976549865499655006550165502655036550465505655066550765508655096551065511655126551365514655156551665517655186551965520655216552265523655246552565526655276552865529655306553165532655336553465535655366553765538655396554065541655426554365544655456554665547655486554965550655516555265553655546555565556655576555865559655606556165562655636556465565655666556765568655696557065571655726557365574655756557665577655786557965580655816558265583655846558565586655876558865589655906559165592655936559465595655966559765598655996560065601656026560365604656056560665607656086560965610656116561265613656146561565616656176561865619656206562165622656236562465625656266562765628656296563065631656326563365634656356563665637656386563965640656416564265643656446564565646656476564865649656506565165652656536565465655656566565765658656596566065661656626566365664656656566665667656686566965670656716567265673656746567565676656776567865679656806568165682656836568465685656866568765688656896569065691656926569365694656956569665697656986569965700657016570265703657046570565706657076570865709657106571165712657136571465715657166571765718657196572065721657226572365724657256572665727657286572965730657316573265733657346573565736657376573865739657406574165742657436574465745657466574765748657496575065751657526575365754657556575665757657586575965760657616576265763657646576565766657676576865769657706577165772657736577465775657766577765778657796578065781657826578365784657856578665787657886578965790657916579265793657946579565796657976579865799658006580165802658036580465805658066580765808658096581065811658126581365814658156581665817658186581965820658216582265823658246582565826658276582865829658306583165832658336583465835658366583765838658396584065841658426584365844658456584665847658486584965850658516585265853658546585565856658576585865859658606586165862658636586465865658666586765868658696587065871658726587365874658756587665877658786587965880658816588265883658846588565886658876588865889658906589165892658936589465895658966589765898658996590065901659026590365904659056590665907659086590965910659116591265913659146591565916659176591865919659206592165922659236592465925659266592765928659296593065931659326593365934659356593665937659386593965940659416594265943659446594565946659476594865949659506595165952659536595465955659566595765958659596596065961659626596365964659656596665967659686596965970659716597265973659746597565976659776597865979659806598165982659836598465985659866598765988659896599065991659926599365994659956599665997659986599966000660016600266003660046600566006660076600866009660106601166012660136601466015660166601766018660196602066021660226602366024660256602666027660286602966030660316603266033660346603566036660376603866039660406604166042660436604466045660466604766048660496605066051660526605366054660556605666057660586605966060660616606266063660646606566066660676606866069660706607166072660736607466075660766607766078660796608066081660826608366084660856608666087660886608966090660916609266093660946609566096660976609866099661006610166102661036610466105661066610766108661096611066111661126611366114661156611666117661186611966120661216612266123661246612566126661276612866129661306613166132661336613466135661366613766138661396614066141661426614366144661456614666147661486614966150661516615266153661546615566156661576615866159661606616166162661636616466165661666616766168661696617066171661726617366174661756617666177661786617966180661816618266183661846618566186661876618866189661906619166192661936619466195661966619766198661996620066201662026620366204662056620666207662086620966210662116621266213662146621566216662176621866219662206622166222662236622466225662266622766228662296623066231662326623366234662356623666237662386623966240662416624266243662446624566246662476624866249662506625166252662536625466255662566625766258662596626066261662626626366264662656626666267662686626966270662716627266273662746627566276662776627866279662806628166282662836628466285662866628766288662896629066291662926629366294662956629666297662986629966300663016630266303663046630566306663076630866309663106631166312663136631466315663166631766318663196632066321663226632366324663256632666327663286632966330663316633266333663346633566336663376633866339663406634166342663436634466345663466634766348663496635066351663526635366354663556635666357663586635966360663616636266363663646636566366663676636866369663706637166372663736637466375663766637766378663796638066381663826638366384663856638666387663886638966390663916639266393663946639566396663976639866399664006640166402664036640466405664066640766408664096641066411664126641366414664156641666417664186641966420664216642266423664246642566426664276642866429664306643166432664336643466435664366643766438664396644066441664426644366444664456644666447664486644966450664516645266453664546645566456664576645866459664606646166462664636646466465664666646766468664696647066471664726647366474664756647666477664786647966480664816648266483664846648566486664876648866489664906649166492664936649466495664966649766498664996650066501665026650366504665056650666507665086650966510665116651266513665146651566516665176651866519665206652166522665236652466525665266652766528665296653066531665326653366534665356653666537665386653966540665416654266543665446654566546665476654866549665506655166552665536655466555665566655766558665596656066561665626656366564665656656666567665686656966570665716657266573665746657566576665776657866579665806658166582665836658466585665866658766588665896659066591665926659366594665956659666597665986659966600666016660266603666046660566606666076660866609666106661166612666136661466615666166661766618666196662066621666226662366624666256662666627666286662966630666316663266633666346663566636666376663866639666406664166642666436664466645666466664766648666496665066651666526665366654666556665666657666586665966660666616666266663666646666566666666676666866669666706667166672666736667466675666766667766678666796668066681666826668366684666856668666687666886668966690666916669266693666946669566696666976669866699667006670166702667036670466705667066670766708667096671066711667126671366714667156671666717667186671966720667216672266723667246672566726667276672866729667306673166732667336673466735667366673766738667396674066741667426674366744667456674666747667486674966750667516675266753667546675566756667576675866759667606676166762667636676466765667666676766768667696677066771667726677366774667756677666777667786677966780667816678266783667846678566786667876678866789667906679166792667936679466795667966679766798667996680066801668026680366804668056680666807668086680966810668116681266813668146681566816668176681866819668206682166822668236682466825668266682766828668296683066831668326683366834668356683666837668386683966840668416684266843668446684566846668476684866849668506685166852668536685466855668566685766858668596686066861668626686366864668656686666867668686686966870668716687266873668746687566876668776687866879668806688166882668836688466885668866688766888668896689066891668926689366894668956689666897668986689966900669016690266903669046690566906669076690866909669106691166912669136691466915669166691766918669196692066921669226692366924669256692666927669286692966930669316693266933669346693566936669376693866939669406694166942669436694466945669466694766948669496695066951669526695366954669556695666957669586695966960669616696266963669646696566966669676696866969669706697166972669736697466975669766697766978669796698066981669826698366984669856698666987669886698966990669916699266993669946699566996669976699866999670006700167002670036700467005670066700767008670096701067011670126701367014670156701667017670186701967020670216702267023670246702567026670276702867029670306703167032670336703467035670366703767038670396704067041670426704367044670456704667047670486704967050670516705267053670546705567056670576705867059670606706167062670636706467065670666706767068670696707067071670726707367074670756707667077670786707967080670816708267083670846708567086670876708867089670906709167092670936709467095670966709767098670996710067101671026710367104671056710667107671086710967110671116711267113671146711567116671176711867119671206712167122671236712467125671266712767128671296713067131671326713367134671356713667137671386713967140671416714267143671446714567146671476714867149671506715167152671536715467155671566715767158671596716067161671626716367164671656716667167671686716967170671716717267173671746717567176671776717867179671806718167182671836718467185671866718767188671896719067191671926719367194671956719667197671986719967200672016720267203672046720567206672076720867209672106721167212672136721467215672166721767218672196722067221672226722367224672256722667227672286722967230672316723267233672346723567236672376723867239672406724167242672436724467245672466724767248672496725067251672526725367254672556725667257672586725967260672616726267263672646726567266672676726867269672706727167272672736727467275672766727767278672796728067281672826728367284672856728667287672886728967290672916729267293672946729567296672976729867299673006730167302673036730467305673066730767308673096731067311673126731367314673156731667317673186731967320673216732267323673246732567326673276732867329673306733167332673336733467335673366733767338673396734067341673426734367344673456734667347673486734967350673516735267353673546735567356673576735867359673606736167362673636736467365673666736767368673696737067371673726737367374673756737667377673786737967380673816738267383673846738567386673876738867389673906739167392673936739467395673966739767398673996740067401674026740367404674056740667407674086740967410674116741267413674146741567416674176741867419674206742167422674236742467425674266742767428674296743067431674326743367434674356743667437674386743967440674416744267443674446744567446674476744867449674506745167452674536745467455674566745767458674596746067461674626746367464674656746667467674686746967470674716747267473674746747567476674776747867479674806748167482674836748467485674866748767488674896749067491674926749367494674956749667497674986749967500675016750267503675046750567506675076750867509675106751167512675136751467515675166751767518675196752067521675226752367524675256752667527675286752967530675316753267533675346753567536675376753867539675406754167542675436754467545675466754767548675496755067551675526755367554675556755667557675586755967560675616756267563675646756567566675676756867569675706757167572675736757467575675766757767578675796758067581675826758367584675856758667587675886758967590675916759267593675946759567596675976759867599676006760167602676036760467605676066760767608676096761067611676126761367614676156761667617676186761967620676216762267623676246762567626676276762867629676306763167632676336763467635676366763767638676396764067641676426764367644676456764667647676486764967650676516765267653676546765567656676576765867659676606766167662676636766467665676666766767668676696767067671676726767367674676756767667677676786767967680676816768267683676846768567686676876768867689676906769167692676936769467695676966769767698676996770067701677026770367704677056770667707677086770967710677116771267713677146771567716677176771867719677206772167722677236772467725677266772767728677296773067731677326773367734677356773667737677386773967740677416774267743677446774567746677476774867749677506775167752677536775467755677566775767758677596776067761677626776367764677656776667767677686776967770677716777267773677746777567776677776777867779677806778167782677836778467785677866778767788677896779067791677926779367794677956779667797677986779967800678016780267803678046780567806678076780867809678106781167812678136781467815678166781767818678196782067821678226782367824678256782667827678286782967830678316783267833678346783567836678376783867839678406784167842678436784467845678466784767848678496785067851678526785367854678556785667857678586785967860678616786267863678646786567866678676786867869678706787167872678736787467875678766787767878678796788067881678826788367884678856788667887678886788967890678916789267893678946789567896678976789867899679006790167902679036790467905679066790767908679096791067911679126791367914679156791667917679186791967920679216792267923679246792567926679276792867929679306793167932679336793467935679366793767938679396794067941679426794367944679456794667947679486794967950679516795267953679546795567956679576795867959679606796167962679636796467965679666796767968679696797067971679726797367974679756797667977679786797967980679816798267983679846798567986679876798867989679906799167992679936799467995679966799767998679996800068001680026800368004680056800668007680086800968010680116801268013680146801568016680176801868019680206802168022680236802468025680266802768028680296803068031680326803368034680356803668037680386803968040680416804268043680446804568046680476804868049680506805168052680536805468055680566805768058680596806068061680626806368064680656806668067680686806968070680716807268073680746807568076680776807868079680806808168082680836808468085680866808768088680896809068091680926809368094680956809668097680986809968100681016810268103681046810568106681076810868109681106811168112681136811468115681166811768118681196812068121681226812368124681256812668127681286812968130681316813268133681346813568136681376813868139681406814168142681436814468145681466814768148681496815068151681526815368154681556815668157681586815968160681616816268163681646816568166681676816868169681706817168172681736817468175681766817768178681796818068181681826818368184681856818668187681886818968190681916819268193681946819568196681976819868199682006820168202682036820468205682066820768208682096821068211682126821368214682156821668217682186821968220682216822268223682246822568226682276822868229682306823168232682336823468235682366823768238682396824068241682426824368244682456824668247682486824968250682516825268253682546825568256682576825868259682606826168262682636826468265682666826768268682696827068271682726827368274682756827668277682786827968280682816828268283682846828568286682876828868289682906829168292682936829468295682966829768298682996830068301683026830368304683056830668307683086830968310683116831268313683146831568316683176831868319683206832168322683236832468325683266832768328683296833068331683326833368334683356833668337683386833968340683416834268343683446834568346683476834868349683506835168352683536835468355683566835768358683596836068361683626836368364683656836668367683686836968370683716837268373683746837568376683776837868379683806838168382683836838468385683866838768388683896839068391683926839368394683956839668397683986839968400684016840268403684046840568406684076840868409684106841168412684136841468415684166841768418684196842068421684226842368424684256842668427684286842968430684316843268433684346843568436684376843868439684406844168442684436844468445684466844768448684496845068451684526845368454684556845668457684586845968460684616846268463684646846568466684676846868469684706847168472684736847468475684766847768478684796848068481684826848368484684856848668487684886848968490684916849268493684946849568496684976849868499685006850168502685036850468505685066850768508685096851068511685126851368514685156851668517685186851968520685216852268523685246852568526685276852868529685306853168532685336853468535685366853768538685396854068541685426854368544685456854668547685486854968550685516855268553685546855568556685576855868559685606856168562685636856468565685666856768568685696857068571685726857368574685756857668577685786857968580685816858268583685846858568586685876858868589685906859168592685936859468595685966859768598685996860068601686026860368604686056860668607686086860968610686116861268613686146861568616686176861868619686206862168622686236862468625686266862768628686296863068631686326863368634686356863668637686386863968640686416864268643686446864568646686476864868649686506865168652686536865468655686566865768658686596866068661686626866368664686656866668667686686866968670686716867268673686746867568676686776867868679686806868168682686836868468685686866868768688686896869068691686926869368694686956869668697686986869968700687016870268703687046870568706687076870868709687106871168712687136871468715687166871768718687196872068721687226872368724687256872668727687286872968730687316873268733687346873568736687376873868739687406874168742687436874468745687466874768748687496875068751687526875368754687556875668757687586875968760687616876268763687646876568766687676876868769687706877168772687736877468775687766877768778687796878068781687826878368784687856878668787687886878968790687916879268793687946879568796687976879868799688006880168802688036880468805688066880768808688096881068811688126881368814688156881668817688186881968820688216882268823688246882568826688276882868829688306883168832688336883468835688366883768838688396884068841688426884368844688456884668847688486884968850688516885268853688546885568856688576885868859688606886168862688636886468865688666886768868688696887068871688726887368874688756887668877688786887968880688816888268883688846888568886688876888868889688906889168892688936889468895688966889768898688996890068901689026890368904689056890668907689086890968910689116891268913689146891568916689176891868919689206892168922689236892468925689266892768928689296893068931689326893368934689356893668937689386893968940689416894268943689446894568946689476894868949689506895168952689536895468955689566895768958689596896068961689626896368964689656896668967689686896968970689716897268973689746897568976689776897868979689806898168982689836898468985689866898768988689896899068991689926899368994689956899668997689986899969000690016900269003690046900569006690076900869009690106901169012690136901469015690166901769018690196902069021690226902369024690256902669027690286902969030690316903269033690346903569036690376903869039690406904169042690436904469045690466904769048690496905069051690526905369054690556905669057690586905969060690616906269063690646906569066690676906869069690706907169072690736907469075690766907769078690796908069081690826908369084690856908669087690886908969090690916909269093690946909569096690976909869099691006910169102691036910469105691066910769108691096911069111691126911369114691156911669117691186911969120691216912269123691246912569126691276912869129691306913169132691336913469135691366913769138691396914069141691426914369144691456914669147691486914969150691516915269153691546915569156691576915869159691606916169162691636916469165691666916769168691696917069171691726917369174691756917669177691786917969180691816918269183691846918569186691876918869189691906919169192691936919469195691966919769198691996920069201692026920369204692056920669207692086920969210692116921269213692146921569216692176921869219692206922169222692236922469225692266922769228692296923069231692326923369234692356923669237692386923969240692416924269243692446924569246692476924869249692506925169252692536925469255692566925769258692596926069261692626926369264692656926669267692686926969270692716927269273692746927569276692776927869279692806928169282692836928469285692866928769288692896929069291692926929369294692956929669297692986929969300693016930269303693046930569306693076930869309693106931169312693136931469315693166931769318693196932069321693226932369324693256932669327693286932969330693316933269333693346933569336693376933869339693406934169342693436934469345693466934769348693496935069351693526935369354693556935669357693586935969360693616936269363693646936569366693676936869369693706937169372693736937469375693766937769378693796938069381693826938369384693856938669387693886938969390693916939269393693946939569396693976939869399694006940169402694036940469405694066940769408694096941069411694126941369414694156941669417694186941969420694216942269423694246942569426694276942869429694306943169432694336943469435694366943769438694396944069441694426944369444694456944669447694486944969450694516945269453694546945569456694576945869459694606946169462694636946469465694666946769468694696947069471694726947369474694756947669477694786947969480694816948269483694846948569486694876948869489694906949169492694936949469495694966949769498694996950069501695026950369504695056950669507695086950969510695116951269513695146951569516695176951869519695206952169522695236952469525695266952769528695296953069531695326953369534695356953669537695386953969540695416954269543695446954569546695476954869549695506955169552695536955469555695566955769558695596956069561695626956369564695656956669567695686956969570695716957269573695746957569576695776957869579695806958169582695836958469585695866958769588695896959069591695926959369594695956959669597695986959969600696016960269603696046960569606696076960869609696106961169612696136961469615696166961769618696196962069621696226962369624696256962669627696286962969630696316963269633696346963569636696376963869639696406964169642696436964469645696466964769648696496965069651696526965369654696556965669657696586965969660696616966269663696646966569666696676966869669696706967169672696736967469675696766967769678696796968069681696826968369684696856968669687696886968969690696916969269693696946969569696696976969869699697006970169702697036970469705697066970769708697096971069711697126971369714697156971669717697186971969720697216972269723697246972569726697276972869729697306973169732697336973469735697366973769738697396974069741697426974369744697456974669747697486974969750697516975269753697546975569756697576975869759697606976169762697636976469765697666976769768697696977069771697726977369774697756977669777697786977969780697816978269783697846978569786697876978869789697906979169792697936979469795697966979769798697996980069801698026980369804698056980669807698086980969810698116981269813698146981569816698176981869819698206982169822698236982469825698266982769828698296983069831698326983369834698356983669837698386983969840698416984269843698446984569846698476984869849698506985169852698536985469855698566985769858698596986069861698626986369864698656986669867698686986969870698716987269873698746987569876698776987869879698806988169882698836988469885698866988769888698896989069891698926989369894698956989669897698986989969900699016990269903699046990569906699076990869909699106991169912699136991469915699166991769918699196992069921699226992369924699256992669927699286992969930699316993269933699346993569936699376993869939699406994169942699436994469945699466994769948699496995069951699526995369954699556995669957699586995969960699616996269963699646996569966699676996869969699706997169972699736997469975699766997769978699796998069981699826998369984699856998669987699886998969990699916999269993699946999569996699976999869999700007000170002700037000470005700067000770008700097001070011700127001370014700157001670017700187001970020700217002270023700247002570026700277002870029700307003170032700337003470035700367003770038700397004070041700427004370044700457004670047700487004970050700517005270053700547005570056700577005870059700607006170062700637006470065700667006770068700697007070071700727007370074700757007670077700787007970080700817008270083700847008570086700877008870089700907009170092700937009470095700967009770098700997010070101701027010370104701057010670107701087010970110701117011270113701147011570116701177011870119701207012170122701237012470125701267012770128701297013070131701327013370134701357013670137701387013970140701417014270143701447014570146701477014870149701507015170152701537015470155701567015770158701597016070161701627016370164701657016670167701687016970170701717017270173701747017570176701777017870179701807018170182701837018470185701867018770188701897019070191701927019370194701957019670197701987019970200702017020270203702047020570206702077020870209702107021170212702137021470215702167021770218702197022070221702227022370224702257022670227702287022970230702317023270233702347023570236702377023870239702407024170242702437024470245702467024770248702497025070251702527025370254702557025670257702587025970260702617026270263702647026570266702677026870269702707027170272702737027470275702767027770278702797028070281702827028370284702857028670287702887028970290702917029270293702947029570296702977029870299703007030170302703037030470305703067030770308703097031070311703127031370314703157031670317703187031970320703217032270323703247032570326703277032870329703307033170332703337033470335703367033770338703397034070341703427034370344703457034670347703487034970350703517035270353703547035570356703577035870359703607036170362703637036470365703667036770368703697037070371703727037370374703757037670377703787037970380703817038270383703847038570386703877038870389703907039170392703937039470395703967039770398703997040070401704027040370404704057040670407704087040970410704117041270413704147041570416704177041870419704207042170422704237042470425704267042770428704297043070431704327043370434704357043670437704387043970440704417044270443704447044570446704477044870449704507045170452704537045470455704567045770458704597046070461704627046370464704657046670467704687046970470704717047270473704747047570476704777047870479704807048170482704837048470485704867048770488704897049070491704927049370494704957049670497704987049970500705017050270503705047050570506705077050870509705107051170512705137051470515705167051770518705197052070521705227052370524705257052670527705287052970530705317053270533705347053570536705377053870539705407054170542705437054470545705467054770548705497055070551705527055370554705557055670557705587055970560705617056270563705647056570566705677056870569705707057170572705737057470575705767057770578705797058070581705827058370584705857058670587705887058970590705917059270593705947059570596705977059870599706007060170602706037060470605706067060770608706097061070611706127061370614706157061670617706187061970620706217062270623706247062570626706277062870629706307063170632706337063470635706367063770638706397064070641706427064370644706457064670647706487064970650706517065270653706547065570656706577065870659706607066170662706637066470665706667066770668706697067070671706727067370674706757067670677706787067970680706817068270683706847068570686706877068870689706907069170692706937069470695706967069770698706997070070701707027070370704707057070670707707087070970710707117071270713707147071570716707177071870719707207072170722707237072470725707267072770728707297073070731707327073370734707357073670737707387073970740707417074270743707447074570746707477074870749707507075170752707537075470755707567075770758707597076070761707627076370764707657076670767707687076970770707717077270773707747077570776707777077870779707807078170782707837078470785707867078770788707897079070791707927079370794707957079670797707987079970800708017080270803708047080570806708077080870809708107081170812708137081470815708167081770818708197082070821708227082370824708257082670827708287082970830708317083270833708347083570836708377083870839708407084170842708437084470845708467084770848708497085070851708527085370854708557085670857708587085970860708617086270863708647086570866708677086870869708707087170872708737087470875708767087770878708797088070881708827088370884708857088670887708887088970890708917089270893708947089570896708977089870899709007090170902709037090470905709067090770908709097091070911709127091370914709157091670917709187091970920709217092270923709247092570926709277092870929709307093170932709337093470935709367093770938709397094070941709427094370944709457094670947709487094970950709517095270953709547095570956709577095870959709607096170962709637096470965709667096770968709697097070971709727097370974709757097670977709787097970980709817098270983709847098570986709877098870989709907099170992709937099470995709967099770998709997100071001710027100371004710057100671007710087100971010710117101271013710147101571016710177101871019710207102171022710237102471025710267102771028710297103071031710327103371034710357103671037710387103971040710417104271043710447104571046710477104871049710507105171052710537105471055710567105771058710597106071061710627106371064710657106671067710687106971070710717107271073710747107571076710777107871079710807108171082710837108471085710867108771088710897109071091710927109371094710957109671097710987109971100711017110271103711047110571106711077110871109711107111171112711137111471115711167111771118711197112071121711227112371124711257112671127711287112971130711317113271133711347113571136711377113871139711407114171142711437114471145711467114771148711497115071151711527115371154711557115671157711587115971160711617116271163711647116571166711677116871169711707117171172711737117471175711767117771178711797118071181711827118371184711857118671187711887118971190711917119271193711947119571196711977119871199712007120171202712037120471205712067120771208712097121071211712127121371214712157121671217712187121971220712217122271223712247122571226712277122871229712307123171232712337123471235712367123771238712397124071241712427124371244712457124671247712487124971250712517125271253712547125571256712577125871259712607126171262712637126471265712667126771268712697127071271712727127371274712757127671277712787127971280712817128271283712847128571286712877128871289712907129171292712937129471295712967129771298712997130071301713027130371304713057130671307713087130971310713117131271313713147131571316713177131871319713207132171322713237132471325713267132771328713297133071331713327133371334713357133671337713387133971340713417134271343713447134571346713477134871349713507135171352713537135471355713567135771358713597136071361713627136371364713657136671367713687136971370713717137271373713747137571376713777137871379713807138171382713837138471385713867138771388713897139071391713927139371394713957139671397713987139971400714017140271403714047140571406714077140871409714107141171412714137141471415714167141771418714197142071421714227142371424714257142671427714287142971430714317143271433714347143571436714377143871439714407144171442714437144471445714467144771448714497145071451714527145371454714557145671457714587145971460714617146271463714647146571466714677146871469714707147171472714737147471475714767147771478714797148071481714827148371484714857148671487714887148971490714917149271493714947149571496714977149871499715007150171502715037150471505715067150771508715097151071511715127151371514715157151671517715187151971520715217152271523715247152571526715277152871529715307153171532715337153471535715367153771538715397154071541715427154371544715457154671547715487154971550715517155271553715547155571556715577155871559715607156171562715637156471565715667156771568715697157071571715727157371574715757157671577715787157971580715817158271583715847158571586715877158871589715907159171592715937159471595715967159771598715997160071601716027160371604716057160671607716087160971610716117161271613716147161571616716177161871619716207162171622716237162471625716267162771628716297163071631716327163371634716357163671637716387163971640716417164271643716447164571646716477164871649716507165171652716537165471655716567165771658716597166071661716627166371664716657166671667716687166971670716717167271673716747167571676716777167871679716807168171682716837168471685716867168771688716897169071691716927169371694716957169671697716987169971700717017170271703717047170571706717077170871709717107171171712717137171471715717167171771718717197172071721717227172371724717257172671727717287172971730717317173271733717347173571736717377173871739717407174171742717437174471745717467174771748717497175071751717527175371754717557175671757717587175971760717617176271763717647176571766717677176871769717707177171772717737177471775717767177771778717797178071781717827178371784717857178671787717887178971790717917179271793717947179571796717977179871799718007180171802718037180471805718067180771808718097181071811718127181371814718157181671817718187181971820718217182271823718247182571826718277182871829718307183171832718337183471835718367183771838718397184071841718427184371844718457184671847718487184971850718517185271853718547185571856718577185871859718607186171862718637186471865718667186771868718697187071871718727187371874718757187671877718787187971880718817188271883718847188571886718877188871889718907189171892718937189471895718967189771898718997190071901719027190371904719057190671907719087190971910719117191271913719147191571916719177191871919719207192171922719237192471925719267192771928719297193071931719327193371934719357193671937719387193971940719417194271943719447194571946719477194871949719507195171952719537195471955719567195771958719597196071961719627196371964719657196671967719687196971970719717197271973719747197571976719777197871979719807198171982719837198471985719867198771988719897199071991719927199371994719957199671997719987199972000720017200272003720047200572006720077200872009720107201172012720137201472015720167201772018720197202072021720227202372024720257202672027720287202972030720317203272033720347203572036720377203872039720407204172042720437204472045720467204772048720497205072051720527205372054720557205672057720587205972060720617206272063720647206572066720677206872069720707207172072720737207472075720767207772078720797208072081720827208372084720857208672087720887208972090720917209272093720947209572096720977209872099721007210172102721037210472105721067210772108721097211072111721127211372114721157211672117721187211972120721217212272123721247212572126721277212872129721307213172132721337213472135721367213772138721397214072141721427214372144721457214672147721487214972150721517215272153721547215572156721577215872159721607216172162721637216472165721667216772168721697217072171721727217372174721757217672177721787217972180721817218272183721847218572186721877218872189721907219172192721937219472195721967219772198721997220072201722027220372204722057220672207722087220972210722117221272213722147221572216722177221872219722207222172222722237222472225722267222772228722297223072231722327223372234722357223672237722387223972240722417224272243722447224572246722477224872249722507225172252722537225472255722567225772258722597226072261722627226372264722657226672267722687226972270722717227272273722747227572276722777227872279722807228172282722837228472285722867228772288722897229072291722927229372294722957229672297722987229972300723017230272303723047230572306723077230872309723107231172312723137231472315723167231772318723197232072321723227232372324723257232672327723287232972330723317233272333723347233572336723377233872339723407234172342723437234472345723467234772348723497235072351723527235372354723557235672357723587235972360723617236272363723647236572366723677236872369723707237172372723737237472375723767237772378723797238072381723827238372384723857238672387723887238972390723917239272393723947239572396723977239872399724007240172402724037240472405724067240772408724097241072411724127241372414724157241672417724187241972420724217242272423724247242572426724277242872429724307243172432724337243472435724367243772438724397244072441724427244372444724457244672447724487244972450724517245272453724547245572456724577245872459724607246172462724637246472465724667246772468724697247072471724727247372474724757247672477724787247972480724817248272483724847248572486724877248872489724907249172492724937249472495724967249772498724997250072501725027250372504725057250672507725087250972510725117251272513725147251572516725177251872519725207252172522725237252472525725267252772528725297253072531725327253372534725357253672537725387253972540725417254272543725447254572546725477254872549725507255172552725537255472555725567255772558725597256072561725627256372564725657256672567725687256972570725717257272573725747257572576725777257872579725807258172582725837258472585725867258772588725897259072591725927259372594725957259672597725987259972600726017260272603726047260572606726077260872609726107261172612726137261472615726167261772618726197262072621726227262372624726257262672627726287262972630726317263272633726347263572636726377263872639726407264172642726437264472645726467264772648726497265072651726527265372654726557265672657726587265972660726617266272663726647266572666726677266872669726707267172672726737267472675726767267772678726797268072681726827268372684726857268672687726887268972690726917269272693726947269572696726977269872699727007270172702727037270472705727067270772708727097271072711727127271372714727157271672717727187271972720727217272272723727247272572726727277272872729727307273172732727337273472735727367273772738727397274072741727427274372744727457274672747727487274972750727517275272753727547275572756727577275872759727607276172762727637276472765727667276772768727697277072771727727277372774727757277672777727787277972780727817278272783727847278572786727877278872789727907279172792727937279472795727967279772798727997280072801728027280372804728057280672807728087280972810728117281272813728147281572816728177281872819728207282172822728237282472825728267282772828728297283072831728327283372834728357283672837728387283972840728417284272843728447284572846728477284872849728507285172852728537285472855728567285772858728597286072861728627286372864728657286672867728687286972870728717287272873728747287572876728777287872879728807288172882728837288472885728867288772888728897289072891728927289372894728957289672897728987289972900729017290272903729047290572906729077290872909729107291172912729137291472915729167291772918729197292072921729227292372924729257292672927729287292972930729317293272933729347293572936729377293872939729407294172942729437294472945729467294772948729497295072951729527295372954729557295672957729587295972960729617296272963729647296572966729677296872969729707297172972729737297472975729767297772978729797298072981729827298372984729857298672987729887298972990729917299272993729947299572996729977299872999730007300173002730037300473005730067300773008730097301073011730127301373014730157301673017730187301973020730217302273023730247302573026730277302873029730307303173032730337303473035730367303773038730397304073041730427304373044730457304673047730487304973050730517305273053730547305573056730577305873059730607306173062730637306473065730667306773068730697307073071730727307373074730757307673077730787307973080730817308273083730847308573086730877308873089730907309173092730937309473095730967309773098730997310073101731027310373104731057310673107731087310973110731117311273113731147311573116731177311873119731207312173122731237312473125731267312773128731297313073131731327313373134731357313673137731387313973140731417314273143731447314573146731477314873149731507315173152731537315473155731567315773158731597316073161731627316373164731657316673167731687316973170731717317273173731747317573176731777317873179731807318173182731837318473185731867318773188731897319073191731927319373194731957319673197731987319973200732017320273203732047320573206732077320873209732107321173212732137321473215732167321773218732197322073221732227322373224732257322673227732287322973230732317323273233732347323573236732377323873239732407324173242732437324473245732467324773248732497325073251732527325373254732557325673257732587325973260732617326273263732647326573266732677326873269732707327173272732737327473275732767327773278732797328073281732827328373284732857328673287732887328973290732917329273293732947329573296732977329873299733007330173302733037330473305733067330773308733097331073311733127331373314733157331673317733187331973320733217332273323733247332573326733277332873329733307333173332733337333473335733367333773338733397334073341733427334373344733457334673347733487334973350733517335273353733547335573356733577335873359733607336173362733637336473365733667336773368733697337073371733727337373374733757337673377733787337973380733817338273383733847338573386733877338873389733907339173392733937339473395733967339773398733997340073401734027340373404734057340673407734087340973410734117341273413734147341573416734177341873419734207342173422734237342473425734267342773428734297343073431734327343373434734357343673437734387343973440734417344273443734447344573446734477344873449734507345173452734537345473455734567345773458734597346073461734627346373464734657346673467734687346973470734717347273473734747347573476734777347873479734807348173482734837348473485734867348773488734897349073491734927349373494734957349673497734987349973500735017350273503735047350573506735077350873509735107351173512735137351473515735167351773518735197352073521735227352373524735257352673527735287352973530735317353273533735347353573536735377353873539735407354173542735437354473545735467354773548735497355073551735527355373554735557355673557735587355973560735617356273563735647356573566735677356873569735707357173572735737357473575735767357773578735797358073581735827358373584735857358673587735887358973590735917359273593735947359573596735977359873599736007360173602736037360473605736067360773608736097361073611736127361373614736157361673617736187361973620736217362273623736247362573626736277362873629736307363173632736337363473635736367363773638736397364073641736427364373644736457364673647736487364973650736517365273653736547365573656736577365873659736607366173662736637366473665736667366773668736697367073671736727367373674736757367673677736787367973680736817368273683736847368573686736877368873689736907369173692736937369473695736967369773698736997370073701737027370373704737057370673707737087370973710737117371273713737147371573716737177371873719737207372173722737237372473725737267372773728737297373073731737327373373734737357373673737737387373973740737417374273743737447374573746737477374873749737507375173752737537375473755737567375773758737597376073761737627376373764737657376673767737687376973770737717377273773737747377573776737777377873779737807378173782737837378473785737867378773788737897379073791737927379373794737957379673797737987379973800738017380273803738047380573806738077380873809738107381173812738137381473815738167381773818738197382073821738227382373824738257382673827738287382973830738317383273833738347383573836738377383873839738407384173842738437384473845738467384773848738497385073851738527385373854738557385673857738587385973860738617386273863738647386573866738677386873869738707387173872738737387473875738767387773878738797388073881738827388373884738857388673887738887388973890738917389273893738947389573896738977389873899739007390173902739037390473905739067390773908739097391073911739127391373914739157391673917739187391973920739217392273923739247392573926739277392873929739307393173932739337393473935739367393773938739397394073941739427394373944739457394673947739487394973950739517395273953739547395573956739577395873959739607396173962739637396473965739667396773968739697397073971739727397373974739757397673977739787397973980739817398273983739847398573986739877398873989739907399173992739937399473995739967399773998739997400074001740027400374004740057400674007740087400974010740117401274013740147401574016740177401874019740207402174022740237402474025740267402774028740297403074031740327403374034740357403674037740387403974040740417404274043740447404574046740477404874049740507405174052740537405474055740567405774058740597406074061740627406374064740657406674067740687406974070740717407274073740747407574076740777407874079740807408174082740837408474085740867408774088740897409074091740927409374094740957409674097740987409974100741017410274103741047410574106741077410874109741107411174112741137411474115741167411774118741197412074121741227412374124741257412674127741287412974130741317413274133741347413574136741377413874139741407414174142741437414474145741467414774148741497415074151741527415374154741557415674157741587415974160741617416274163741647416574166741677416874169741707417174172741737417474175741767417774178741797418074181741827418374184741857418674187741887418974190741917419274193741947419574196741977419874199742007420174202742037420474205742067420774208742097421074211742127421374214742157421674217742187421974220742217422274223742247422574226742277422874229742307423174232742337423474235742367423774238742397424074241742427424374244742457424674247742487424974250742517425274253742547425574256742577425874259742607426174262742637426474265742667426774268742697427074271742727427374274742757427674277742787427974280742817428274283742847428574286742877428874289742907429174292742937429474295742967429774298742997430074301743027430374304743057430674307743087430974310743117431274313743147431574316743177431874319743207432174322743237432474325743267432774328743297433074331743327433374334743357433674337743387433974340743417434274343743447434574346743477434874349743507435174352743537435474355743567435774358743597436074361743627436374364743657436674367743687436974370743717437274373743747437574376743777437874379743807438174382743837438474385743867438774388743897439074391743927439374394743957439674397743987439974400744017440274403744047440574406744077440874409744107441174412744137441474415744167441774418744197442074421744227442374424744257442674427744287442974430744317443274433744347443574436744377443874439744407444174442744437444474445744467444774448744497445074451744527445374454744557445674457744587445974460744617446274463744647446574466744677446874469744707447174472744737447474475744767447774478744797448074481744827448374484744857448674487744887448974490744917449274493744947449574496744977449874499745007450174502745037450474505745067450774508745097451074511745127451374514745157451674517745187451974520745217452274523745247452574526745277452874529745307453174532745337453474535745367453774538745397454074541745427454374544745457454674547745487454974550745517455274553745547455574556745577455874559745607456174562745637456474565745667456774568745697457074571745727457374574745757457674577745787457974580745817458274583745847458574586745877458874589745907459174592745937459474595745967459774598745997460074601746027460374604746057460674607746087460974610746117461274613746147461574616746177461874619746207462174622746237462474625746267462774628746297463074631746327463374634746357463674637746387463974640746417464274643746447464574646746477464874649746507465174652746537465474655746567465774658746597466074661746627466374664746657466674667746687466974670746717467274673746747467574676746777467874679746807468174682746837468474685746867468774688746897469074691746927469374694746957469674697746987469974700747017470274703747047470574706747077470874709747107471174712747137471474715747167471774718747197472074721747227472374724747257472674727747287472974730747317473274733747347473574736747377473874739747407474174742747437474474745747467474774748747497475074751747527475374754747557475674757747587475974760747617476274763747647476574766747677476874769747707477174772747737477474775747767477774778747797478074781747827478374784747857478674787747887478974790747917479274793747947479574796747977479874799748007480174802748037480474805748067480774808748097481074811748127481374814748157481674817748187481974820748217482274823748247482574826748277482874829748307483174832748337483474835748367483774838748397484074841748427484374844748457484674847748487484974850748517485274853748547485574856748577485874859748607486174862748637486474865748667486774868748697487074871748727487374874748757487674877748787487974880748817488274883748847488574886748877488874889748907489174892748937489474895748967489774898748997490074901749027490374904749057490674907749087490974910749117491274913749147491574916749177491874919749207492174922749237492474925749267492774928749297493074931749327493374934749357493674937749387493974940749417494274943749447494574946749477494874949749507495174952749537495474955749567495774958749597496074961749627496374964749657496674967749687496974970749717497274973749747497574976749777497874979749807498174982749837498474985749867498774988749897499074991749927499374994749957499674997749987499975000750017500275003750047500575006750077500875009750107501175012750137501475015750167501775018750197502075021750227502375024750257502675027750287502975030750317503275033750347503575036750377503875039750407504175042750437504475045750467504775048750497505075051750527505375054750557505675057750587505975060750617506275063750647506575066750677506875069750707507175072750737507475075750767507775078750797508075081750827508375084750857508675087750887508975090750917509275093750947509575096750977509875099751007510175102751037510475105751067510775108751097511075111751127511375114751157511675117751187511975120751217512275123751247512575126751277512875129751307513175132751337513475135751367513775138751397514075141751427514375144751457514675147751487514975150751517515275153751547515575156751577515875159751607516175162751637516475165751667516775168751697517075171751727517375174751757517675177751787517975180751817518275183751847518575186751877518875189751907519175192751937519475195751967519775198751997520075201752027520375204752057520675207752087520975210752117521275213752147521575216752177521875219752207522175222752237522475225752267522775228752297523075231752327523375234752357523675237752387523975240752417524275243752447524575246752477524875249752507525175252752537525475255752567525775258752597526075261752627526375264752657526675267752687526975270752717527275273752747527575276752777527875279752807528175282752837528475285752867528775288752897529075291752927529375294752957529675297752987529975300753017530275303753047530575306753077530875309753107531175312753137531475315753167531775318753197532075321753227532375324753257532675327753287532975330753317533275333753347533575336753377533875339753407534175342753437534475345753467534775348753497535075351753527535375354753557535675357753587535975360753617536275363753647536575366753677536875369753707537175372753737537475375753767537775378753797538075381753827538375384753857538675387753887538975390753917539275393753947539575396753977539875399754007540175402754037540475405754067540775408754097541075411754127541375414754157541675417754187541975420754217542275423754247542575426754277542875429754307543175432754337543475435754367543775438754397544075441754427544375444754457544675447754487544975450754517545275453754547545575456754577545875459754607546175462754637546475465754667546775468754697547075471754727547375474754757547675477754787547975480754817548275483754847548575486754877548875489754907549175492754937549475495754967549775498754997550075501755027550375504755057550675507755087550975510755117551275513755147551575516755177551875519755207552175522755237552475525755267552775528755297553075531755327553375534755357553675537755387553975540755417554275543755447554575546755477554875549755507555175552755537555475555755567555775558755597556075561755627556375564755657556675567755687556975570755717557275573755747557575576755777557875579755807558175582755837558475585755867558775588755897559075591755927559375594755957559675597755987559975600756017560275603756047560575606756077560875609756107561175612756137561475615756167561775618756197562075621756227562375624756257562675627756287562975630756317563275633756347563575636756377563875639756407564175642756437564475645756467564775648756497565075651756527565375654756557565675657756587565975660756617566275663756647566575666756677566875669756707567175672756737567475675756767567775678756797568075681756827568375684756857568675687756887568975690756917569275693756947569575696756977569875699757007570175702757037570475705757067570775708757097571075711757127571375714757157571675717757187571975720757217572275723757247572575726757277572875729757307573175732757337573475735757367573775738757397574075741757427574375744757457574675747757487574975750757517575275753757547575575756757577575875759757607576175762757637576475765757667576775768757697577075771757727577375774757757577675777757787577975780757817578275783757847578575786757877578875789757907579175792757937579475795757967579775798757997580075801758027580375804758057580675807758087580975810758117581275813758147581575816758177581875819758207582175822758237582475825758267582775828758297583075831758327583375834758357583675837758387583975840758417584275843758447584575846758477584875849758507585175852758537585475855758567585775858758597586075861758627586375864758657586675867758687586975870758717587275873758747587575876758777587875879758807588175882758837588475885758867588775888758897589075891758927589375894758957589675897758987589975900759017590275903759047590575906759077590875909759107591175912759137591475915759167591775918759197592075921759227592375924759257592675927759287592975930759317593275933759347593575936759377593875939759407594175942759437594475945759467594775948759497595075951759527595375954759557595675957759587595975960759617596275963759647596575966759677596875969759707597175972759737597475975759767597775978759797598075981759827598375984759857598675987759887598975990759917599275993759947599575996759977599875999760007600176002760037600476005760067600776008760097601076011760127601376014760157601676017760187601976020760217602276023760247602576026760277602876029760307603176032760337603476035760367603776038760397604076041760427604376044760457604676047760487604976050760517605276053760547605576056760577605876059760607606176062760637606476065760667606776068760697607076071760727607376074760757607676077760787607976080760817608276083760847608576086760877608876089760907609176092760937609476095760967609776098760997610076101761027610376104761057610676107761087610976110761117611276113761147611576116761177611876119761207612176122761237612476125761267612776128761297613076131761327613376134761357613676137761387613976140761417614276143761447614576146761477614876149761507615176152761537615476155761567615776158761597616076161761627616376164761657616676167761687616976170761717617276173761747617576176761777617876179761807618176182761837618476185761867618776188761897619076191761927619376194761957619676197761987619976200762017620276203762047620576206762077620876209762107621176212762137621476215762167621776218762197622076221762227622376224762257622676227762287622976230762317623276233762347623576236762377623876239762407624176242762437624476245762467624776248762497625076251762527625376254762557625676257762587625976260762617626276263762647626576266762677626876269762707627176272762737627476275762767627776278762797628076281762827628376284762857628676287762887628976290762917629276293762947629576296762977629876299763007630176302763037630476305763067630776308763097631076311763127631376314763157631676317763187631976320763217632276323763247632576326763277632876329763307633176332763337633476335763367633776338763397634076341763427634376344763457634676347763487634976350763517635276353763547635576356763577635876359763607636176362763637636476365763667636776368763697637076371763727637376374763757637676377763787637976380763817638276383763847638576386763877638876389763907639176392763937639476395763967639776398763997640076401764027640376404764057640676407764087640976410764117641276413764147641576416764177641876419764207642176422764237642476425764267642776428764297643076431764327643376434764357643676437764387643976440764417644276443764447644576446764477644876449764507645176452764537645476455764567645776458764597646076461764627646376464764657646676467764687646976470764717647276473764747647576476764777647876479764807648176482764837648476485764867648776488764897649076491764927649376494764957649676497764987649976500765017650276503765047650576506765077650876509765107651176512765137651476515765167651776518765197652076521765227652376524765257652676527765287652976530765317653276533765347653576536765377653876539765407654176542765437654476545765467654776548765497655076551765527655376554765557655676557765587655976560765617656276563765647656576566765677656876569765707657176572765737657476575765767657776578765797658076581765827658376584765857658676587765887658976590765917659276593765947659576596765977659876599766007660176602766037660476605766067660776608766097661076611766127661376614766157661676617766187661976620766217662276623766247662576626766277662876629766307663176632766337663476635766367663776638766397664076641766427664376644766457664676647766487664976650766517665276653766547665576656766577665876659766607666176662766637666476665766667666776668766697667076671766727667376674766757667676677766787667976680766817668276683766847668576686766877668876689766907669176692766937669476695766967669776698766997670076701767027670376704767057670676707767087670976710767117671276713767147671576716767177671876719767207672176722767237672476725767267672776728767297673076731767327673376734767357673676737767387673976740767417674276743767447674576746767477674876749767507675176752767537675476755767567675776758767597676076761767627676376764767657676676767767687676976770767717677276773767747677576776767777677876779767807678176782767837678476785767867678776788767897679076791767927679376794767957679676797767987679976800768017680276803768047680576806768077680876809768107681176812768137681476815768167681776818768197682076821768227682376824768257682676827768287682976830768317683276833768347683576836768377683876839768407684176842768437684476845768467684776848768497685076851768527685376854768557685676857768587685976860768617686276863768647686576866768677686876869768707687176872768737687476875768767687776878768797688076881768827688376884768857688676887768887688976890768917689276893768947689576896768977689876899769007690176902769037690476905769067690776908769097691076911769127691376914769157691676917769187691976920769217692276923769247692576926769277692876929769307693176932769337693476935769367693776938769397694076941769427694376944769457694676947769487694976950769517695276953769547695576956769577695876959769607696176962769637696476965769667696776968769697697076971769727697376974769757697676977769787697976980769817698276983769847698576986769877698876989769907699176992769937699476995769967699776998769997700077001770027700377004770057700677007770087700977010770117701277013770147701577016770177701877019770207702177022770237702477025770267702777028770297703077031770327703377034770357703677037770387703977040770417704277043770447704577046770477704877049770507705177052770537705477055770567705777058770597706077061770627706377064770657706677067770687706977070770717707277073770747707577076770777707877079770807708177082770837708477085770867708777088770897709077091770927709377094770957709677097770987709977100771017710277103771047710577106771077710877109771107711177112771137711477115771167711777118771197712077121771227712377124771257712677127771287712977130771317713277133771347713577136771377713877139771407714177142771437714477145771467714777148771497715077151771527715377154771557715677157771587715977160771617716277163771647716577166771677716877169771707717177172771737717477175771767717777178771797718077181771827718377184771857718677187771887718977190771917719277193771947719577196771977719877199772007720177202772037720477205772067720777208772097721077211772127721377214772157721677217772187721977220772217722277223772247722577226772277722877229772307723177232772337723477235772367723777238772397724077241772427724377244772457724677247772487724977250772517725277253772547725577256772577725877259772607726177262772637726477265772667726777268772697727077271772727727377274772757727677277772787727977280772817728277283772847728577286772877728877289772907729177292772937729477295772967729777298772997730077301773027730377304773057730677307773087730977310773117731277313773147731577316773177731877319773207732177322773237732477325773267732777328773297733077331773327733377334773357733677337773387733977340773417734277343773447734577346773477734877349773507735177352773537735477355773567735777358773597736077361773627736377364773657736677367773687736977370773717737277373773747737577376773777737877379773807738177382773837738477385773867738777388773897739077391773927739377394773957739677397773987739977400774017740277403774047740577406774077740877409774107741177412774137741477415774167741777418774197742077421774227742377424774257742677427774287742977430774317743277433774347743577436774377743877439774407744177442774437744477445774467744777448774497745077451774527745377454774557745677457774587745977460774617746277463774647746577466774677746877469774707747177472774737747477475774767747777478774797748077481774827748377484774857748677487774887748977490774917749277493774947749577496774977749877499775007750177502775037750477505775067750777508775097751077511775127751377514775157751677517775187751977520775217752277523775247752577526775277752877529775307753177532775337753477535775367753777538775397754077541775427754377544775457754677547775487754977550775517755277553775547755577556775577755877559775607756177562775637756477565775667756777568775697757077571775727757377574775757757677577775787757977580775817758277583775847758577586775877758877589775907759177592775937759477595775967759777598775997760077601776027760377604776057760677607776087760977610776117761277613776147761577616776177761877619776207762177622776237762477625776267762777628776297763077631776327763377634776357763677637776387763977640776417764277643776447764577646776477764877649776507765177652776537765477655776567765777658776597766077661776627766377664776657766677667776687766977670776717767277673776747767577676776777767877679776807768177682776837768477685776867768777688776897769077691776927769377694776957769677697776987769977700777017770277703777047770577706777077770877709777107771177712777137771477715777167771777718777197772077721777227772377724777257772677727777287772977730777317773277733777347773577736777377773877739777407774177742777437774477745777467774777748777497775077751777527775377754777557775677757777587775977760777617776277763777647776577766777677776877769777707777177772777737777477775777767777777778777797778077781777827778377784777857778677787777887778977790777917779277793777947779577796777977779877799778007780177802778037780477805778067780777808778097781077811778127781377814778157781677817778187781977820778217782277823778247782577826778277782877829778307783177832778337783477835778367783777838778397784077841778427784377844778457784677847778487784977850778517785277853778547785577856778577785877859778607786177862778637786477865778667786777868778697787077871778727787377874778757787677877778787787977880778817788277883778847788577886778877788877889778907789177892778937789477895778967789777898778997790077901779027790377904779057790677907779087790977910779117791277913779147791577916779177791877919779207792177922779237792477925779267792777928779297793077931779327793377934779357793677937779387793977940779417794277943779447794577946779477794877949779507795177952779537795477955779567795777958779597796077961779627796377964779657796677967779687796977970779717797277973779747797577976779777797877979779807798177982779837798477985779867798777988779897799077991779927799377994779957799677997779987799978000780017800278003780047800578006780077800878009780107801178012780137801478015780167801778018780197802078021780227802378024780257802678027780287802978030780317803278033780347803578036780377803878039780407804178042780437804478045780467804778048780497805078051780527805378054780557805678057780587805978060780617806278063780647806578066780677806878069780707807178072780737807478075780767807778078780797808078081780827808378084780857808678087780887808978090780917809278093780947809578096780977809878099781007810178102781037810478105781067810778108781097811078111781127811378114781157811678117781187811978120781217812278123781247812578126781277812878129781307813178132781337813478135781367813778138781397814078141781427814378144781457814678147781487814978150781517815278153781547815578156781577815878159781607816178162781637816478165781667816778168781697817078171781727817378174781757817678177781787817978180781817818278183781847818578186781877818878189781907819178192781937819478195781967819778198781997820078201782027820378204782057820678207782087820978210782117821278213782147821578216782177821878219782207822178222782237822478225782267822778228782297823078231782327823378234782357823678237782387823978240782417824278243782447824578246782477824878249782507825178252782537825478255782567825778258782597826078261782627826378264782657826678267782687826978270782717827278273782747827578276782777827878279782807828178282782837828478285782867828778288782897829078291782927829378294782957829678297782987829978300783017830278303783047830578306783077830878309783107831178312783137831478315783167831778318783197832078321783227832378324783257832678327783287832978330783317833278333783347833578336783377833878339783407834178342783437834478345783467834778348783497835078351783527835378354783557835678357783587835978360783617836278363783647836578366783677836878369783707837178372783737837478375783767837778378783797838078381783827838378384783857838678387783887838978390783917839278393783947839578396783977839878399784007840178402784037840478405784067840778408784097841078411784127841378414784157841678417784187841978420784217842278423784247842578426784277842878429784307843178432784337843478435784367843778438784397844078441784427844378444784457844678447784487844978450784517845278453784547845578456784577845878459784607846178462784637846478465784667846778468784697847078471784727847378474784757847678477784787847978480784817848278483784847848578486784877848878489784907849178492784937849478495784967849778498784997850078501785027850378504785057850678507785087850978510785117851278513785147851578516785177851878519785207852178522785237852478525785267852778528785297853078531785327853378534785357853678537785387853978540785417854278543785447854578546785477854878549785507855178552785537855478555785567855778558785597856078561785627856378564785657856678567785687856978570785717857278573785747857578576785777857878579785807858178582785837858478585785867858778588785897859078591785927859378594785957859678597785987859978600786017860278603786047860578606786077860878609786107861178612786137861478615786167861778618786197862078621786227862378624786257862678627786287862978630786317863278633786347863578636786377863878639786407864178642786437864478645786467864778648786497865078651786527865378654786557865678657786587865978660786617866278663786647866578666786677866878669786707867178672786737867478675786767867778678786797868078681786827868378684786857868678687786887868978690786917869278693786947869578696786977869878699787007870178702787037870478705787067870778708787097871078711787127871378714787157871678717787187871978720787217872278723787247872578726787277872878729787307873178732787337873478735787367873778738787397874078741787427874378744787457874678747787487874978750787517875278753787547875578756787577875878759787607876178762787637876478765787667876778768787697877078771787727877378774787757877678777787787877978780787817878278783787847878578786787877878878789787907879178792787937879478795787967879778798787997880078801788027880378804788057880678807788087880978810788117881278813788147881578816788177881878819788207882178822788237882478825788267882778828788297883078831788327883378834788357883678837788387883978840788417884278843788447884578846788477884878849788507885178852788537885478855788567885778858788597886078861788627886378864788657886678867788687886978870788717887278873788747887578876788777887878879788807888178882788837888478885788867888778888788897889078891788927889378894788957889678897788987889978900789017890278903789047890578906789077890878909789107891178912789137891478915789167891778918789197892078921789227892378924789257892678927789287892978930789317893278933789347893578936789377893878939789407894178942789437894478945789467894778948789497895078951789527895378954789557895678957789587895978960789617896278963789647896578966789677896878969789707897178972789737897478975789767897778978789797898078981789827898378984789857898678987789887898978990789917899278993789947899578996789977899878999790007900179002790037900479005790067900779008790097901079011790127901379014790157901679017790187901979020790217902279023790247902579026790277902879029790307903179032790337903479035790367903779038790397904079041790427904379044790457904679047790487904979050790517905279053790547905579056790577905879059790607906179062790637906479065790667906779068790697907079071790727907379074790757907679077790787907979080790817908279083790847908579086790877908879089790907909179092790937909479095790967909779098790997910079101791027910379104791057910679107791087910979110791117911279113791147911579116791177911879119791207912179122791237912479125791267912779128791297913079131791327913379134791357913679137791387913979140791417914279143791447914579146791477914879149791507915179152791537915479155791567915779158791597916079161791627916379164791657916679167791687916979170791717917279173791747917579176791777917879179791807918179182791837918479185791867918779188791897919079191791927919379194791957919679197791987919979200792017920279203792047920579206792077920879209792107921179212792137921479215792167921779218792197922079221792227922379224792257922679227792287922979230792317923279233792347923579236792377923879239792407924179242792437924479245792467924779248792497925079251792527925379254792557925679257792587925979260792617926279263792647926579266792677926879269792707927179272792737927479275792767927779278792797928079281792827928379284792857928679287792887928979290792917929279293792947929579296792977929879299793007930179302793037930479305793067930779308793097931079311793127931379314793157931679317793187931979320793217932279323793247932579326793277932879329793307933179332793337933479335793367933779338793397934079341793427934379344793457934679347793487934979350793517935279353793547935579356793577935879359793607936179362793637936479365793667936779368793697937079371793727937379374793757937679377793787937979380793817938279383793847938579386793877938879389793907939179392793937939479395793967939779398793997940079401794027940379404794057940679407794087940979410794117941279413794147941579416794177941879419794207942179422794237942479425794267942779428794297943079431794327943379434794357943679437794387943979440794417944279443794447944579446794477944879449794507945179452794537945479455794567945779458794597946079461794627946379464794657946679467794687946979470794717947279473794747947579476794777947879479794807948179482794837948479485794867948779488794897949079491794927949379494794957949679497794987949979500795017950279503795047950579506795077950879509795107951179512795137951479515795167951779518795197952079521795227952379524795257952679527795287952979530795317953279533795347953579536795377953879539795407954179542795437954479545795467954779548795497955079551795527955379554795557955679557795587955979560795617956279563795647956579566795677956879569795707957179572795737957479575795767957779578795797958079581795827958379584795857958679587795887958979590795917959279593795947959579596795977959879599796007960179602796037960479605796067960779608796097961079611796127961379614796157961679617796187961979620796217962279623796247962579626796277962879629796307963179632796337963479635796367963779638796397964079641796427964379644796457964679647796487964979650796517965279653796547965579656796577965879659796607966179662796637966479665796667966779668796697967079671796727967379674796757967679677796787967979680796817968279683796847968579686796877968879689796907969179692796937969479695796967969779698796997970079701797027970379704797057970679707797087970979710797117971279713797147971579716797177971879719797207972179722797237972479725797267972779728797297973079731797327973379734797357973679737797387973979740797417974279743797447974579746797477974879749797507975179752797537975479755797567975779758797597976079761797627976379764797657976679767797687976979770797717977279773797747977579776797777977879779797807978179782797837978479785797867978779788797897979079791797927979379794797957979679797797987979979800798017980279803798047980579806798077980879809798107981179812798137981479815798167981779818798197982079821798227982379824798257982679827798287982979830798317983279833798347983579836798377983879839798407984179842798437984479845798467984779848798497985079851798527985379854798557985679857798587985979860798617986279863798647986579866798677986879869798707987179872798737987479875798767987779878798797988079881798827988379884798857988679887798887988979890798917989279893798947989579896798977989879899799007990179902799037990479905799067990779908799097991079911799127991379914799157991679917799187991979920799217992279923799247992579926799277992879929799307993179932799337993479935799367993779938799397994079941799427994379944799457994679947799487994979950799517995279953799547995579956799577995879959799607996179962799637996479965799667996779968799697997079971799727997379974799757997679977799787997979980799817998279983799847998579986799877998879989799907999179992799937999479995799967999779998799998000080001800028000380004800058000680007800088000980010800118001280013800148001580016800178001880019800208002180022800238002480025800268002780028800298003080031800328003380034800358003680037800388003980040800418004280043800448004580046800478004880049800508005180052800538005480055800568005780058800598006080061800628006380064800658006680067800688006980070800718007280073800748007580076800778007880079800808008180082800838008480085800868008780088800898009080091800928009380094800958009680097800988009980100801018010280103801048010580106801078010880109801108011180112801138011480115801168011780118801198012080121801228012380124801258012680127801288012980130801318013280133801348013580136801378013880139801408014180142801438014480145801468014780148801498015080151801528015380154801558015680157801588015980160801618016280163801648016580166801678016880169801708017180172801738017480175801768017780178801798018080181801828018380184801858018680187801888018980190801918019280193801948019580196801978019880199802008020180202802038020480205802068020780208802098021080211802128021380214802158021680217802188021980220802218022280223802248022580226802278022880229802308023180232802338023480235802368023780238802398024080241802428024380244802458024680247802488024980250802518025280253802548025580256802578025880259802608026180262802638026480265802668026780268802698027080271802728027380274802758027680277802788027980280802818028280283802848028580286802878028880289802908029180292802938029480295802968029780298802998030080301803028030380304803058030680307803088030980310803118031280313803148031580316803178031880319803208032180322803238032480325803268032780328803298033080331803328033380334803358033680337803388033980340803418034280343803448034580346803478034880349803508035180352803538035480355803568035780358803598036080361803628036380364803658036680367803688036980370803718037280373803748037580376803778037880379803808038180382803838038480385803868038780388803898039080391803928039380394803958039680397803988039980400804018040280403804048040580406804078040880409804108041180412804138041480415804168041780418804198042080421804228042380424804258042680427804288042980430804318043280433804348043580436804378043880439804408044180442804438044480445804468044780448804498045080451804528045380454804558045680457804588045980460804618046280463804648046580466804678046880469804708047180472804738047480475804768047780478804798048080481804828048380484804858048680487804888048980490804918049280493804948049580496804978049880499805008050180502805038050480505805068050780508805098051080511805128051380514805158051680517805188051980520805218052280523805248052580526805278052880529805308053180532805338053480535805368053780538805398054080541805428054380544805458054680547805488054980550805518055280553805548055580556805578055880559805608056180562805638056480565805668056780568805698057080571805728057380574805758057680577805788057980580805818058280583805848058580586805878058880589805908059180592805938059480595805968059780598805998060080601806028060380604806058060680607806088060980610806118061280613806148061580616806178061880619806208062180622806238062480625806268062780628806298063080631806328063380634806358063680637806388063980640806418064280643806448064580646806478064880649806508065180652806538065480655806568065780658806598066080661806628066380664806658066680667806688066980670806718067280673806748067580676806778067880679806808068180682806838068480685806868068780688806898069080691806928069380694806958069680697806988069980700807018070280703807048070580706807078070880709807108071180712807138071480715807168071780718807198072080721807228072380724807258072680727807288072980730807318073280733807348073580736807378073880739807408074180742807438074480745807468074780748807498075080751807528075380754807558075680757807588075980760807618076280763807648076580766807678076880769807708077180772807738077480775807768077780778807798078080781807828078380784807858078680787807888078980790807918079280793807948079580796807978079880799808008080180802808038080480805808068080780808808098081080811808128081380814808158081680817808188081980820808218082280823808248082580826808278082880829808308083180832808338083480835808368083780838808398084080841808428084380844808458084680847808488084980850808518085280853808548085580856808578085880859808608086180862808638086480865808668086780868808698087080871808728087380874808758087680877808788087980880808818088280883808848088580886808878088880889808908089180892808938089480895808968089780898808998090080901809028090380904809058090680907809088090980910809118091280913809148091580916809178091880919809208092180922809238092480925809268092780928809298093080931809328093380934809358093680937809388093980940809418094280943809448094580946809478094880949809508095180952809538095480955809568095780958809598096080961809628096380964809658096680967809688096980970809718097280973809748097580976809778097880979809808098180982809838098480985809868098780988809898099080991809928099380994809958099680997809988099981000810018100281003810048100581006810078100881009810108101181012810138101481015810168101781018810198102081021810228102381024810258102681027810288102981030810318103281033810348103581036810378103881039810408104181042810438104481045810468104781048810498105081051810528105381054810558105681057810588105981060810618106281063810648106581066810678106881069810708107181072810738107481075810768107781078810798108081081810828108381084810858108681087810888108981090810918109281093810948109581096810978109881099811008110181102811038110481105811068110781108811098111081111811128111381114811158111681117811188111981120811218112281123811248112581126811278112881129811308113181132811338113481135811368113781138811398114081141811428114381144811458114681147811488114981150811518115281153811548115581156811578115881159811608116181162811638116481165811668116781168811698117081171811728117381174811758117681177811788117981180811818118281183811848118581186811878118881189811908119181192811938119481195811968119781198811998120081201812028120381204812058120681207812088120981210812118121281213812148121581216812178121881219812208122181222812238122481225812268122781228812298123081231812328123381234812358123681237812388123981240812418124281243812448124581246812478124881249812508125181252812538125481255812568125781258812598126081261812628126381264812658126681267812688126981270812718127281273812748127581276812778127881279812808128181282812838128481285812868128781288812898129081291812928129381294812958129681297812988129981300813018130281303813048130581306813078130881309813108131181312813138131481315813168131781318813198132081321813228132381324813258132681327813288132981330813318133281333813348133581336813378133881339813408134181342813438134481345813468134781348813498135081351813528135381354813558135681357813588135981360813618136281363813648136581366813678136881369813708137181372813738137481375813768137781378813798138081381813828138381384813858138681387813888138981390813918139281393813948139581396813978139881399814008140181402814038140481405814068140781408814098141081411814128141381414814158141681417814188141981420814218142281423814248142581426814278142881429814308143181432814338143481435814368143781438814398144081441814428144381444814458144681447814488144981450814518145281453814548145581456814578145881459814608146181462814638146481465814668146781468814698147081471814728147381474814758147681477814788147981480814818148281483814848148581486814878148881489814908149181492814938149481495814968149781498814998150081501815028150381504815058150681507815088150981510815118151281513815148151581516815178151881519815208152181522815238152481525815268152781528815298153081531815328153381534815358153681537815388153981540815418154281543815448154581546815478154881549815508155181552815538155481555815568155781558815598156081561815628156381564815658156681567815688156981570815718157281573815748157581576815778157881579815808158181582815838158481585815868158781588815898159081591815928159381594815958159681597815988159981600816018160281603816048160581606816078160881609816108161181612816138161481615816168161781618816198162081621816228162381624816258162681627816288162981630816318163281633816348163581636816378163881639816408164181642816438164481645816468164781648816498165081651816528165381654816558165681657816588165981660816618166281663816648166581666816678166881669816708167181672816738167481675816768167781678816798168081681816828168381684816858168681687816888168981690816918169281693816948169581696816978169881699817008170181702817038170481705817068170781708817098171081711817128171381714817158171681717817188171981720817218172281723817248172581726817278172881729817308173181732817338173481735817368173781738817398174081741817428174381744817458174681747817488174981750817518175281753817548175581756817578175881759817608176181762817638176481765817668176781768817698177081771817728177381774817758177681777817788177981780817818178281783817848178581786817878178881789817908179181792817938179481795817968179781798817998180081801818028180381804818058180681807818088180981810818118181281813818148181581816818178181881819818208182181822818238182481825818268182781828818298183081831818328183381834818358183681837818388183981840818418184281843818448184581846818478184881849818508185181852818538185481855818568185781858818598186081861818628186381864818658186681867818688186981870818718187281873818748187581876818778187881879818808188181882818838188481885818868188781888818898189081891818928189381894818958189681897818988189981900819018190281903819048190581906819078190881909819108191181912819138191481915819168191781918819198192081921819228192381924819258192681927819288192981930819318193281933819348193581936819378193881939819408194181942819438194481945819468194781948819498195081951819528195381954819558195681957819588195981960819618196281963819648196581966819678196881969819708197181972819738197481975819768197781978819798198081981819828198381984819858198681987819888198981990819918199281993819948199581996819978199881999820008200182002820038200482005820068200782008820098201082011820128201382014820158201682017820188201982020820218202282023820248202582026820278202882029820308203182032820338203482035820368203782038820398204082041820428204382044820458204682047820488204982050820518205282053820548205582056820578205882059820608206182062820638206482065820668206782068820698207082071820728207382074820758207682077820788207982080820818208282083820848208582086820878208882089820908209182092820938209482095820968209782098820998210082101821028210382104821058210682107821088210982110821118211282113821148211582116821178211882119821208212182122821238212482125821268212782128821298213082131821328213382134821358213682137821388213982140821418214282143821448214582146821478214882149821508215182152821538215482155821568215782158821598216082161821628216382164821658216682167821688216982170821718217282173821748217582176821778217882179821808218182182821838218482185821868218782188821898219082191821928219382194821958219682197821988219982200822018220282203822048220582206822078220882209822108221182212822138221482215822168221782218822198222082221822228222382224822258222682227822288222982230822318223282233822348223582236822378223882239822408224182242822438224482245822468224782248822498225082251822528225382254822558225682257822588225982260822618226282263822648226582266822678226882269822708227182272822738227482275822768227782278822798228082281822828228382284822858228682287822888228982290822918229282293822948229582296822978229882299823008230182302823038230482305823068230782308823098231082311823128231382314823158231682317823188231982320823218232282323823248232582326823278232882329823308233182332823338233482335823368233782338823398234082341823428234382344823458234682347823488234982350823518235282353823548235582356823578235882359823608236182362823638236482365823668236782368823698237082371823728237382374823758237682377823788237982380823818238282383823848238582386823878238882389823908239182392823938239482395823968239782398823998240082401824028240382404824058240682407824088240982410824118241282413824148241582416824178241882419824208242182422824238242482425824268242782428824298243082431824328243382434824358243682437824388243982440824418244282443824448244582446824478244882449824508245182452824538245482455824568245782458824598246082461824628246382464824658246682467824688246982470824718247282473824748247582476824778247882479824808248182482824838248482485824868248782488824898249082491824928249382494824958249682497824988249982500825018250282503825048250582506825078250882509825108251182512825138251482515825168251782518825198252082521825228252382524825258252682527825288252982530825318253282533825348253582536825378253882539825408254182542825438254482545825468254782548825498255082551825528255382554825558255682557825588255982560825618256282563825648256582566825678256882569825708257182572825738257482575825768257782578825798258082581825828258382584825858258682587825888258982590825918259282593825948259582596825978259882599826008260182602826038260482605826068260782608826098261082611826128261382614826158261682617826188261982620826218262282623826248262582626826278262882629826308263182632826338263482635826368263782638826398264082641826428264382644826458264682647826488264982650826518265282653826548265582656826578265882659826608266182662826638266482665826668266782668826698267082671826728267382674826758267682677826788267982680826818268282683826848268582686826878268882689826908269182692826938269482695826968269782698826998270082701827028270382704827058270682707827088270982710827118271282713827148271582716827178271882719827208272182722827238272482725827268272782728827298273082731827328273382734827358273682737827388273982740827418274282743827448274582746827478274882749827508275182752827538275482755827568275782758827598276082761827628276382764827658276682767827688276982770827718277282773827748277582776827778277882779827808278182782827838278482785827868278782788827898279082791827928279382794827958279682797827988279982800828018280282803828048280582806828078280882809828108281182812828138281482815828168281782818828198282082821828228282382824828258282682827828288282982830828318283282833828348283582836828378283882839828408284182842828438284482845828468284782848828498285082851828528285382854828558285682857828588285982860828618286282863828648286582866828678286882869828708287182872828738287482875828768287782878828798288082881828828288382884828858288682887828888288982890828918289282893828948289582896828978289882899829008290182902829038290482905829068290782908829098291082911829128291382914829158291682917829188291982920829218292282923829248292582926829278292882929829308293182932829338293482935829368293782938829398294082941829428294382944829458294682947829488294982950829518295282953829548295582956829578295882959829608296182962829638296482965829668296782968829698297082971829728297382974829758297682977829788297982980829818298282983829848298582986829878298882989829908299182992829938299482995829968299782998829998300083001830028300383004830058300683007830088300983010830118301283013830148301583016830178301883019830208302183022830238302483025830268302783028830298303083031830328303383034830358303683037830388303983040830418304283043830448304583046830478304883049830508305183052830538305483055830568305783058830598306083061830628306383064830658306683067830688306983070830718307283073830748307583076830778307883079830808308183082830838308483085830868308783088830898309083091830928309383094830958309683097830988309983100831018310283103831048310583106831078310883109831108311183112831138311483115831168311783118831198312083121831228312383124831258312683127831288312983130831318313283133831348313583136831378313883139831408314183142831438314483145831468314783148831498315083151831528315383154831558315683157831588315983160831618316283163831648316583166831678316883169831708317183172831738317483175831768317783178831798318083181831828318383184831858318683187831888318983190831918319283193831948319583196831978319883199832008320183202832038320483205832068320783208832098321083211832128321383214832158321683217832188321983220832218322283223832248322583226832278322883229832308323183232832338323483235832368323783238832398324083241832428324383244832458324683247832488324983250832518325283253832548325583256832578325883259832608326183262832638326483265832668326783268832698327083271832728327383274832758327683277832788327983280832818328283283832848328583286832878328883289832908329183292832938329483295832968329783298832998330083301833028330383304833058330683307833088330983310833118331283313833148331583316833178331883319833208332183322833238332483325833268332783328833298333083331833328333383334833358333683337833388333983340833418334283343833448334583346833478334883349833508335183352833538335483355833568335783358833598336083361833628336383364833658336683367833688336983370833718337283373833748337583376833778337883379833808338183382833838338483385833868338783388833898339083391833928339383394833958339683397833988339983400834018340283403834048340583406834078340883409834108341183412834138341483415834168341783418834198342083421834228342383424834258342683427834288342983430834318343283433834348343583436834378343883439834408344183442834438344483445834468344783448834498345083451834528345383454834558345683457834588345983460834618346283463834648346583466834678346883469834708347183472834738347483475834768347783478834798348083481834828348383484834858348683487834888348983490834918349283493834948349583496834978349883499835008350183502835038350483505835068350783508835098351083511835128351383514835158351683517835188351983520835218352283523835248352583526835278352883529835308353183532835338353483535835368353783538835398354083541835428354383544835458354683547835488354983550835518355283553835548355583556835578355883559835608356183562835638356483565835668356783568835698357083571835728357383574835758357683577835788357983580835818358283583835848358583586835878358883589835908359183592835938359483595835968359783598835998360083601836028360383604836058360683607836088360983610836118361283613836148361583616836178361883619836208362183622836238362483625836268362783628836298363083631836328363383634836358363683637836388363983640836418364283643836448364583646836478364883649836508365183652836538365483655836568365783658836598366083661836628366383664836658366683667836688366983670836718367283673836748367583676836778367883679836808368183682836838368483685836868368783688836898369083691836928369383694836958369683697836988369983700837018370283703837048370583706837078370883709837108371183712837138371483715837168371783718837198372083721837228372383724837258372683727837288372983730837318373283733837348373583736837378373883739837408374183742837438374483745837468374783748837498375083751837528375383754837558375683757837588375983760837618376283763837648376583766837678376883769837708377183772837738377483775837768377783778837798378083781837828378383784837858378683787837888378983790837918379283793837948379583796837978379883799838008380183802838038380483805838068380783808838098381083811838128381383814838158381683817838188381983820838218382283823838248382583826838278382883829838308383183832838338383483835838368383783838838398384083841838428384383844838458384683847838488384983850838518385283853838548385583856838578385883859838608386183862838638386483865838668386783868838698387083871838728387383874838758387683877838788387983880838818388283883838848388583886838878388883889838908389183892838938389483895838968389783898838998390083901839028390383904839058390683907839088390983910839118391283913839148391583916839178391883919839208392183922839238392483925839268392783928839298393083931839328393383934839358393683937839388393983940839418394283943839448394583946839478394883949839508395183952839538395483955839568395783958839598396083961839628396383964839658396683967839688396983970839718397283973839748397583976839778397883979839808398183982839838398483985839868398783988839898399083991839928399383994839958399683997839988399984000840018400284003840048400584006840078400884009840108401184012840138401484015840168401784018840198402084021840228402384024840258402684027840288402984030840318403284033840348403584036840378403884039840408404184042840438404484045840468404784048840498405084051840528405384054840558405684057840588405984060840618406284063840648406584066840678406884069840708407184072840738407484075840768407784078840798408084081840828408384084840858408684087840888408984090840918409284093840948409584096840978409884099841008410184102841038410484105841068410784108841098411084111841128411384114841158411684117841188411984120841218412284123841248412584126841278412884129841308413184132841338413484135841368413784138841398414084141841428414384144841458414684147841488414984150841518415284153841548415584156841578415884159841608416184162841638416484165841668416784168841698417084171841728417384174841758417684177841788417984180841818418284183841848418584186841878418884189841908419184192841938419484195841968419784198841998420084201842028420384204842058420684207842088420984210842118421284213842148421584216842178421884219842208422184222842238422484225842268422784228842298423084231842328423384234842358423684237842388423984240842418424284243842448424584246842478424884249842508425184252842538425484255842568425784258842598426084261842628426384264842658426684267842688426984270842718427284273842748427584276842778427884279842808428184282842838428484285842868428784288842898429084291842928429384294842958429684297842988429984300843018430284303843048430584306843078430884309843108431184312843138431484315843168431784318843198432084321843228432384324843258432684327843288432984330843318433284333843348433584336843378433884339843408434184342843438434484345843468434784348843498435084351843528435384354843558435684357843588435984360843618436284363843648436584366843678436884369843708437184372843738437484375843768437784378843798438084381843828438384384843858438684387843888438984390843918439284393843948439584396843978439884399844008440184402844038440484405844068440784408844098441084411844128441384414844158441684417844188441984420844218442284423844248442584426844278442884429844308443184432844338443484435844368443784438844398444084441844428444384444844458444684447844488444984450844518445284453844548445584456844578445884459844608446184462844638446484465844668446784468844698447084471844728447384474844758447684477844788447984480844818448284483844848448584486844878448884489844908449184492844938449484495844968449784498844998450084501845028450384504845058450684507845088450984510845118451284513845148451584516845178451884519845208452184522845238452484525845268452784528845298453084531845328453384534845358453684537845388453984540845418454284543845448454584546845478454884549845508455184552845538455484555845568455784558845598456084561845628456384564845658456684567845688456984570845718457284573845748457584576845778457884579845808458184582845838458484585845868458784588845898459084591845928459384594845958459684597845988459984600846018460284603846048460584606846078460884609846108461184612846138461484615846168461784618846198462084621846228462384624846258462684627846288462984630846318463284633846348463584636846378463884639846408464184642846438464484645846468464784648846498465084651846528465384654846558465684657846588465984660846618466284663846648466584666846678466884669846708467184672846738467484675846768467784678846798468084681846828468384684846858468684687846888468984690846918469284693846948469584696846978469884699847008470184702847038470484705847068470784708847098471084711847128471384714847158471684717847188471984720847218472284723847248472584726847278472884729847308473184732847338473484735847368473784738847398474084741847428474384744847458474684747847488474984750847518475284753847548475584756847578475884759847608476184762847638476484765847668476784768847698477084771847728477384774847758477684777847788477984780847818478284783847848478584786847878478884789847908479184792847938479484795847968479784798847998480084801848028480384804848058480684807848088480984810848118481284813848148481584816848178481884819848208482184822848238482484825848268482784828848298483084831848328483384834848358483684837848388483984840848418484284843848448484584846848478484884849848508485184852848538485484855848568485784858848598486084861848628486384864848658486684867848688486984870848718487284873848748487584876848778487884879848808488184882848838488484885848868488784888848898489084891848928489384894848958489684897848988489984900849018490284903849048490584906849078490884909849108491184912849138491484915849168491784918849198492084921849228492384924849258492684927849288492984930849318493284933849348493584936849378493884939849408494184942849438494484945849468494784948849498495084951849528495384954849558495684957849588495984960849618496284963849648496584966849678496884969849708497184972849738497484975849768497784978849798498084981849828498384984849858498684987849888498984990849918499284993849948499584996849978499884999850008500185002850038500485005850068500785008850098501085011850128501385014850158501685017850188501985020850218502285023850248502585026850278502885029850308503185032850338503485035850368503785038850398504085041850428504385044850458504685047850488504985050850518505285053850548505585056850578505885059850608506185062850638506485065850668506785068850698507085071850728507385074850758507685077850788507985080850818508285083850848508585086850878508885089850908509185092850938509485095850968509785098850998510085101851028510385104851058510685107851088510985110851118511285113851148511585116851178511885119851208512185122851238512485125851268512785128851298513085131851328513385134851358513685137851388513985140851418514285143851448514585146851478514885149851508515185152851538515485155851568515785158851598516085161851628516385164851658516685167851688516985170851718517285173851748517585176851778517885179851808518185182851838518485185851868518785188851898519085191851928519385194851958519685197851988519985200852018520285203852048520585206852078520885209852108521185212852138521485215852168521785218852198522085221852228522385224852258522685227852288522985230852318523285233852348523585236852378523885239852408524185242852438524485245852468524785248852498525085251852528525385254852558525685257852588525985260852618526285263852648526585266852678526885269852708527185272852738527485275852768527785278852798528085281852828528385284852858528685287852888528985290852918529285293852948529585296852978529885299853008530185302853038530485305853068530785308853098531085311853128531385314853158531685317853188531985320853218532285323853248532585326853278532885329853308533185332853338533485335853368533785338853398534085341853428534385344853458534685347853488534985350853518535285353853548535585356853578535885359853608536185362853638536485365853668536785368853698537085371853728537385374853758537685377853788537985380853818538285383853848538585386853878538885389853908539185392853938539485395853968539785398853998540085401854028540385404854058540685407854088540985410854118541285413854148541585416854178541885419854208542185422854238542485425854268542785428854298543085431854328543385434854358543685437854388543985440854418544285443854448544585446854478544885449854508545185452854538545485455854568545785458854598546085461854628546385464854658546685467854688546985470854718547285473854748547585476854778547885479854808548185482854838548485485854868548785488854898549085491854928549385494854958549685497854988549985500855018550285503855048550585506855078550885509855108551185512855138551485515855168551785518855198552085521855228552385524855258552685527855288552985530855318553285533855348553585536855378553885539855408554185542855438554485545855468554785548855498555085551855528555385554855558555685557855588555985560855618556285563855648556585566855678556885569855708557185572855738557485575855768557785578855798558085581855828558385584855858558685587855888558985590855918559285593855948559585596855978559885599856008560185602856038560485605856068560785608856098561085611856128561385614856158561685617856188561985620856218562285623856248562585626856278562885629856308563185632856338563485635856368563785638856398564085641856428564385644856458564685647856488564985650856518565285653856548565585656856578565885659856608566185662856638566485665856668566785668856698567085671856728567385674856758567685677856788567985680856818568285683856848568585686856878568885689856908569185692856938569485695856968569785698856998570085701857028570385704857058570685707857088570985710857118571285713857148571585716857178571885719857208572185722857238572485725857268572785728857298573085731857328573385734857358573685737857388573985740857418574285743857448574585746857478574885749857508575185752857538575485755857568575785758857598576085761857628576385764857658576685767857688576985770857718577285773857748577585776857778577885779857808578185782857838578485785857868578785788857898579085791857928579385794857958579685797857988579985800858018580285803858048580585806858078580885809858108581185812858138581485815858168581785818858198582085821858228582385824858258582685827858288582985830858318583285833858348583585836858378583885839858408584185842858438584485845858468584785848858498585085851858528585385854858558585685857858588585985860858618586285863858648586585866858678586885869858708587185872858738587485875858768587785878858798588085881858828588385884858858588685887858888588985890858918589285893858948589585896858978589885899859008590185902859038590485905859068590785908859098591085911859128591385914859158591685917859188591985920859218592285923859248592585926859278592885929859308593185932859338593485935859368593785938859398594085941859428594385944859458594685947859488594985950859518595285953859548595585956859578595885959859608596185962859638596485965859668596785968859698597085971859728597385974859758597685977859788597985980859818598285983859848598585986859878598885989859908599185992859938599485995859968599785998859998600086001860028600386004860058600686007860088600986010860118601286013860148601586016860178601886019860208602186022860238602486025860268602786028860298603086031860328603386034860358603686037860388603986040860418604286043860448604586046860478604886049860508605186052860538605486055860568605786058860598606086061860628606386064860658606686067860688606986070860718607286073860748607586076860778607886079860808608186082860838608486085860868608786088860898609086091860928609386094860958609686097860988609986100861018610286103861048610586106861078610886109861108611186112861138611486115861168611786118861198612086121861228612386124861258612686127861288612986130861318613286133861348613586136861378613886139861408614186142861438614486145861468614786148861498615086151861528615386154861558615686157861588615986160861618616286163861648616586166861678616886169861708617186172861738617486175861768617786178861798618086181861828618386184861858618686187861888618986190861918619286193861948619586196861978619886199862008620186202862038620486205862068620786208862098621086211862128621386214862158621686217862188621986220862218622286223862248622586226862278622886229862308623186232862338623486235862368623786238862398624086241862428624386244862458624686247862488624986250862518625286253862548625586256862578625886259862608626186262862638626486265862668626786268862698627086271862728627386274862758627686277862788627986280862818628286283862848628586286862878628886289862908629186292862938629486295862968629786298862998630086301863028630386304863058630686307863088630986310863118631286313863148631586316863178631886319863208632186322863238632486325863268632786328863298633086331863328633386334863358633686337863388633986340863418634286343863448634586346863478634886349863508635186352863538635486355863568635786358863598636086361863628636386364863658636686367863688636986370863718637286373863748637586376863778637886379863808638186382863838638486385863868638786388863898639086391863928639386394863958639686397863988639986400864018640286403864048640586406864078640886409864108641186412864138641486415864168641786418864198642086421864228642386424864258642686427864288642986430864318643286433864348643586436864378643886439864408644186442864438644486445864468644786448864498645086451864528645386454864558645686457864588645986460864618646286463864648646586466864678646886469864708647186472864738647486475864768647786478864798648086481864828648386484864858648686487864888648986490864918649286493864948649586496864978649886499865008650186502865038650486505865068650786508865098651086511865128651386514865158651686517865188651986520865218652286523865248652586526865278652886529865308653186532865338653486535865368653786538865398654086541865428654386544865458654686547865488654986550865518655286553865548655586556865578655886559865608656186562865638656486565865668656786568865698657086571865728657386574865758657686577865788657986580865818658286583865848658586586865878658886589865908659186592865938659486595865968659786598865998660086601866028660386604866058660686607866088660986610866118661286613866148661586616866178661886619866208662186622866238662486625866268662786628866298663086631866328663386634866358663686637866388663986640866418664286643866448664586646866478664886649866508665186652866538665486655866568665786658866598666086661866628666386664866658666686667866688666986670866718667286673866748667586676866778667886679866808668186682866838668486685866868668786688866898669086691866928669386694866958669686697866988669986700867018670286703867048670586706867078670886709867108671186712867138671486715867168671786718867198672086721867228672386724867258672686727867288672986730867318673286733867348673586736867378673886739867408674186742867438674486745867468674786748867498675086751867528675386754867558675686757867588675986760867618676286763867648676586766867678676886769867708677186772867738677486775867768677786778867798678086781867828678386784867858678686787867888678986790867918679286793867948679586796867978679886799868008680186802868038680486805868068680786808868098681086811868128681386814868158681686817868188681986820868218682286823868248682586826868278682886829868308683186832868338683486835868368683786838868398684086841868428684386844868458684686847868488684986850868518685286853868548685586856868578685886859868608686186862868638686486865868668686786868868698687086871868728687386874868758687686877868788687986880868818688286883868848688586886868878688886889868908689186892868938689486895868968689786898868998690086901869028690386904869058690686907869088690986910869118691286913869148691586916869178691886919869208692186922869238692486925869268692786928869298693086931869328693386934869358693686937869388693986940869418694286943869448694586946869478694886949869508695186952869538695486955869568695786958869598696086961869628696386964869658696686967869688696986970869718697286973869748697586976869778697886979869808698186982869838698486985869868698786988869898699086991869928699386994869958699686997869988699987000870018700287003870048700587006870078700887009870108701187012870138701487015870168701787018870198702087021870228702387024870258702687027870288702987030870318703287033870348703587036870378703887039870408704187042870438704487045870468704787048870498705087051870528705387054870558705687057870588705987060870618706287063870648706587066870678706887069870708707187072870738707487075870768707787078870798708087081870828708387084870858708687087870888708987090870918709287093870948709587096870978709887099871008710187102871038710487105871068710787108871098711087111871128711387114871158711687117871188711987120871218712287123871248712587126871278712887129871308713187132871338713487135871368713787138871398714087141871428714387144871458714687147871488714987150871518715287153871548715587156871578715887159871608716187162871638716487165871668716787168871698717087171871728717387174871758717687177871788717987180871818718287183871848718587186871878718887189871908719187192871938719487195871968719787198871998720087201872028720387204872058720687207872088720987210872118721287213872148721587216872178721887219872208722187222872238722487225872268722787228872298723087231872328723387234872358723687237872388723987240872418724287243872448724587246872478724887249872508725187252872538725487255872568725787258872598726087261872628726387264872658726687267872688726987270872718727287273872748727587276872778727887279872808728187282872838728487285872868728787288872898729087291872928729387294872958729687297872988729987300873018730287303873048730587306873078730887309873108731187312873138731487315873168731787318873198732087321873228732387324873258732687327873288732987330873318733287333873348733587336873378733887339873408734187342873438734487345873468734787348873498735087351873528735387354873558735687357873588735987360873618736287363873648736587366873678736887369873708737187372873738737487375873768737787378873798738087381873828738387384873858738687387873888738987390873918739287393873948739587396873978739887399874008740187402874038740487405874068740787408874098741087411874128741387414874158741687417874188741987420874218742287423874248742587426874278742887429874308743187432874338743487435874368743787438874398744087441874428744387444874458744687447874488744987450874518745287453874548745587456874578745887459874608746187462874638746487465874668746787468874698747087471874728747387474874758747687477874788747987480874818748287483874848748587486874878748887489874908749187492874938749487495874968749787498874998750087501875028750387504875058750687507875088750987510875118751287513875148751587516875178751887519875208752187522875238752487525875268752787528875298753087531875328753387534875358753687537875388753987540875418754287543875448754587546875478754887549875508755187552875538755487555875568755787558875598756087561875628756387564875658756687567875688756987570875718757287573875748757587576875778757887579875808758187582875838758487585875868758787588875898759087591875928759387594875958759687597875988759987600876018760287603876048760587606876078760887609876108761187612876138761487615876168761787618876198762087621876228762387624876258762687627876288762987630876318763287633876348763587636876378763887639876408764187642876438764487645876468764787648876498765087651876528765387654876558765687657876588765987660876618766287663876648766587666876678766887669876708767187672876738767487675876768767787678876798768087681876828768387684876858768687687876888768987690876918769287693876948769587696876978769887699877008770187702877038770487705877068770787708877098771087711877128771387714877158771687717877188771987720877218772287723877248772587726877278772887729877308773187732877338773487735877368773787738877398774087741877428774387744877458774687747877488774987750877518775287753877548775587756877578775887759877608776187762877638776487765877668776787768877698777087771877728777387774877758777687777877788777987780877818778287783877848778587786877878778887789877908779187792877938779487795877968779787798877998780087801878028780387804878058780687807878088780987810878118781287813878148781587816878178781887819878208782187822878238782487825878268782787828878298783087831878328783387834878358783687837878388783987840878418784287843878448784587846878478784887849878508785187852878538785487855878568785787858878598786087861878628786387864878658786687867878688786987870878718787287873878748787587876878778787887879878808788187882878838788487885878868788787888878898789087891878928789387894878958789687897878988789987900879018790287903879048790587906879078790887909879108791187912879138791487915879168791787918879198792087921879228792387924879258792687927879288792987930879318793287933879348793587936879378793887939879408794187942879438794487945879468794787948879498795087951879528795387954879558795687957879588795987960879618796287963879648796587966879678796887969879708797187972879738797487975879768797787978879798798087981879828798387984879858798687987879888798987990879918799287993879948799587996879978799887999880008800188002880038800488005880068800788008880098801088011880128801388014880158801688017880188801988020880218802288023880248802588026880278802888029880308803188032880338803488035880368803788038880398804088041880428804388044880458804688047880488804988050880518805288053880548805588056880578805888059880608806188062880638806488065880668806788068880698807088071880728807388074880758807688077880788807988080880818808288083880848808588086880878808888089880908809188092880938809488095880968809788098880998810088101881028810388104881058810688107881088810988110881118811288113881148811588116881178811888119881208812188122881238812488125881268812788128881298813088131881328813388134881358813688137881388813988140881418814288143881448814588146881478814888149881508815188152881538815488155881568815788158881598816088161881628816388164881658816688167881688816988170881718817288173881748817588176881778817888179881808818188182881838818488185881868818788188881898819088191881928819388194881958819688197881988819988200882018820288203882048820588206882078820888209882108821188212882138821488215882168821788218882198822088221882228822388224882258822688227882288822988230882318823288233882348823588236882378823888239882408824188242882438824488245882468824788248882498825088251882528825388254882558825688257882588825988260882618826288263882648826588266882678826888269882708827188272882738827488275882768827788278882798828088281882828828388284882858828688287882888828988290882918829288293882948829588296882978829888299883008830188302883038830488305883068830788308883098831088311883128831388314883158831688317883188831988320883218832288323883248832588326883278832888329883308833188332883338833488335883368833788338883398834088341883428834388344883458834688347883488834988350883518835288353883548835588356883578835888359883608836188362883638836488365883668836788368883698837088371883728837388374883758837688377883788837988380883818838288383883848838588386883878838888389883908839188392883938839488395883968839788398883998840088401884028840388404884058840688407884088840988410884118841288413884148841588416884178841888419884208842188422884238842488425884268842788428884298843088431884328843388434884358843688437884388843988440884418844288443884448844588446884478844888449884508845188452884538845488455884568845788458884598846088461884628846388464884658846688467884688846988470884718847288473884748847588476884778847888479884808848188482884838848488485884868848788488884898849088491884928849388494884958849688497884988849988500885018850288503885048850588506885078850888509885108851188512885138851488515885168851788518885198852088521885228852388524885258852688527885288852988530885318853288533885348853588536885378853888539885408854188542885438854488545885468854788548885498855088551885528855388554885558855688557885588855988560885618856288563885648856588566885678856888569885708857188572885738857488575885768857788578885798858088581885828858388584885858858688587885888858988590885918859288593885948859588596885978859888599886008860188602886038860488605886068860788608886098861088611886128861388614886158861688617886188861988620886218862288623886248862588626886278862888629886308863188632886338863488635886368863788638886398864088641886428864388644886458864688647886488864988650886518865288653886548865588656886578865888659886608866188662886638866488665886668866788668886698867088671886728867388674886758867688677886788867988680886818868288683886848868588686886878868888689886908869188692886938869488695886968869788698886998870088701887028870388704887058870688707887088870988710887118871288713887148871588716887178871888719887208872188722887238872488725887268872788728887298873088731887328873388734887358873688737887388873988740887418874288743887448874588746887478874888749887508875188752887538875488755887568875788758887598876088761887628876388764887658876688767887688876988770887718877288773887748877588776887778877888779887808878188782887838878488785887868878788788887898879088791887928879388794887958879688797887988879988800888018880288803888048880588806888078880888809888108881188812888138881488815888168881788818888198882088821888228882388824888258882688827888288882988830888318883288833888348883588836888378883888839888408884188842888438884488845888468884788848888498885088851888528885388854888558885688857888588885988860888618886288863888648886588866888678886888869888708887188872888738887488875888768887788878888798888088881888828888388884888858888688887888888888988890888918889288893888948889588896888978889888899889008890188902889038890488905889068890788908889098891088911889128891388914889158891688917889188891988920889218892288923889248892588926889278892888929889308893188932889338893488935889368893788938889398894088941889428894388944889458894688947889488894988950889518895288953889548895588956889578895888959889608896188962889638896488965889668896788968889698897088971889728897388974889758897688977889788897988980889818898288983889848898588986889878898888989889908899188992889938899488995889968899788998889998900089001890028900389004890058900689007890088900989010890118901289013890148901589016890178901889019890208902189022890238902489025890268902789028890298903089031890328903389034890358903689037890388903989040890418904289043890448904589046890478904889049890508905189052890538905489055890568905789058890598906089061890628906389064890658906689067890688906989070890718907289073890748907589076890778907889079890808908189082890838908489085890868908789088890898909089091890928909389094890958909689097890988909989100891018910289103891048910589106891078910889109891108911189112891138911489115891168911789118891198912089121891228912389124891258912689127891288912989130891318913289133891348913589136891378913889139891408914189142891438914489145891468914789148891498915089151891528915389154891558915689157891588915989160891618916289163891648916589166891678916889169891708917189172891738917489175891768917789178891798918089181891828918389184891858918689187891888918989190891918919289193891948919589196891978919889199892008920189202892038920489205892068920789208892098921089211892128921389214892158921689217892188921989220892218922289223892248922589226892278922889229892308923189232892338923489235892368923789238892398924089241892428924389244892458924689247892488924989250892518925289253892548925589256892578925889259892608926189262892638926489265892668926789268892698927089271892728927389274892758927689277892788927989280892818928289283892848928589286892878928889289892908929189292892938929489295892968929789298892998930089301893028930389304893058930689307893088930989310893118931289313893148931589316893178931889319893208932189322893238932489325893268932789328893298933089331893328933389334893358933689337893388933989340893418934289343893448934589346893478934889349893508935189352893538935489355893568935789358893598936089361893628936389364893658936689367893688936989370893718937289373893748937589376893778937889379893808938189382893838938489385893868938789388893898939089391893928939389394893958939689397893988939989400894018940289403894048940589406894078940889409894108941189412894138941489415894168941789418894198942089421894228942389424894258942689427894288942989430894318943289433894348943589436894378943889439894408944189442894438944489445894468944789448894498945089451894528945389454894558945689457894588945989460894618946289463894648946589466894678946889469894708947189472894738947489475894768947789478894798948089481894828948389484894858948689487894888948989490894918949289493894948949589496894978949889499895008950189502895038950489505895068950789508895098951089511895128951389514895158951689517895188951989520895218952289523895248952589526895278952889529895308953189532895338953489535895368953789538895398954089541895428954389544895458954689547895488954989550895518955289553895548955589556895578955889559895608956189562895638956489565895668956789568895698957089571895728957389574895758957689577895788957989580895818958289583895848958589586895878958889589895908959189592895938959489595895968959789598895998960089601896028960389604896058960689607896088960989610896118961289613896148961589616896178961889619896208962189622896238962489625896268962789628896298963089631896328963389634896358963689637896388963989640896418964289643896448964589646896478964889649896508965189652896538965489655896568965789658896598966089661896628966389664896658966689667896688966989670896718967289673896748967589676896778967889679896808968189682896838968489685896868968789688896898969089691896928969389694896958969689697896988969989700897018970289703897048970589706897078970889709897108971189712897138971489715897168971789718897198972089721897228972389724897258972689727897288972989730897318973289733897348973589736897378973889739897408974189742897438974489745897468974789748897498975089751897528975389754897558975689757897588975989760897618976289763897648976589766897678976889769897708977189772897738977489775897768977789778897798978089781897828978389784897858978689787897888978989790897918979289793897948979589796897978979889799898008980189802898038980489805898068980789808898098981089811898128981389814898158981689817898188981989820898218982289823898248982589826898278982889829898308983189832898338983489835898368983789838898398984089841898428984389844898458984689847898488984989850898518985289853898548985589856898578985889859898608986189862898638986489865898668986789868898698987089871898728987389874898758987689877898788987989880898818988289883898848988589886898878988889889898908989189892898938989489895898968989789898898998990089901899028990389904899058990689907899088990989910899118991289913899148991589916899178991889919899208992189922899238992489925899268992789928899298993089931899328993389934899358993689937899388993989940899418994289943899448994589946899478994889949899508995189952899538995489955899568995789958899598996089961899628996389964899658996689967899688996989970899718997289973899748997589976899778997889979899808998189982899838998489985899868998789988899898999089991899928999389994899958999689997899988999990000900019000290003900049000590006900079000890009900109001190012900139001490015900169001790018900199002090021900229002390024900259002690027900289002990030900319003290033900349003590036900379003890039900409004190042900439004490045900469004790048900499005090051900529005390054900559005690057900589005990060900619006290063900649006590066900679006890069900709007190072900739007490075900769007790078900799008090081900829008390084900859008690087900889008990090900919009290093900949009590096900979009890099901009010190102901039010490105901069010790108901099011090111901129011390114901159011690117901189011990120901219012290123901249012590126901279012890129901309013190132901339013490135901369013790138901399014090141901429014390144901459014690147901489014990150901519015290153901549015590156901579015890159901609016190162901639016490165901669016790168901699017090171901729017390174901759017690177901789017990180901819018290183901849018590186901879018890189901909019190192901939019490195901969019790198901999020090201902029020390204902059020690207902089020990210902119021290213902149021590216902179021890219902209022190222902239022490225902269022790228902299023090231902329023390234902359023690237902389023990240902419024290243902449024590246902479024890249902509025190252902539025490255902569025790258902599026090261902629026390264902659026690267902689026990270902719027290273902749027590276902779027890279902809028190282902839028490285902869028790288902899029090291902929029390294902959029690297902989029990300903019030290303903049030590306903079030890309903109031190312903139031490315903169031790318903199032090321903229032390324903259032690327903289032990330903319033290333903349033590336903379033890339903409034190342903439034490345903469034790348903499035090351903529035390354903559035690357903589035990360903619036290363903649036590366903679036890369903709037190372903739037490375903769037790378903799038090381903829038390384903859038690387903889038990390903919039290393903949039590396903979039890399904009040190402904039040490405904069040790408904099041090411904129041390414904159041690417904189041990420904219042290423904249042590426904279042890429904309043190432904339043490435904369043790438904399044090441904429044390444904459044690447904489044990450904519045290453904549045590456904579045890459904609046190462904639046490465904669046790468904699047090471904729047390474904759047690477904789047990480904819048290483904849048590486904879048890489904909049190492904939049490495904969049790498904999050090501905029050390504905059050690507905089050990510905119051290513905149051590516905179051890519905209052190522905239052490525905269052790528905299053090531905329053390534905359053690537905389053990540905419054290543905449054590546905479054890549905509055190552905539055490555905569055790558905599056090561905629056390564905659056690567905689056990570905719057290573905749057590576905779057890579905809058190582905839058490585905869058790588905899059090591905929059390594905959059690597905989059990600906019060290603906049060590606906079060890609906109061190612906139061490615906169061790618906199062090621906229062390624906259062690627906289062990630906319063290633906349063590636906379063890639906409064190642906439064490645906469064790648906499065090651906529065390654906559065690657906589065990660906619066290663906649066590666906679066890669906709067190672906739067490675906769067790678906799068090681906829068390684906859068690687906889068990690906919069290693906949069590696906979069890699907009070190702907039070490705907069070790708907099071090711907129071390714907159071690717907189071990720907219072290723907249072590726907279072890729907309073190732907339073490735907369073790738907399074090741907429074390744907459074690747907489074990750907519075290753907549075590756907579075890759907609076190762907639076490765907669076790768907699077090771907729077390774907759077690777907789077990780907819078290783907849078590786907879078890789907909079190792907939079490795907969079790798907999080090801908029080390804908059080690807908089080990810908119081290813908149081590816908179081890819908209082190822908239082490825908269082790828908299083090831908329083390834908359083690837908389083990840908419084290843908449084590846908479084890849908509085190852908539085490855908569085790858908599086090861908629086390864908659086690867908689086990870908719087290873908749087590876908779087890879908809088190882908839088490885908869088790888908899089090891908929089390894908959089690897908989089990900909019090290903909049090590906909079090890909909109091190912909139091490915909169091790918909199092090921909229092390924909259092690927909289092990930909319093290933909349093590936909379093890939909409094190942909439094490945909469094790948909499095090951909529095390954909559095690957909589095990960909619096290963909649096590966909679096890969909709097190972909739097490975909769097790978909799098090981909829098390984909859098690987909889098990990909919099290993909949099590996909979099890999910009100191002910039100491005910069100791008910099101091011910129101391014910159101691017910189101991020910219102291023910249102591026910279102891029910309103191032910339103491035910369103791038910399104091041910429104391044910459104691047910489104991050910519105291053910549105591056910579105891059910609106191062910639106491065910669106791068910699107091071910729107391074910759107691077910789107991080910819108291083910849108591086910879108891089910909109191092910939109491095910969109791098910999110091101911029110391104911059110691107911089110991110911119111291113911149111591116911179111891119911209112191122911239112491125911269112791128911299113091131911329113391134911359113691137911389113991140911419114291143911449114591146911479114891149911509115191152911539115491155911569115791158911599116091161911629116391164911659116691167911689116991170911719117291173911749117591176911779117891179911809118191182911839118491185911869118791188911899119091191911929119391194911959119691197911989119991200912019120291203912049120591206912079120891209912109121191212912139121491215912169121791218912199122091221912229122391224912259122691227912289122991230912319123291233912349123591236912379123891239912409124191242912439124491245912469124791248912499125091251912529125391254912559125691257912589125991260912619126291263912649126591266912679126891269912709127191272912739127491275912769127791278912799128091281912829128391284912859128691287912889128991290912919129291293912949129591296912979129891299913009130191302913039130491305913069130791308913099131091311913129131391314913159131691317913189131991320913219132291323913249132591326913279132891329913309133191332913339133491335913369133791338913399134091341913429134391344913459134691347913489134991350913519135291353913549135591356913579135891359913609136191362913639136491365913669136791368913699137091371913729137391374913759137691377913789137991380913819138291383913849138591386913879138891389913909139191392913939139491395913969139791398913999140091401914029140391404914059140691407914089140991410914119141291413914149141591416914179141891419914209142191422914239142491425914269142791428914299143091431914329143391434914359143691437914389143991440914419144291443914449144591446914479144891449914509145191452914539145491455914569145791458914599146091461914629146391464914659146691467914689146991470914719147291473914749147591476914779147891479914809148191482914839148491485914869148791488914899149091491914929149391494914959149691497914989149991500915019150291503915049150591506915079150891509915109151191512915139151491515915169151791518915199152091521915229152391524915259152691527915289152991530915319153291533915349153591536915379153891539915409154191542915439154491545915469154791548915499155091551915529155391554915559155691557915589155991560915619156291563915649156591566915679156891569915709157191572915739157491575915769157791578915799158091581915829158391584915859158691587915889158991590915919159291593915949159591596915979159891599916009160191602916039160491605916069160791608916099161091611916129161391614916159161691617916189161991620916219162291623916249162591626916279162891629916309163191632916339163491635916369163791638916399164091641916429164391644916459164691647916489164991650916519165291653916549165591656916579165891659916609166191662916639166491665916669166791668916699167091671916729167391674916759167691677916789167991680916819168291683916849168591686916879168891689916909169191692916939169491695916969169791698916999170091701917029170391704917059170691707917089170991710917119171291713917149171591716917179171891719917209172191722917239172491725917269172791728917299173091731917329173391734917359173691737917389173991740917419174291743917449174591746917479174891749917509175191752917539175491755917569175791758917599176091761917629176391764917659176691767917689176991770917719177291773917749177591776917779177891779917809178191782917839178491785917869178791788917899179091791917929179391794917959179691797917989179991800918019180291803918049180591806918079180891809918109181191812918139181491815918169181791818918199182091821918229182391824918259182691827918289182991830918319183291833918349183591836918379183891839918409184191842918439184491845918469184791848918499185091851918529185391854918559185691857918589185991860918619186291863918649186591866918679186891869918709187191872918739187491875918769187791878918799188091881918829188391884918859188691887918889188991890918919189291893918949189591896918979189891899919009190191902919039190491905919069190791908919099191091911919129191391914919159191691917919189191991920919219192291923919249192591926919279192891929919309193191932919339193491935919369193791938919399194091941919429194391944919459194691947919489194991950919519195291953919549195591956919579195891959919609196191962919639196491965919669196791968919699197091971919729197391974919759197691977919789197991980919819198291983919849198591986919879198891989919909199191992919939199491995919969199791998919999200092001920029200392004920059200692007920089200992010920119201292013920149201592016920179201892019920209202192022920239202492025920269202792028920299203092031920329203392034920359203692037920389203992040920419204292043920449204592046920479204892049920509205192052920539205492055920569205792058920599206092061920629206392064920659206692067920689206992070920719207292073920749207592076920779207892079920809208192082920839208492085920869208792088920899209092091920929209392094920959209692097920989209992100921019210292103921049210592106921079210892109921109211192112921139211492115921169211792118921199212092121921229212392124921259212692127921289212992130921319213292133921349213592136921379213892139921409214192142921439214492145921469214792148921499215092151921529215392154921559215692157921589215992160921619216292163921649216592166921679216892169921709217192172921739217492175921769217792178921799218092181921829218392184921859218692187921889218992190921919219292193921949219592196921979219892199922009220192202922039220492205922069220792208922099221092211922129221392214922159221692217922189221992220922219222292223922249222592226922279222892229922309223192232922339223492235922369223792238922399224092241922429224392244922459224692247922489224992250922519225292253922549225592256922579225892259922609226192262922639226492265922669226792268922699227092271922729227392274922759227692277922789227992280922819228292283922849228592286922879228892289922909229192292922939229492295922969229792298922999230092301923029230392304923059230692307923089230992310923119231292313923149231592316923179231892319923209232192322923239232492325923269232792328923299233092331923329233392334923359233692337923389233992340923419234292343923449234592346923479234892349923509235192352923539235492355923569235792358923599236092361923629236392364923659236692367923689236992370923719237292373923749237592376923779237892379923809238192382923839238492385923869238792388923899239092391923929239392394923959239692397923989239992400924019240292403924049240592406924079240892409924109241192412924139241492415924169241792418924199242092421924229242392424924259242692427924289242992430924319243292433924349243592436924379243892439924409244192442924439244492445924469244792448924499245092451924529245392454924559245692457924589245992460924619246292463924649246592466924679246892469924709247192472924739247492475924769247792478924799248092481924829248392484924859248692487924889248992490924919249292493924949249592496924979249892499925009250192502925039250492505925069250792508925099251092511925129251392514925159251692517925189251992520925219252292523925249252592526925279252892529925309253192532925339253492535925369253792538925399254092541925429254392544925459254692547925489254992550925519255292553925549255592556925579255892559925609256192562925639256492565925669256792568925699257092571925729257392574925759257692577925789257992580925819258292583925849258592586925879258892589925909259192592925939259492595925969259792598925999260092601926029260392604926059260692607926089260992610926119261292613926149261592616926179261892619926209262192622926239262492625926269262792628926299263092631926329263392634926359263692637926389263992640926419264292643926449264592646926479264892649926509265192652926539265492655926569265792658926599266092661926629266392664926659266692667926689266992670926719267292673926749267592676926779267892679926809268192682926839268492685926869268792688926899269092691926929269392694926959269692697926989269992700927019270292703927049270592706927079270892709927109271192712927139271492715927169271792718927199272092721927229272392724927259272692727927289272992730927319273292733927349273592736927379273892739927409274192742927439274492745927469274792748927499275092751927529275392754927559275692757927589275992760927619276292763927649276592766927679276892769927709277192772927739277492775927769277792778927799278092781927829278392784927859278692787927889278992790927919279292793927949279592796927979279892799928009280192802928039280492805928069280792808928099281092811928129281392814928159281692817928189281992820928219282292823928249282592826928279282892829928309283192832928339283492835928369283792838928399284092841928429284392844928459284692847928489284992850928519285292853928549285592856928579285892859928609286192862928639286492865928669286792868928699287092871928729287392874928759287692877928789287992880928819288292883928849288592886928879288892889928909289192892928939289492895928969289792898928999290092901929029290392904929059290692907929089290992910929119291292913929149291592916929179291892919929209292192922929239292492925929269292792928929299293092931929329293392934929359293692937929389293992940929419294292943929449294592946929479294892949929509295192952929539295492955929569295792958929599296092961929629296392964929659296692967929689296992970929719297292973929749297592976929779297892979929809298192982929839298492985929869298792988929899299092991929929299392994929959299692997929989299993000930019300293003930049300593006930079300893009930109301193012930139301493015930169301793018930199302093021930229302393024930259302693027930289302993030930319303293033930349303593036930379303893039930409304193042930439304493045930469304793048930499305093051930529305393054930559305693057930589305993060930619306293063930649306593066930679306893069930709307193072930739307493075930769307793078930799308093081930829308393084930859308693087930889308993090930919309293093930949309593096930979309893099931009310193102931039310493105931069310793108931099311093111931129311393114931159311693117931189311993120931219312293123931249312593126931279312893129931309313193132931339313493135931369313793138931399314093141931429314393144931459314693147931489314993150931519315293153931549315593156931579315893159931609316193162931639316493165931669316793168931699317093171931729317393174931759317693177931789317993180931819318293183931849318593186931879318893189931909319193192931939319493195931969319793198931999320093201932029320393204932059320693207932089320993210932119321293213932149321593216932179321893219932209322193222932239322493225932269322793228932299323093231932329323393234932359323693237932389323993240932419324293243932449324593246932479324893249932509325193252932539325493255932569325793258932599326093261932629326393264932659326693267932689326993270932719327293273932749327593276932779327893279932809328193282932839328493285932869328793288932899329093291932929329393294932959329693297932989329993300933019330293303933049330593306933079330893309933109331193312933139331493315933169331793318933199332093321933229332393324933259332693327933289332993330933319333293333933349333593336933379333893339933409334193342933439334493345933469334793348933499335093351933529335393354933559335693357933589335993360933619336293363933649336593366933679336893369933709337193372933739337493375933769337793378933799338093381933829338393384933859338693387933889338993390933919339293393933949339593396933979339893399934009340193402934039340493405934069340793408934099341093411934129341393414934159341693417934189341993420934219342293423934249342593426934279342893429934309343193432934339343493435934369343793438934399344093441934429344393444934459344693447934489344993450934519345293453934549345593456934579345893459934609346193462934639346493465934669346793468934699347093471934729347393474934759347693477934789347993480934819348293483934849348593486934879348893489934909349193492934939349493495934969349793498934999350093501935029350393504935059350693507935089350993510935119351293513935149351593516935179351893519935209352193522935239352493525935269352793528935299353093531935329353393534935359353693537935389353993540935419354293543935449354593546935479354893549935509355193552935539355493555935569355793558935599356093561935629356393564935659356693567935689356993570935719357293573935749357593576935779357893579935809358193582935839358493585935869358793588935899359093591935929359393594935959359693597935989359993600936019360293603936049360593606936079360893609936109361193612936139361493615936169361793618936199362093621936229362393624936259362693627936289362993630936319363293633936349363593636936379363893639936409364193642936439364493645936469364793648936499365093651936529365393654936559365693657936589365993660936619366293663936649366593666936679366893669936709367193672936739367493675936769367793678936799368093681936829368393684936859368693687936889368993690936919369293693936949369593696936979369893699937009370193702937039370493705937069370793708937099371093711937129371393714937159371693717937189371993720937219372293723937249372593726937279372893729937309373193732937339373493735937369373793738937399374093741937429374393744937459374693747937489374993750937519375293753937549375593756937579375893759937609376193762937639376493765937669376793768937699377093771937729377393774937759377693777937789377993780937819378293783937849378593786937879378893789937909379193792937939379493795937969379793798937999380093801938029380393804938059380693807938089380993810938119381293813938149381593816938179381893819938209382193822938239382493825938269382793828938299383093831938329383393834938359383693837938389383993840938419384293843938449384593846938479384893849938509385193852938539385493855938569385793858938599386093861938629386393864938659386693867938689386993870938719387293873938749387593876938779387893879938809388193882938839388493885938869388793888938899389093891938929389393894938959389693897938989389993900939019390293903939049390593906939079390893909939109391193912939139391493915939169391793918939199392093921939229392393924939259392693927939289392993930939319393293933939349393593936939379393893939939409394193942939439394493945939469394793948939499395093951939529395393954939559395693957939589395993960939619396293963939649396593966939679396893969939709397193972939739397493975939769397793978939799398093981939829398393984939859398693987939889398993990939919399293993939949399593996939979399893999940009400194002940039400494005940069400794008940099401094011940129401394014940159401694017940189401994020940219402294023940249402594026940279402894029940309403194032940339403494035940369403794038940399404094041940429404394044940459404694047940489404994050940519405294053940549405594056940579405894059940609406194062940639406494065940669406794068940699407094071940729407394074940759407694077940789407994080940819408294083940849408594086940879408894089940909409194092940939409494095940969409794098940999410094101941029410394104941059410694107941089410994110941119411294113941149411594116941179411894119941209412194122941239412494125941269412794128941299413094131941329413394134941359413694137941389413994140941419414294143941449414594146941479414894149941509415194152941539415494155941569415794158941599416094161941629416394164941659416694167941689416994170941719417294173941749417594176941779417894179941809418194182941839418494185941869418794188941899419094191941929419394194941959419694197941989419994200942019420294203942049420594206942079420894209942109421194212942139421494215942169421794218942199422094221942229422394224942259422694227942289422994230942319423294233942349423594236942379423894239942409424194242942439424494245942469424794248942499425094251942529425394254942559425694257942589425994260942619426294263942649426594266942679426894269942709427194272942739427494275942769427794278942799428094281942829428394284942859428694287942889428994290942919429294293942949429594296942979429894299943009430194302943039430494305943069430794308943099431094311943129431394314943159431694317943189431994320943219432294323943249432594326943279432894329943309433194332943339433494335943369433794338943399434094341943429434394344943459434694347943489434994350943519435294353943549435594356943579435894359943609436194362943639436494365943669436794368943699437094371943729437394374943759437694377943789437994380943819438294383943849438594386943879438894389943909439194392943939439494395943969439794398943999440094401944029440394404944059440694407944089440994410944119441294413944149441594416944179441894419944209442194422944239442494425944269442794428944299443094431944329443394434944359443694437944389443994440944419444294443944449444594446944479444894449944509445194452944539445494455944569445794458944599446094461944629446394464944659446694467944689446994470944719447294473944749447594476944779447894479944809448194482944839448494485944869448794488944899449094491944929449394494944959449694497944989449994500945019450294503945049450594506945079450894509945109451194512945139451494515945169451794518945199452094521945229452394524945259452694527945289452994530945319453294533945349453594536945379453894539945409454194542945439454494545945469454794548945499455094551945529455394554945559455694557945589455994560945619456294563945649456594566945679456894569945709457194572945739457494575945769457794578945799458094581945829458394584945859458694587945889458994590945919459294593945949459594596945979459894599946009460194602946039460494605946069460794608946099461094611946129461394614946159461694617946189461994620946219462294623946249462594626946279462894629946309463194632946339463494635946369463794638946399464094641946429464394644946459464694647946489464994650946519465294653946549465594656946579465894659946609466194662946639466494665946669466794668946699467094671946729467394674946759467694677946789467994680946819468294683946849468594686946879468894689946909469194692946939469494695946969469794698946999470094701947029470394704947059470694707947089470994710947119471294713947149471594716947179471894719947209472194722947239472494725947269472794728947299473094731947329473394734947359473694737947389473994740947419474294743947449474594746947479474894749947509475194752947539475494755947569475794758947599476094761947629476394764947659476694767947689476994770947719477294773947749477594776947779477894779947809478194782947839478494785947869478794788947899479094791947929479394794947959479694797947989479994800948019480294803948049480594806948079480894809948109481194812948139481494815948169481794818948199482094821948229482394824948259482694827948289482994830948319483294833948349483594836948379483894839948409484194842948439484494845948469484794848948499485094851948529485394854948559485694857948589485994860948619486294863948649486594866948679486894869948709487194872948739487494875948769487794878948799488094881948829488394884948859488694887948889488994890948919489294893948949489594896948979489894899949009490194902949039490494905949069490794908949099491094911949129491394914949159491694917949189491994920949219492294923949249492594926949279492894929949309493194932949339493494935949369493794938949399494094941949429494394944949459494694947949489494994950949519495294953949549495594956949579495894959949609496194962949639496494965949669496794968949699497094971949729497394974949759497694977949789497994980949819498294983949849498594986949879498894989949909499194992949939499494995949969499794998949999500095001950029500395004950059500695007950089500995010950119501295013950149501595016950179501895019950209502195022950239502495025950269502795028950299503095031950329503395034950359503695037950389503995040950419504295043950449504595046950479504895049950509505195052950539505495055950569505795058950599506095061950629506395064950659506695067950689506995070950719507295073950749507595076950779507895079950809508195082950839508495085950869508795088950899509095091950929509395094950959509695097950989509995100951019510295103951049510595106951079510895109951109511195112951139511495115951169511795118951199512095121951229512395124951259512695127951289512995130951319513295133951349513595136951379513895139951409514195142951439514495145951469514795148951499515095151951529515395154951559515695157951589515995160951619516295163951649516595166951679516895169951709517195172951739517495175951769517795178951799518095181951829518395184951859518695187951889518995190951919519295193951949519595196951979519895199952009520195202952039520495205952069520795208952099521095211952129521395214952159521695217952189521995220952219522295223952249522595226952279522895229952309523195232952339523495235952369523795238952399524095241952429524395244952459524695247952489524995250952519525295253952549525595256952579525895259952609526195262952639526495265952669526795268952699527095271952729527395274952759527695277952789527995280952819528295283952849528595286952879528895289952909529195292952939529495295952969529795298952999530095301953029530395304953059530695307953089530995310953119531295313953149531595316953179531895319953209532195322953239532495325953269532795328953299533095331953329533395334953359533695337953389533995340953419534295343953449534595346953479534895349953509535195352953539535495355953569535795358953599536095361953629536395364953659536695367953689536995370953719537295373953749537595376953779537895379953809538195382953839538495385953869538795388953899539095391953929539395394953959539695397953989539995400954019540295403954049540595406954079540895409954109541195412954139541495415954169541795418954199542095421954229542395424954259542695427954289542995430954319543295433954349543595436954379543895439954409544195442954439544495445954469544795448954499545095451954529545395454954559545695457954589545995460954619546295463954649546595466954679546895469954709547195472954739547495475954769547795478954799548095481954829548395484954859548695487954889548995490954919549295493954949549595496954979549895499955009550195502955039550495505955069550795508955099551095511955129551395514955159551695517955189551995520955219552295523955249552595526955279552895529955309553195532955339553495535955369553795538955399554095541955429554395544955459554695547955489554995550955519555295553955549555595556955579555895559955609556195562955639556495565955669556795568955699557095571955729557395574955759557695577955789557995580955819558295583955849558595586955879558895589955909559195592955939559495595955969559795598955999560095601956029560395604956059560695607956089560995610956119561295613956149561595616956179561895619956209562195622956239562495625956269562795628956299563095631956329563395634956359563695637956389563995640956419564295643956449564595646956479564895649956509565195652956539565495655956569565795658956599566095661956629566395664956659566695667956689566995670956719567295673956749567595676956779567895679956809568195682956839568495685956869568795688956899569095691956929569395694956959569695697956989569995700957019570295703957049570595706957079570895709957109571195712957139571495715957169571795718957199572095721957229572395724957259572695727957289572995730957319573295733957349573595736957379573895739957409574195742957439574495745957469574795748957499575095751957529575395754957559575695757957589575995760957619576295763957649576595766957679576895769957709577195772957739577495775957769577795778957799578095781957829578395784957859578695787957889578995790957919579295793957949579595796957979579895799958009580195802958039580495805958069580795808958099581095811958129581395814958159581695817958189581995820958219582295823958249582595826958279582895829958309583195832958339583495835958369583795838958399584095841958429584395844958459584695847958489584995850958519585295853958549585595856958579585895859958609586195862958639586495865958669586795868958699587095871958729587395874958759587695877958789587995880958819588295883958849588595886958879588895889958909589195892958939589495895958969589795898958999590095901959029590395904959059590695907959089590995910959119591295913959149591595916959179591895919959209592195922959239592495925959269592795928959299593095931959329593395934959359593695937959389593995940959419594295943959449594595946959479594895949959509595195952959539595495955959569595795958959599596095961959629596395964959659596695967959689596995970959719597295973959749597595976959779597895979959809598195982959839598495985959869598795988959899599095991959929599395994959959599695997959989599996000960019600296003960049600596006960079600896009960109601196012960139601496015960169601796018960199602096021960229602396024960259602696027960289602996030960319603296033960349603596036960379603896039960409604196042960439604496045960469604796048960499605096051960529605396054960559605696057960589605996060960619606296063960649606596066960679606896069960709607196072960739607496075960769607796078960799608096081960829608396084960859608696087960889608996090960919609296093960949609596096960979609896099961009610196102961039610496105961069610796108961099611096111961129611396114961159611696117961189611996120961219612296123961249612596126961279612896129961309613196132961339613496135961369613796138961399614096141961429614396144961459614696147961489614996150961519615296153961549615596156961579615896159961609616196162961639616496165961669616796168961699617096171961729617396174961759617696177961789617996180961819618296183961849618596186961879618896189961909619196192961939619496195961969619796198961999620096201962029620396204962059620696207962089620996210962119621296213962149621596216962179621896219962209622196222962239622496225962269622796228962299623096231962329623396234962359623696237962389623996240962419624296243962449624596246962479624896249962509625196252962539625496255962569625796258962599626096261962629626396264962659626696267962689626996270962719627296273962749627596276962779627896279962809628196282962839628496285962869628796288962899629096291962929629396294962959629696297962989629996300963019630296303963049630596306963079630896309963109631196312963139631496315963169631796318963199632096321963229632396324963259632696327963289632996330963319633296333963349633596336963379633896339963409634196342963439634496345963469634796348963499635096351963529635396354963559635696357963589635996360963619636296363963649636596366963679636896369963709637196372963739637496375963769637796378963799638096381963829638396384963859638696387963889638996390963919639296393963949639596396963979639896399964009640196402964039640496405964069640796408964099641096411964129641396414964159641696417964189641996420964219642296423964249642596426964279642896429964309643196432964339643496435964369643796438964399644096441964429644396444964459644696447964489644996450964519645296453964549645596456964579645896459964609646196462964639646496465964669646796468964699647096471964729647396474964759647696477964789647996480964819648296483964849648596486964879648896489964909649196492964939649496495964969649796498964999650096501965029650396504965059650696507965089650996510965119651296513965149651596516965179651896519965209652196522965239652496525965269652796528965299653096531965329653396534965359653696537965389653996540965419654296543965449654596546965479654896549965509655196552965539655496555965569655796558965599656096561965629656396564965659656696567965689656996570965719657296573965749657596576965779657896579965809658196582965839658496585965869658796588965899659096591965929659396594965959659696597965989659996600966019660296603966049660596606966079660896609966109661196612966139661496615966169661796618966199662096621966229662396624966259662696627966289662996630966319663296633966349663596636966379663896639966409664196642966439664496645966469664796648966499665096651966529665396654966559665696657966589665996660966619666296663966649666596666966679666896669966709667196672966739667496675966769667796678966799668096681966829668396684966859668696687966889668996690966919669296693966949669596696966979669896699967009670196702967039670496705967069670796708967099671096711967129671396714967159671696717967189671996720967219672296723967249672596726967279672896729967309673196732967339673496735967369673796738967399674096741967429674396744967459674696747967489674996750967519675296753967549675596756967579675896759967609676196762967639676496765967669676796768967699677096771967729677396774967759677696777967789677996780967819678296783967849678596786967879678896789967909679196792967939679496795967969679796798967999680096801968029680396804968059680696807968089680996810968119681296813968149681596816968179681896819968209682196822968239682496825968269682796828968299683096831968329683396834968359683696837968389683996840968419684296843968449684596846968479684896849968509685196852968539685496855968569685796858968599686096861968629686396864968659686696867968689686996870968719687296873968749687596876968779687896879968809688196882968839688496885968869688796888968899689096891968929689396894968959689696897968989689996900969019690296903969049690596906969079690896909969109691196912969139691496915969169691796918969199692096921969229692396924969259692696927969289692996930969319693296933969349693596936969379693896939969409694196942969439694496945969469694796948969499695096951969529695396954969559695696957969589695996960969619696296963969649696596966969679696896969969709697196972969739697496975969769697796978969799698096981969829698396984969859698696987969889698996990969919699296993969949699596996969979699896999970009700197002970039700497005970069700797008970099701097011970129701397014970159701697017970189701997020970219702297023970249702597026970279702897029970309703197032970339703497035970369703797038970399704097041970429704397044970459704697047970489704997050970519705297053970549705597056970579705897059970609706197062970639706497065970669706797068970699707097071970729707397074970759707697077970789707997080970819708297083970849708597086970879708897089970909709197092970939709497095970969709797098970999710097101971029710397104971059710697107971089710997110971119711297113971149711597116971179711897119971209712197122971239712497125971269712797128971299713097131971329713397134971359713697137971389713997140971419714297143971449714597146971479714897149971509715197152971539715497155971569715797158971599716097161971629716397164971659716697167971689716997170971719717297173971749717597176971779717897179971809718197182971839718497185971869718797188971899719097191971929719397194971959719697197971989719997200972019720297203972049720597206972079720897209972109721197212972139721497215972169721797218972199722097221972229722397224972259722697227972289722997230972319723297233972349723597236972379723897239972409724197242972439724497245972469724797248972499725097251972529725397254972559725697257972589725997260972619726297263972649726597266972679726897269972709727197272972739727497275972769727797278972799728097281972829728397284972859728697287972889728997290972919729297293972949729597296972979729897299973009730197302973039730497305973069730797308973099731097311973129731397314973159731697317973189731997320973219732297323973249732597326973279732897329973309733197332973339733497335973369733797338973399734097341973429734397344973459734697347973489734997350973519735297353973549735597356973579735897359973609736197362973639736497365973669736797368973699737097371973729737397374973759737697377973789737997380973819738297383973849738597386973879738897389973909739197392973939739497395973969739797398973999740097401974029740397404974059740697407974089740997410974119741297413974149741597416974179741897419974209742197422974239742497425974269742797428974299743097431974329743397434974359743697437974389743997440974419744297443974449744597446974479744897449974509745197452974539745497455974569745797458974599746097461974629746397464974659746697467974689746997470974719747297473974749747597476974779747897479974809748197482974839748497485974869748797488974899749097491974929749397494974959749697497974989749997500975019750297503975049750597506975079750897509975109751197512975139751497515975169751797518975199752097521975229752397524975259752697527975289752997530975319753297533975349753597536975379753897539975409754197542975439754497545975469754797548975499755097551975529755397554975559755697557975589755997560975619756297563975649756597566975679756897569975709757197572975739757497575975769757797578975799758097581975829758397584975859758697587975889758997590975919759297593975949759597596975979759897599976009760197602976039760497605976069760797608976099761097611976129761397614976159761697617976189761997620976219762297623976249762597626976279762897629976309763197632976339763497635976369763797638976399764097641976429764397644976459764697647976489764997650976519765297653976549765597656976579765897659976609766197662976639766497665976669766797668976699767097671976729767397674976759767697677976789767997680976819768297683976849768597686976879768897689976909769197692976939769497695976969769797698976999770097701977029770397704977059770697707977089770997710977119771297713977149771597716977179771897719977209772197722977239772497725977269772797728977299773097731977329773397734977359773697737977389773997740977419774297743977449774597746977479774897749977509775197752977539775497755977569775797758977599776097761977629776397764977659776697767977689776997770977719777297773977749777597776977779777897779977809778197782977839778497785977869778797788977899779097791977929779397794977959779697797977989779997800978019780297803978049780597806978079780897809978109781197812978139781497815978169781797818978199782097821978229782397824978259782697827978289782997830978319783297833978349783597836978379783897839978409784197842978439784497845978469784797848978499785097851978529785397854978559785697857978589785997860978619786297863978649786597866978679786897869978709787197872978739787497875978769787797878978799788097881978829788397884978859788697887978889788997890978919789297893978949789597896978979789897899979009790197902979039790497905979069790797908979099791097911979129791397914979159791697917979189791997920979219792297923979249792597926979279792897929979309793197932979339793497935979369793797938979399794097941979429794397944979459794697947979489794997950979519795297953979549795597956979579795897959979609796197962979639796497965979669796797968979699797097971979729797397974979759797697977979789797997980979819798297983979849798597986979879798897989979909799197992979939799497995979969799797998979999800098001980029800398004980059800698007980089800998010980119801298013980149801598016980179801898019980209802198022980239802498025980269802798028980299803098031980329803398034980359803698037980389803998040980419804298043980449804598046980479804898049980509805198052980539805498055980569805798058980599806098061980629806398064980659806698067980689806998070980719807298073980749807598076980779807898079980809808198082980839808498085980869808798088980899809098091980929809398094980959809698097980989809998100981019810298103981049810598106981079810898109981109811198112981139811498115981169811798118981199812098121981229812398124981259812698127981289812998130981319813298133981349813598136981379813898139981409814198142981439814498145981469814798148981499815098151981529815398154981559815698157981589815998160981619816298163981649816598166981679816898169981709817198172981739817498175981769817798178981799818098181981829818398184981859818698187981889818998190981919819298193981949819598196981979819898199982009820198202982039820498205982069820798208982099821098211982129821398214982159821698217982189821998220982219822298223982249822598226982279822898229982309823198232982339823498235982369823798238982399824098241982429824398244982459824698247982489824998250982519825298253982549825598256982579825898259982609826198262982639826498265982669826798268982699827098271982729827398274982759827698277982789827998280982819828298283982849828598286982879828898289982909829198292982939829498295982969829798298982999830098301983029830398304983059830698307983089830998310983119831298313983149831598316983179831898319983209832198322983239832498325983269832798328983299833098331983329833398334983359833698337983389833998340983419834298343983449834598346983479834898349983509835198352983539835498355983569835798358983599836098361983629836398364983659836698367983689836998370983719837298373983749837598376983779837898379983809838198382983839838498385983869838798388983899839098391983929839398394983959839698397983989839998400984019840298403984049840598406984079840898409984109841198412984139841498415984169841798418984199842098421984229842398424984259842698427984289842998430984319843298433984349843598436984379843898439984409844198442984439844498445984469844798448984499845098451984529845398454984559845698457984589845998460984619846298463984649846598466984679846898469984709847198472984739847498475984769847798478984799848098481984829848398484984859848698487984889848998490984919849298493984949849598496984979849898499985009850198502985039850498505985069850798508985099851098511985129851398514985159851698517985189851998520985219852298523985249852598526985279852898529985309853198532985339853498535985369853798538985399854098541985429854398544985459854698547985489854998550985519855298553985549855598556985579855898559985609856198562985639856498565985669856798568985699857098571985729857398574985759857698577985789857998580985819858298583985849858598586985879858898589985909859198592985939859498595985969859798598985999860098601986029860398604986059860698607986089860998610986119861298613986149861598616986179861898619986209862198622986239862498625986269862798628986299863098631986329863398634986359863698637986389863998640986419864298643986449864598646986479864898649986509865198652986539865498655986569865798658986599866098661986629866398664986659866698667986689866998670986719867298673986749867598676986779867898679986809868198682986839868498685986869868798688986899869098691986929869398694986959869698697986989869998700987019870298703987049870598706987079870898709987109871198712987139871498715987169871798718987199872098721987229872398724987259872698727987289872998730987319873298733987349873598736987379873898739987409874198742987439874498745987469874798748987499875098751987529875398754987559875698757987589875998760987619876298763987649876598766987679876898769987709877198772987739877498775987769877798778987799878098781987829878398784987859878698787987889878998790987919879298793987949879598796987979879898799988009880198802988039880498805988069880798808988099881098811988129881398814988159881698817988189881998820988219882298823988249882598826988279882898829988309883198832988339883498835988369883798838988399884098841988429884398844988459884698847988489884998850988519885298853988549885598856988579885898859988609886198862988639886498865988669886798868988699887098871988729887398874988759887698877988789887998880988819888298883988849888598886988879888898889988909889198892988939889498895988969889798898988999890098901989029890398904989059890698907989089890998910989119891298913989149891598916989179891898919989209892198922989239892498925989269892798928989299893098931989329893398934989359893698937989389893998940989419894298943989449894598946989479894898949989509895198952989539895498955989569895798958989599896098961989629896398964989659896698967989689896998970989719897298973989749897598976989779897898979989809898198982989839898498985989869898798988989899899098991989929899398994989959899698997989989899999000990019900299003990049900599006990079900899009990109901199012990139901499015990169901799018990199902099021990229902399024990259902699027990289902999030990319903299033990349903599036990379903899039990409904199042990439904499045990469904799048990499905099051990529905399054990559905699057990589905999060990619906299063990649906599066990679906899069990709907199072990739907499075990769907799078990799908099081990829908399084990859908699087990889908999090990919909299093990949909599096990979909899099991009910199102991039910499105991069910799108991099911099111991129911399114991159911699117991189911999120991219912299123991249912599126991279912899129991309913199132991339913499135991369913799138991399914099141991429914399144991459914699147991489914999150991519915299153991549915599156991579915899159991609916199162991639916499165991669916799168991699917099171991729917399174991759917699177991789917999180991819918299183991849918599186991879918899189991909919199192991939919499195991969919799198991999920099201992029920399204992059920699207992089920999210992119921299213992149921599216992179921899219992209922199222992239922499225992269922799228992299923099231992329923399234992359923699237992389923999240992419924299243992449924599246992479924899249992509925199252992539925499255992569925799258992599926099261992629926399264992659926699267992689926999270992719927299273992749927599276992779927899279992809928199282992839928499285992869928799288992899929099291992929929399294992959929699297992989929999300993019930299303993049930599306993079930899309993109931199312993139931499315993169931799318993199932099321993229932399324993259932699327993289932999330993319933299333993349933599336993379933899339993409934199342993439934499345993469934799348993499935099351993529935399354993559935699357993589935999360993619936299363993649936599366993679936899369993709937199372993739937499375993769937799378993799938099381993829938399384993859938699387993889938999390993919939299393993949939599396993979939899399994009940199402994039940499405994069940799408994099941099411994129941399414994159941699417994189941999420994219942299423994249942599426994279942899429994309943199432994339943499435994369943799438994399944099441994429944399444994459944699447994489944999450994519945299453994549945599456994579945899459994609946199462994639946499465994669946799468994699947099471994729947399474994759947699477994789947999480994819948299483994849948599486994879948899489994909949199492994939949499495994969949799498994999950099501995029950399504995059950699507995089950999510995119951299513995149951599516995179951899519995209952199522995239952499525995269952799528995299953099531995329953399534995359953699537995389953999540995419954299543995449954599546995479954899549995509955199552995539955499555995569955799558995599956099561995629956399564995659956699567995689956999570995719957299573995749957599576995779957899579995809958199582995839958499585995869958799588995899959099591995929959399594995959959699597995989959999600996019960299603996049960599606996079960899609996109961199612996139961499615996169961799618996199962099621996229962399624996259962699627996289962999630996319963299633996349963599636996379963899639996409964199642996439964499645996469964799648996499965099651996529965399654996559965699657996589965999660996619966299663996649966599666996679966899669996709967199672996739967499675996769967799678996799968099681996829968399684996859968699687996889968999690996919969299693996949969599696996979969899699997009970199702997039970499705997069970799708997099971099711997129971399714997159971699717997189971999720997219972299723997249972599726997279972899729997309973199732997339973499735997369973799738997399974099741997429974399744997459974699747997489974999750997519975299753997549975599756997579975899759997609976199762997639976499765997669976799768997699977099771997729977399774997759977699777997789977999780997819978299783997849978599786997879978899789997909979199792997939979499795997969979799798997999980099801998029980399804998059980699807998089980999810998119981299813998149981599816998179981899819998209982199822998239982499825998269982799828998299983099831998329983399834998359983699837998389983999840998419984299843998449984599846998479984899849998509985199852998539985499855998569985799858998599986099861998629986399864998659986699867998689986999870998719987299873998749987599876998779987899879998809988199882998839988499885998869988799888998899989099891998929989399894998959989699897998989989999900999019990299903999049990599906999079990899909999109991199912999139991499915999169991799918999199992099921999229992399924999259992699927999289992999930999319993299933999349993599936999379993899939999409994199942999439994499945999469994799948999499995099951999529995399954999559995699957999589995999960999619996299963999649996599966999679996899969999709997199972999739997499975999769997799978999799998099981999829998399984999859998699987999889998999990999919999299993999949999599996999979999899999100000100001100002100003100004100005100006100007100008100009100010100011100012100013100014100015100016100017100018100019100020100021100022100023100024100025100026100027100028100029100030100031100032100033100034100035100036100037100038100039100040100041100042100043100044100045100046100047100048100049100050100051100052100053100054100055100056100057100058100059100060100061100062100063100064100065100066100067100068100069100070100071100072100073100074100075100076100077100078100079100080100081100082100083100084100085100086100087100088100089100090100091100092100093100094100095100096100097100098100099100100100101100102100103100104100105100106100107100108100109100110100111100112100113100114100115100116100117100118100119100120100121100122100123100124100125100126100127100128100129100130100131100132100133100134100135100136100137100138100139100140100141100142100143100144100145100146100147100148100149100150100151100152100153100154100155100156100157100158100159100160100161100162100163100164100165100166100167100168100169100170100171100172100173100174100175100176100177100178100179100180100181100182100183100184100185100186100187100188100189100190100191100192100193100194100195100196100197100198100199100200100201100202100203100204100205100206100207100208100209100210100211100212100213100214100215100216100217100218100219100220100221100222100223100224100225100226100227100228100229100230100231100232100233100234100235100236100237100238100239100240100241100242100243100244100245100246100247100248100249100250100251100252100253100254100255100256100257100258100259100260100261100262100263100264100265100266100267100268100269100270100271100272100273100274100275100276100277100278100279100280100281100282100283100284100285100286100287100288100289100290100291100292100293100294100295100296100297100298100299100300100301100302100303100304100305100306100307100308100309100310100311100312100313100314100315100316100317100318100319100320100321100322100323100324100325100326100327100328100329100330100331100332100333100334100335100336100337100338100339100340100341100342100343100344100345100346100347100348100349100350100351100352100353100354100355100356100357100358100359100360100361100362100363100364100365100366100367100368100369100370100371100372100373100374100375100376100377100378100379100380100381100382100383100384100385100386100387100388100389100390100391100392100393100394100395100396100397100398100399100400100401100402100403100404100405100406100407100408100409100410100411100412100413100414100415100416100417100418100419100420100421100422100423100424100425100426100427100428100429100430100431100432100433100434100435100436100437100438100439100440100441100442100443100444100445100446100447100448100449100450100451100452100453100454100455100456100457100458100459100460100461100462100463100464100465100466100467100468100469100470100471100472100473100474100475100476100477100478100479100480100481100482100483100484100485100486100487100488100489100490100491100492100493100494100495100496100497100498100499100500100501100502100503100504100505100506100507100508100509100510100511100512100513100514100515100516100517100518100519100520100521100522100523100524100525100526100527100528100529100530100531100532100533100534100535100536100537100538100539100540100541100542100543100544100545100546100547100548100549100550100551100552100553100554100555100556100557100558100559100560100561100562100563100564100565100566100567100568100569100570100571100572100573100574100575100576100577100578100579100580100581100582100583100584100585100586100587100588100589100590100591100592100593100594100595100596100597100598100599100600100601100602100603100604100605100606100607100608100609100610100611100612100613100614100615100616100617100618100619100620100621100622100623100624100625100626100627100628100629100630100631100632100633100634100635100636100637100638100639100640100641100642100643100644100645100646100647100648100649100650100651100652100653100654100655100656100657100658100659100660100661100662100663100664100665100666100667100668100669100670100671100672100673100674100675100676100677100678100679100680100681100682100683100684100685100686100687100688100689100690100691100692100693100694100695100696100697100698100699100700100701100702100703100704100705100706100707100708100709100710100711100712100713100714100715100716100717100718100719100720100721100722100723100724100725100726100727100728100729100730100731100732100733100734100735100736100737100738100739100740100741100742100743100744100745100746100747100748100749100750100751100752100753100754100755100756100757100758100759100760100761100762100763100764100765100766100767100768100769100770100771100772100773100774100775100776100777100778100779100780100781100782100783100784100785100786100787100788100789100790100791100792100793100794100795100796100797100798100799100800100801100802100803100804100805100806100807100808100809100810100811100812100813100814100815100816100817100818100819100820100821100822100823100824100825100826100827100828100829100830100831100832100833100834100835100836100837100838100839100840100841100842100843100844100845100846100847100848100849100850100851100852100853100854100855100856100857100858100859100860100861100862100863100864100865100866100867100868100869100870100871100872100873100874100875100876100877100878100879100880100881100882100883100884100885100886100887100888100889100890100891100892100893100894100895100896100897100898100899100900100901100902100903100904100905100906100907100908100909100910100911100912100913100914100915100916100917100918100919100920100921100922100923100924100925100926100927100928100929100930100931100932100933100934100935100936100937100938100939100940100941100942100943100944100945100946100947100948100949100950100951100952100953100954100955100956100957100958100959100960100961100962100963100964100965100966100967100968100969100970100971100972100973100974100975100976100977100978100979100980100981100982100983100984100985100986100987100988100989100990100991100992100993100994100995100996100997100998100999101000101001101002101003101004101005101006101007101008101009101010101011101012101013101014101015101016101017101018101019101020101021101022101023101024101025101026101027101028101029101030101031101032101033101034101035101036101037101038101039101040101041101042101043101044101045101046101047101048101049101050101051101052101053101054101055101056101057101058101059101060101061101062101063101064101065101066101067101068101069101070101071101072101073101074101075101076101077101078101079101080101081101082101083101084101085101086101087101088101089101090101091101092101093101094101095101096101097101098101099101100101101101102101103101104101105101106101107101108101109101110101111101112101113101114101115101116101117101118101119101120101121101122101123101124101125101126101127101128101129101130101131101132101133101134101135101136101137101138101139101140101141101142101143101144101145101146101147101148101149101150101151101152101153101154101155101156101157101158101159101160101161101162101163101164101165101166101167101168101169101170101171101172101173101174101175101176101177101178101179101180101181101182101183101184101185101186101187101188101189101190101191101192101193101194101195101196101197101198101199101200101201101202101203101204101205101206101207101208101209101210101211101212101213101214101215101216101217101218101219101220101221101222101223101224101225101226101227101228101229101230101231101232101233101234101235101236101237101238101239101240101241101242101243101244101245101246101247101248101249101250101251101252101253101254101255101256101257101258101259101260101261101262101263101264101265101266101267101268101269101270101271101272101273101274101275101276101277101278101279101280101281101282101283101284101285101286101287101288101289101290101291101292101293101294101295101296101297101298101299101300101301101302101303101304101305101306101307101308101309101310101311101312101313101314101315101316101317101318101319101320101321101322101323101324101325101326101327101328101329101330101331101332101333101334101335101336101337101338101339101340101341101342101343101344101345101346101347101348101349101350101351101352101353101354101355101356101357101358101359101360101361101362101363101364101365101366101367101368101369101370101371101372101373101374101375101376101377101378101379101380101381101382101383101384101385101386101387101388101389101390101391101392101393101394101395101396101397101398101399101400101401101402101403101404101405101406101407101408101409101410101411101412101413101414101415101416101417101418101419101420101421101422101423101424101425101426101427101428101429101430101431101432101433101434101435101436101437101438101439101440101441101442101443101444101445101446101447101448101449101450101451101452101453101454101455101456101457101458101459101460101461101462101463101464101465101466101467101468101469101470101471101472101473101474101475101476101477101478101479101480101481101482101483101484101485101486101487101488101489101490101491101492101493101494101495101496101497101498101499101500101501101502101503101504101505101506101507101508101509101510101511101512101513101514101515101516101517101518101519101520101521101522101523101524101525101526101527101528101529101530101531101532101533101534101535101536101537101538101539101540101541101542101543101544101545101546101547101548101549101550101551101552101553101554101555101556101557101558101559101560101561101562101563101564101565101566101567101568101569101570101571101572101573101574101575101576101577101578101579101580101581101582101583101584101585101586101587101588101589101590101591101592101593101594101595101596101597101598101599101600101601101602101603101604101605101606101607101608101609101610101611101612101613101614101615101616101617101618101619101620101621101622101623101624101625101626101627101628101629101630101631101632101633101634101635101636101637101638101639101640101641101642101643101644101645101646101647101648101649101650101651101652101653101654101655101656101657101658101659101660101661101662101663101664101665101666101667101668101669101670101671101672101673101674101675101676101677101678101679101680101681101682101683101684101685101686101687101688101689101690101691101692101693101694101695101696101697101698101699101700101701101702101703101704101705101706101707101708101709101710101711101712101713101714101715101716101717101718101719101720101721101722101723101724101725101726101727101728101729101730101731101732101733101734101735101736101737101738101739101740101741101742101743101744101745101746101747101748101749101750101751101752101753101754101755101756101757101758101759101760101761101762101763101764101765101766101767101768101769101770101771101772101773101774101775101776101777101778101779101780101781101782101783101784101785101786101787101788101789101790101791101792101793101794101795101796101797101798101799101800101801101802101803101804101805101806101807101808101809101810101811101812101813101814101815101816101817101818101819101820101821101822101823101824101825101826101827101828101829101830101831101832101833101834101835101836101837101838101839101840101841101842101843101844101845101846101847101848101849101850101851101852101853101854101855101856101857101858101859101860101861101862101863101864101865101866101867101868101869101870101871101872101873101874101875101876101877101878101879101880101881101882101883101884101885101886101887101888101889101890101891101892101893101894101895101896101897101898101899101900101901101902101903101904101905101906101907101908101909101910101911101912101913101914101915101916101917101918101919101920101921101922101923101924101925101926101927101928101929101930101931101932101933101934101935101936101937101938101939101940101941101942101943101944101945101946101947101948101949101950101951101952101953101954101955101956101957101958101959101960101961101962101963101964101965101966101967101968101969101970101971101972101973101974101975101976101977101978101979101980101981101982101983101984101985101986101987101988101989101990101991101992101993101994101995101996101997101998101999102000102001102002102003102004102005102006102007102008102009102010102011102012102013102014102015102016102017102018102019102020102021102022102023102024102025102026102027102028102029102030102031102032102033102034102035102036102037102038102039102040102041102042102043102044102045102046102047102048102049102050102051102052102053102054102055102056102057102058102059102060102061102062102063102064102065102066102067102068102069102070102071102072102073102074102075102076102077102078102079102080102081102082102083102084102085102086102087102088102089102090102091102092102093102094102095102096102097102098102099102100102101102102102103102104102105102106102107102108102109102110102111102112102113102114102115102116102117102118102119102120102121102122102123102124102125102126102127102128102129102130102131102132102133102134102135102136102137102138102139102140102141102142102143102144102145102146102147102148102149102150102151102152102153102154102155102156102157102158102159102160102161102162102163102164102165102166102167102168102169102170102171102172102173102174102175102176102177102178102179102180102181102182102183102184102185102186102187102188102189102190102191102192102193102194102195102196102197102198102199102200102201102202102203102204102205102206102207102208102209102210102211102212102213102214102215102216102217102218102219102220102221102222102223102224102225102226102227102228102229102230102231102232102233102234102235102236102237102238102239102240102241102242102243102244102245102246102247102248102249102250102251102252102253102254102255102256102257102258102259102260102261102262102263102264102265102266102267102268102269102270102271102272102273102274102275102276102277102278102279102280102281102282102283102284102285102286102287102288102289102290102291102292102293102294102295102296102297102298102299102300102301102302102303102304102305102306102307102308102309102310102311102312102313102314102315102316102317102318102319102320102321102322102323102324102325102326102327102328102329102330102331102332102333102334102335102336102337102338102339102340102341102342102343102344102345102346102347102348102349102350102351102352102353102354102355102356102357102358102359102360102361102362102363102364102365102366102367102368102369102370102371102372102373102374102375102376102377102378102379102380102381102382102383102384102385102386102387102388102389102390102391102392102393102394102395102396102397102398102399102400102401102402102403102404102405102406102407102408102409102410102411102412102413102414102415102416102417102418102419102420102421102422102423102424102425102426102427102428102429102430102431102432102433102434102435102436102437102438102439102440102441102442102443102444102445102446102447102448102449102450102451102452102453102454102455102456102457102458102459102460102461102462102463102464102465102466102467102468102469102470102471102472102473102474102475102476102477102478102479102480102481102482102483102484102485102486102487102488102489102490102491102492102493102494102495102496102497102498102499102500102501102502102503102504102505102506102507102508102509102510102511102512102513102514102515102516102517102518102519102520102521102522102523102524102525102526102527102528102529102530102531102532102533102534102535102536102537102538102539102540102541102542102543102544102545102546102547102548102549102550102551102552102553102554102555102556102557102558102559102560102561102562102563102564102565102566102567102568102569102570102571102572102573102574102575102576102577102578102579102580102581102582102583102584102585102586102587102588102589102590102591102592102593102594102595102596102597102598102599102600102601102602102603102604102605102606102607102608102609102610102611102612102613102614102615102616102617102618102619102620102621102622102623102624102625102626102627102628102629102630102631102632102633102634102635102636102637102638102639102640102641102642102643102644102645102646102647102648102649102650102651102652102653102654102655102656102657102658102659102660102661102662102663102664102665102666102667102668102669102670102671102672102673102674102675102676102677102678102679102680102681102682102683102684102685102686102687102688102689102690102691102692102693102694102695102696102697102698102699102700102701102702102703102704102705102706102707102708102709102710102711102712102713102714102715102716102717102718102719102720102721102722102723102724102725102726102727102728102729102730102731102732102733102734102735102736102737102738102739102740102741102742102743102744102745102746102747102748102749102750102751102752102753102754102755102756102757102758102759102760102761102762102763102764102765102766102767102768102769102770102771102772102773102774102775102776102777102778102779102780102781102782102783102784102785102786102787102788102789102790102791102792102793102794102795102796102797102798102799102800102801102802102803102804102805102806102807102808102809102810102811102812102813102814102815102816102817102818102819102820102821102822102823102824102825102826102827102828102829102830102831102832102833102834102835102836102837102838102839102840102841102842102843102844102845102846102847102848102849102850102851102852102853102854102855102856102857102858102859102860102861102862102863102864102865102866102867102868102869102870102871102872102873102874102875102876102877102878102879102880102881102882102883102884102885102886102887102888102889102890102891102892102893102894102895102896102897102898102899102900102901102902102903102904102905102906102907102908102909102910102911102912102913102914102915102916102917102918102919102920102921102922102923102924102925102926102927102928102929102930102931102932102933102934102935102936102937102938102939102940102941102942102943102944102945102946102947102948102949102950102951102952102953102954102955102956102957102958102959102960102961102962102963102964102965102966102967102968102969102970102971102972102973102974102975102976102977102978102979102980102981102982102983102984102985102986102987102988102989102990102991102992102993102994102995102996102997102998102999103000103001103002103003103004103005103006103007103008103009103010103011103012103013103014103015103016103017103018103019103020103021103022103023103024103025103026103027103028103029103030103031103032103033103034103035103036103037103038103039103040103041103042103043103044103045103046103047103048103049103050103051103052103053103054103055103056103057103058103059103060103061103062103063103064103065103066103067103068103069103070103071103072103073103074103075103076103077103078103079103080103081103082103083103084103085103086103087103088103089103090103091103092103093103094103095103096103097103098103099103100103101103102103103103104103105103106103107103108103109103110103111103112103113103114103115103116103117103118103119103120103121103122103123103124103125103126103127103128103129103130103131103132103133103134103135103136103137103138103139103140103141103142103143103144103145103146103147103148103149103150103151103152103153103154103155103156103157103158103159103160103161103162103163103164103165103166103167103168103169103170103171103172103173103174103175103176103177103178103179103180103181103182103183103184103185103186103187103188103189103190103191103192103193103194103195103196103197103198103199103200103201103202103203103204103205103206103207103208103209103210103211103212103213103214103215103216103217103218103219103220103221103222103223103224103225103226103227103228103229103230103231103232103233103234103235103236103237103238103239103240103241103242103243103244103245103246103247103248103249103250103251103252103253103254103255103256103257103258103259103260103261103262103263103264103265103266103267103268103269103270103271103272103273103274103275103276103277103278103279103280103281103282103283103284103285103286103287103288103289103290103291103292103293103294103295103296103297103298103299103300103301103302103303103304103305103306103307103308103309103310103311103312103313103314103315103316103317103318103319103320103321103322103323103324103325103326103327103328103329103330103331103332103333103334103335103336103337103338103339103340103341103342103343103344103345103346103347103348103349103350103351103352103353103354103355103356103357103358103359103360103361103362103363103364103365103366103367103368103369103370103371103372103373103374103375103376103377103378103379103380103381103382103383103384103385103386103387103388103389103390103391103392103393103394103395103396103397103398103399103400103401103402103403103404103405103406103407103408103409103410103411103412103413103414103415103416103417103418103419103420103421103422103423103424103425103426103427103428103429103430103431103432103433103434103435103436103437103438103439103440103441103442103443103444103445103446103447103448103449103450103451103452103453103454103455103456103457103458103459103460103461103462103463103464103465103466103467103468103469103470103471103472103473103474103475103476103477103478103479103480103481103482103483103484103485103486103487103488103489103490103491103492103493103494103495103496103497103498103499103500103501103502103503103504103505103506103507103508103509103510103511103512103513103514103515103516103517103518103519103520103521103522103523103524103525103526103527103528103529103530103531103532103533103534103535103536103537103538103539103540103541103542103543103544103545103546103547103548103549103550103551103552103553103554103555103556103557103558103559103560103561103562103563103564103565103566103567103568103569103570103571103572103573103574103575103576103577103578103579103580103581103582103583103584103585103586103587103588103589103590103591103592103593103594103595103596103597103598103599103600103601103602103603103604103605103606103607103608103609103610103611103612103613103614103615103616103617103618103619103620103621103622103623103624103625103626103627103628103629103630103631103632103633103634103635103636103637103638103639103640103641103642103643103644103645103646103647103648103649103650103651103652103653103654103655103656103657103658103659103660103661103662103663103664103665103666103667103668103669103670103671103672103673103674103675103676103677103678103679103680103681103682103683103684103685103686103687103688103689103690103691103692103693103694103695103696103697103698103699103700103701103702103703103704103705103706103707103708103709103710103711103712103713103714103715103716103717103718103719103720103721103722103723103724103725103726103727103728103729103730103731103732103733103734103735103736103737103738103739103740103741103742103743103744103745103746103747103748103749103750103751103752103753103754103755103756103757103758103759103760103761103762103763103764103765103766103767103768103769103770103771103772103773103774103775103776103777103778103779103780103781103782103783103784103785103786103787103788103789103790103791103792103793103794103795103796103797103798103799103800103801103802103803103804103805103806103807103808103809103810103811103812103813103814103815103816103817103818103819103820103821103822103823103824103825103826103827103828103829103830103831103832103833103834103835103836103837103838103839103840103841103842103843103844103845103846103847103848103849103850103851103852103853103854103855103856103857103858103859103860103861103862103863103864103865103866103867103868103869103870103871103872103873103874103875103876103877103878103879103880103881103882103883103884103885103886103887103888103889103890103891103892103893103894103895103896103897103898103899103900103901103902103903103904103905103906103907103908103909103910103911103912103913103914103915103916103917103918103919103920103921103922103923103924103925103926103927103928103929103930103931103932103933103934103935103936103937103938103939103940103941103942103943103944103945103946103947103948103949103950103951103952103953103954103955103956103957103958103959103960103961103962103963103964103965103966103967103968103969103970103971103972103973103974103975103976103977103978103979103980103981103982103983103984103985103986103987103988103989103990103991103992103993103994103995103996103997103998103999104000104001104002104003104004104005104006104007104008104009104010104011104012104013104014104015104016104017104018104019104020104021104022104023104024104025104026104027104028104029104030104031104032104033104034104035104036104037104038104039104040104041104042104043104044104045104046104047104048104049104050104051104052104053104054104055104056104057104058104059104060104061104062104063104064104065104066104067104068104069104070104071104072104073104074104075104076104077104078104079104080104081104082104083104084104085104086104087104088104089104090104091104092104093104094104095104096104097104098104099104100104101104102104103104104104105104106104107104108104109104110104111104112104113104114104115104116104117104118104119104120104121104122104123104124104125104126104127104128104129104130104131104132104133104134104135104136104137104138104139104140104141104142104143104144104145104146104147104148104149104150104151104152104153104154104155104156104157104158104159104160104161104162104163104164104165104166104167104168104169104170104171104172104173104174104175104176104177104178104179104180104181104182104183104184104185104186104187104188104189104190104191104192104193104194104195104196104197104198104199104200104201104202104203104204104205104206104207104208104209104210104211104212104213104214104215104216104217104218104219104220104221104222104223104224104225104226104227104228104229104230104231104232104233104234104235104236104237104238104239104240104241104242104243104244104245104246104247104248104249104250104251104252104253104254104255104256104257104258104259104260104261104262104263104264104265104266104267104268104269104270104271104272104273104274104275104276104277104278104279104280104281104282104283104284104285104286104287104288104289104290104291104292104293104294104295104296104297104298104299104300104301104302104303104304104305104306104307104308104309104310104311104312104313104314104315104316104317104318104319104320104321104322104323104324104325104326104327104328104329104330104331104332104333104334104335104336104337104338104339104340104341104342104343104344104345104346104347104348104349104350104351104352104353104354104355104356104357104358104359104360104361104362104363104364104365104366104367104368104369104370104371104372104373104374104375104376104377104378104379104380104381104382104383104384104385104386104387104388104389104390104391104392104393104394104395104396104397104398104399104400104401104402104403104404104405104406104407104408104409104410104411104412104413104414104415104416104417104418104419104420104421104422104423104424104425104426104427104428104429104430104431104432104433104434104435104436104437104438104439104440104441104442104443104444104445104446104447104448104449104450104451104452104453104454104455104456104457104458104459104460104461104462104463104464104465104466104467104468104469104470104471104472104473104474104475104476104477104478104479104480104481104482104483104484104485104486104487104488104489104490104491104492104493104494104495104496104497104498104499104500104501104502104503104504104505104506104507104508104509104510104511104512104513104514104515104516104517104518104519104520104521104522104523104524104525104526104527104528104529104530104531104532104533104534104535104536104537104538104539104540104541104542104543104544104545104546104547104548104549104550104551104552104553104554104555104556104557104558104559104560104561104562104563104564104565104566104567104568104569104570104571104572104573104574104575104576104577104578104579104580104581104582104583104584104585104586104587104588104589104590104591104592104593104594104595104596104597104598104599104600104601104602104603104604104605104606104607104608104609104610104611104612104613104614104615104616104617104618104619104620104621104622104623104624104625104626104627104628104629104630104631104632104633104634104635104636104637104638104639104640104641104642104643104644104645104646104647104648104649104650104651104652104653104654104655104656104657104658104659104660104661104662104663104664104665104666104667104668104669104670104671104672104673104674104675104676104677104678104679104680104681104682104683104684104685104686104687104688104689104690104691104692104693104694104695104696104697104698104699104700104701104702104703104704104705104706104707104708104709104710104711104712104713104714104715104716104717104718104719104720104721104722104723104724104725104726104727104728104729104730104731104732104733104734104735104736104737104738104739104740104741104742104743104744104745104746104747104748104749104750104751104752104753104754104755104756104757104758104759104760104761104762104763104764104765104766104767104768104769104770104771104772104773104774104775104776104777104778104779104780104781104782104783104784104785104786104787104788104789104790104791104792104793104794104795104796104797104798104799104800104801104802104803104804104805104806104807104808104809104810104811104812104813104814104815104816104817104818104819104820104821104822104823104824104825104826104827104828104829104830104831104832104833104834104835104836104837104838104839104840104841104842104843104844104845104846104847104848104849104850104851104852104853104854104855104856104857104858104859104860104861104862104863104864104865104866104867104868104869104870104871104872104873104874104875104876104877104878104879104880104881104882104883104884104885104886104887104888104889104890104891104892104893104894104895104896104897104898104899104900104901104902104903104904104905104906104907104908104909104910104911104912104913104914104915104916104917104918104919104920104921104922104923104924104925104926104927104928104929104930104931104932104933104934104935104936104937104938104939104940104941104942104943104944104945104946104947104948104949104950104951104952104953104954104955104956104957104958104959104960104961104962104963104964104965104966104967104968104969104970104971104972104973104974104975104976104977104978104979104980104981104982104983104984104985104986104987104988104989104990104991104992104993104994104995104996104997104998104999105000105001105002105003105004105005105006105007105008105009105010105011105012105013105014105015105016105017105018105019105020105021105022105023105024105025105026105027105028105029105030105031105032105033105034105035105036105037105038105039105040105041105042105043105044105045105046105047105048105049105050105051105052105053105054105055105056105057105058105059105060105061105062105063105064105065105066105067105068105069105070105071105072105073105074105075105076105077105078105079105080105081105082105083105084105085105086105087105088105089105090105091105092105093105094105095105096105097105098105099105100105101105102105103105104105105105106105107105108105109105110105111105112105113105114105115105116105117105118105119105120105121105122105123105124105125105126105127105128105129105130105131105132105133105134105135105136105137105138105139105140105141105142105143105144105145105146105147105148105149105150105151105152105153105154105155105156105157105158105159105160105161105162105163105164105165105166105167105168105169105170105171105172105173105174105175105176105177105178105179105180105181105182105183105184105185105186105187105188105189105190105191105192105193105194105195105196105197105198105199105200105201105202105203105204105205105206105207105208105209105210105211105212105213105214105215105216105217105218105219105220105221105222105223105224105225105226105227105228105229105230105231105232105233105234105235105236105237105238105239105240105241105242105243105244105245105246105247105248105249105250105251105252105253105254105255105256105257105258105259105260105261105262105263105264105265105266105267105268105269105270105271105272105273105274105275105276105277105278105279105280105281105282105283105284105285105286105287105288105289105290105291105292105293105294105295105296105297105298105299105300105301105302105303105304105305105306105307105308105309105310105311105312105313105314105315105316105317105318105319105320105321105322105323105324105325105326105327105328105329105330105331105332105333105334105335105336105337105338105339105340105341105342105343105344105345105346105347105348105349105350105351105352105353105354105355105356105357105358105359105360105361105362105363105364105365105366105367105368105369105370105371105372105373105374105375105376105377105378105379105380105381105382105383105384105385105386105387105388105389105390105391105392105393105394105395105396105397105398105399105400105401105402105403105404105405105406105407105408105409105410105411105412105413105414105415105416105417105418105419105420105421105422105423105424105425105426105427105428105429105430105431105432105433105434105435105436105437105438105439105440105441105442105443105444105445105446105447105448105449105450105451105452105453105454105455105456105457105458105459105460105461105462105463105464105465105466105467105468105469105470105471105472105473105474105475105476105477105478105479105480105481105482105483105484105485105486105487105488105489105490105491105492105493105494105495105496105497105498105499105500105501105502105503105504105505105506105507105508105509105510105511105512105513105514105515105516105517105518105519105520105521105522105523105524105525105526105527105528105529105530105531105532105533105534105535105536105537105538105539105540105541105542105543105544105545105546105547105548105549105550105551105552105553105554105555105556105557105558105559105560105561105562105563105564105565105566105567105568105569105570105571105572105573105574105575105576105577105578105579105580105581105582105583105584105585105586105587105588105589105590105591105592105593105594105595105596105597105598105599105600105601105602105603105604105605105606105607105608105609105610105611105612105613105614105615105616105617105618105619105620105621105622105623105624105625105626105627105628105629105630105631105632105633105634105635105636105637105638105639105640105641105642105643105644105645105646105647105648105649105650105651105652105653105654105655105656105657105658105659105660105661105662105663105664105665105666105667105668105669105670105671105672105673105674105675105676105677105678105679105680105681105682105683105684105685105686105687105688105689105690105691105692105693105694105695105696105697105698105699105700105701105702105703105704105705105706105707105708105709105710105711105712105713105714105715105716105717105718105719105720105721105722105723105724105725105726105727105728105729105730105731105732105733105734105735105736105737105738105739105740105741105742105743105744105745105746105747105748105749105750105751105752105753105754105755105756105757105758105759105760105761105762105763105764105765105766105767105768105769105770105771105772105773105774105775105776105777105778105779105780105781105782105783105784105785105786105787105788105789105790105791105792105793105794105795105796105797105798105799105800105801105802105803105804105805105806105807105808105809105810105811105812105813105814105815105816105817105818105819105820105821105822105823105824105825105826105827105828105829105830105831105832105833105834105835105836105837105838105839105840105841105842105843105844105845105846105847105848105849105850105851105852105853105854105855105856105857105858105859105860105861105862105863105864105865105866105867105868105869105870105871105872105873105874105875105876105877105878105879105880105881105882105883105884105885105886105887105888105889105890105891105892105893105894105895105896105897105898105899105900105901105902105903105904105905105906105907105908105909105910105911105912105913105914105915105916105917105918105919105920105921105922105923105924105925105926105927105928105929105930105931105932105933105934105935105936105937105938105939105940105941105942105943105944105945105946105947105948105949105950105951105952105953105954105955105956105957105958105959105960105961105962105963105964105965105966105967105968105969105970105971105972105973105974105975105976105977105978105979105980105981105982105983105984105985105986105987105988105989105990105991105992105993105994105995105996105997105998105999106000106001106002106003106004106005106006106007106008106009106010106011106012106013106014106015106016106017106018106019106020106021106022106023106024106025106026106027106028106029106030106031106032106033106034106035106036106037106038106039106040106041106042106043106044106045106046106047106048106049106050106051106052106053106054106055106056106057106058106059106060106061106062106063106064106065106066106067106068106069106070106071106072106073106074106075106076106077106078106079106080106081106082106083106084106085106086106087106088106089106090106091106092106093106094106095106096106097106098106099106100106101106102106103106104106105106106106107106108106109106110106111106112106113106114106115106116106117106118106119106120106121106122106123106124106125106126106127106128106129106130106131106132106133106134106135106136106137106138106139106140106141106142106143106144106145106146106147106148106149106150106151106152106153106154106155106156106157106158106159106160106161106162106163106164106165106166106167106168106169106170106171106172106173106174106175106176106177106178106179106180106181106182106183106184106185106186106187106188106189106190106191106192106193106194106195106196106197106198106199106200106201106202106203106204106205106206106207106208106209106210106211106212106213106214106215106216106217106218106219106220106221106222106223106224106225106226106227106228106229106230106231106232106233106234106235106236106237106238106239106240106241106242106243106244106245106246106247106248106249106250106251106252106253106254106255106256106257106258106259106260106261106262106263106264106265106266106267106268106269106270106271106272106273106274106275106276106277106278106279106280106281106282106283106284106285106286106287106288106289106290106291106292106293106294106295106296106297106298106299106300106301106302106303106304106305106306106307106308106309106310106311106312106313106314106315106316106317106318106319106320106321106322106323106324106325106326106327106328106329106330106331106332106333106334106335106336106337106338106339106340106341106342106343106344106345106346106347106348106349106350106351106352106353106354106355106356106357106358106359106360106361106362106363106364106365106366106367106368106369106370106371106372106373106374106375106376106377106378106379106380106381106382106383106384106385106386106387106388106389106390106391106392106393106394106395106396106397106398106399106400106401106402106403106404106405106406106407106408106409106410106411106412106413106414106415106416106417106418106419106420106421106422106423106424106425106426106427106428106429106430106431106432106433106434106435106436106437106438106439106440106441106442106443106444106445106446106447106448106449106450106451106452106453106454106455106456106457106458106459106460106461106462106463106464106465106466106467106468106469106470106471106472106473106474106475106476106477106478106479106480106481106482106483106484106485106486106487106488106489106490106491106492106493106494106495106496106497106498106499106500106501106502106503106504106505106506106507106508106509106510106511106512106513106514106515106516106517106518106519106520106521106522106523106524106525106526106527106528106529106530106531106532106533106534106535106536106537106538106539106540106541106542106543106544106545106546106547106548106549106550106551106552106553106554106555106556106557106558106559106560106561106562106563106564106565106566106567106568106569106570106571106572106573106574106575106576106577106578106579106580106581106582106583106584106585106586106587106588106589106590106591106592106593106594106595106596106597106598106599106600106601106602106603106604106605106606106607106608106609106610106611106612106613106614106615106616106617106618106619106620106621106622106623106624106625106626106627106628106629106630106631106632106633106634106635106636106637106638106639106640106641106642106643106644106645106646106647106648106649106650106651106652106653106654106655106656106657106658106659106660106661106662106663106664106665106666106667106668106669106670106671106672106673106674106675106676106677106678106679106680106681106682106683106684106685106686106687106688106689106690106691106692106693106694106695106696106697106698106699106700106701106702106703106704106705106706106707106708106709106710106711106712106713106714106715106716106717106718106719106720106721106722106723106724106725106726106727106728106729106730106731106732106733106734106735106736106737106738106739106740106741106742106743106744106745106746106747106748106749106750106751106752106753106754106755106756106757106758106759106760106761106762106763106764106765106766106767106768106769106770106771106772106773106774106775106776106777106778106779106780106781106782106783106784106785106786106787106788106789106790106791106792106793106794106795106796106797106798106799106800106801106802106803106804106805106806106807106808106809106810106811106812106813106814106815106816106817106818106819106820106821106822106823106824106825106826106827106828106829106830106831106832106833106834106835106836106837106838106839106840106841106842106843106844106845106846106847106848106849106850106851106852106853106854106855106856106857106858106859106860106861106862106863106864106865106866106867106868106869106870106871106872106873106874106875106876106877106878106879106880106881106882106883106884106885106886106887106888106889106890106891106892106893106894106895106896106897106898106899106900106901106902106903106904106905106906106907106908106909106910106911106912106913106914106915106916106917106918106919106920106921106922106923106924106925106926106927106928106929106930106931106932106933106934106935106936106937106938106939106940106941106942106943106944106945106946106947106948106949106950106951106952106953106954106955106956106957106958106959106960106961106962106963106964106965106966106967106968106969106970106971106972106973106974106975106976106977106978106979106980106981106982106983106984106985106986106987106988106989106990106991106992106993106994106995106996106997106998106999107000107001107002107003107004107005107006107007107008107009107010107011107012107013107014107015107016107017107018107019107020107021107022107023107024107025107026107027107028107029107030107031107032107033107034107035107036107037107038107039107040107041107042107043107044107045107046107047107048107049107050107051107052107053107054107055107056107057107058107059107060107061107062107063107064107065107066107067107068107069107070107071107072107073107074107075107076107077107078107079107080107081107082107083107084107085107086107087107088107089107090107091107092107093107094107095107096107097107098107099107100107101107102107103107104107105107106107107107108107109107110107111107112107113107114107115107116107117107118107119107120107121107122107123107124107125107126107127107128107129107130107131107132107133107134107135107136107137107138107139107140107141107142107143107144107145107146107147107148107149107150107151107152107153107154107155107156107157107158107159107160107161107162107163107164107165107166107167107168107169107170107171107172107173107174107175107176107177107178107179107180107181107182107183107184107185107186107187107188107189107190107191107192107193107194107195107196107197107198107199107200107201107202107203107204107205107206107207107208107209107210107211107212107213107214107215107216107217107218107219107220107221107222107223107224107225107226107227107228107229107230107231107232107233107234107235107236107237107238107239107240107241107242107243107244107245107246107247107248107249107250107251107252107253107254107255107256107257107258107259107260107261107262107263107264107265107266107267107268107269107270107271107272107273107274107275107276107277107278107279107280107281107282107283107284107285107286107287107288107289107290107291107292107293107294107295107296107297107298107299107300107301107302107303107304107305107306107307107308107309107310107311107312107313107314107315107316107317107318107319107320107321107322107323107324107325107326107327107328107329107330107331107332107333107334107335107336107337107338107339107340107341107342107343107344107345107346107347107348107349107350107351107352107353107354107355107356107357107358107359107360107361107362107363107364107365107366107367107368107369107370107371107372107373107374107375107376107377107378107379107380107381107382107383107384107385107386107387107388107389107390107391107392107393107394107395107396107397107398107399107400107401107402107403107404107405107406107407107408107409107410107411107412107413107414107415107416107417107418107419107420107421107422107423107424107425107426107427107428107429107430107431107432107433107434107435107436107437107438107439107440107441107442107443107444107445107446107447107448107449107450107451107452107453107454107455107456107457107458107459107460107461107462107463107464107465107466107467107468107469107470107471107472107473107474107475107476107477107478107479107480107481107482107483107484107485107486107487107488107489107490107491107492107493107494107495107496107497107498107499107500107501107502107503107504107505107506107507107508107509107510107511107512107513107514107515107516107517107518107519107520107521107522107523107524107525107526107527107528107529107530107531107532107533107534107535107536107537107538107539107540107541107542107543107544107545107546107547107548107549107550107551107552107553107554107555107556107557107558107559107560107561107562107563107564107565107566107567107568107569107570107571107572107573107574107575107576107577107578107579107580107581107582107583107584107585107586107587107588107589107590107591107592107593107594107595107596107597107598107599107600107601107602107603107604107605107606107607107608107609107610107611107612107613107614107615107616107617107618107619107620107621107622107623107624107625107626107627107628107629107630107631107632107633107634107635107636107637107638107639107640107641107642107643107644107645107646107647107648107649107650107651107652107653107654107655107656107657107658107659107660107661107662107663107664107665107666107667107668107669107670107671107672107673107674107675107676107677107678107679107680107681107682107683107684107685107686107687107688107689107690107691107692107693107694107695107696107697107698107699107700107701107702107703107704107705107706107707107708107709107710107711107712107713107714107715107716107717107718107719107720107721107722107723107724107725107726107727107728107729107730107731107732107733107734107735107736107737107738107739107740107741107742107743107744107745107746107747107748107749107750107751107752107753107754107755107756107757107758107759107760107761107762107763107764107765107766107767107768107769107770107771107772107773107774107775107776107777107778107779107780107781107782107783107784107785107786107787107788107789107790107791107792107793107794107795107796107797107798107799107800107801107802107803107804107805107806107807107808107809107810107811107812107813107814107815107816107817107818107819107820107821107822107823107824107825107826107827107828107829107830107831107832107833107834107835107836107837107838107839107840107841107842107843107844107845107846107847107848107849107850107851107852107853107854107855107856107857107858107859107860107861107862107863107864107865107866107867107868107869107870107871107872107873107874107875107876107877107878107879107880107881107882107883107884107885107886107887107888107889107890107891107892107893107894107895107896107897107898107899107900107901107902107903107904107905107906107907107908107909107910107911107912107913107914107915107916107917107918107919107920107921107922107923107924107925107926107927107928107929107930107931107932107933107934107935107936107937107938107939107940107941107942107943107944107945107946107947107948107949107950107951107952107953107954107955107956107957107958107959107960107961107962107963107964107965107966107967107968107969107970107971107972107973107974107975107976107977107978107979107980107981107982107983107984107985107986107987107988107989107990107991107992107993107994107995107996107997107998107999108000108001108002108003108004108005108006108007108008108009108010108011108012108013108014108015108016108017108018108019108020108021108022108023108024108025108026108027108028108029108030108031108032108033108034108035108036108037108038108039108040108041108042108043108044108045108046108047108048108049108050108051108052108053108054108055108056108057108058108059108060108061108062108063108064108065108066108067108068108069108070108071108072108073108074108075108076108077108078108079108080108081108082108083108084108085108086108087108088108089108090108091108092108093108094108095108096108097108098108099108100108101108102108103108104108105108106108107108108108109108110108111108112108113108114108115108116108117108118108119108120108121108122108123108124108125108126108127108128108129108130108131108132108133108134108135108136108137108138108139108140108141108142108143108144108145108146108147108148108149108150108151108152108153108154108155108156108157108158108159108160108161108162108163108164108165108166108167108168108169108170108171108172108173108174108175108176108177108178108179108180108181108182108183108184108185108186108187108188108189108190108191108192108193108194108195108196108197108198108199108200108201108202108203108204108205108206108207108208108209108210108211108212108213108214108215108216108217108218108219108220108221108222108223108224108225108226108227108228108229108230108231108232108233108234108235108236108237108238108239108240108241108242108243108244108245108246108247108248108249108250108251108252108253108254108255108256108257108258108259108260108261108262108263108264108265108266108267108268108269108270108271108272108273108274108275108276108277108278108279108280108281108282108283108284108285108286108287108288108289108290108291108292108293108294108295108296108297108298108299108300108301108302108303108304108305108306108307108308108309108310108311108312108313108314108315108316108317108318108319108320108321108322108323108324108325108326108327108328108329108330108331108332108333108334108335108336108337108338108339108340108341108342108343108344108345108346108347108348108349108350108351108352108353108354108355108356108357108358108359108360108361108362108363108364108365108366108367108368108369108370108371108372108373108374108375108376108377108378108379108380108381108382108383108384108385108386108387108388108389108390108391108392108393108394108395108396108397108398108399108400108401108402108403108404108405108406108407108408108409108410108411108412108413108414108415108416108417108418108419108420108421108422108423108424108425108426108427108428108429108430108431108432108433108434108435108436108437108438108439108440108441108442108443108444108445108446108447108448108449108450108451108452108453108454108455108456108457108458108459108460108461108462108463108464108465108466108467108468108469108470108471108472108473108474108475108476108477108478108479108480108481108482108483108484108485108486108487108488108489108490108491108492108493108494108495108496108497108498108499108500108501108502108503108504108505108506108507108508108509108510108511108512108513108514108515108516108517108518108519108520108521108522108523108524108525108526108527108528108529108530108531108532108533108534108535108536108537108538108539108540108541108542108543108544108545108546108547108548108549108550108551108552108553108554108555108556108557108558108559108560108561108562108563108564108565108566108567108568108569108570108571108572108573108574108575108576108577108578108579108580108581108582108583108584108585108586108587108588108589108590108591108592108593108594108595108596108597108598108599108600108601108602108603108604108605108606108607108608108609108610108611108612108613108614108615108616108617108618108619108620108621108622108623108624108625108626108627108628108629108630108631108632108633108634108635108636108637108638108639108640108641108642108643108644108645108646108647108648108649108650108651108652108653108654108655108656108657108658108659108660108661108662108663108664108665108666108667108668108669108670108671108672108673108674108675108676108677108678108679108680108681108682108683108684108685108686108687108688108689108690108691108692108693108694108695108696108697108698108699108700108701108702108703108704108705108706108707108708108709108710108711108712108713108714108715108716108717108718108719108720108721108722108723108724108725108726108727108728108729108730108731108732108733108734108735108736108737108738108739108740108741108742108743108744108745108746108747108748108749108750108751108752108753108754108755108756108757108758108759108760108761108762108763108764108765108766108767108768108769108770108771108772108773108774108775108776108777108778108779108780108781108782108783108784108785108786108787108788108789108790108791108792108793108794108795108796108797108798108799108800108801108802108803108804108805108806108807108808108809108810108811108812108813108814108815108816108817108818108819108820108821108822108823108824108825108826108827108828108829108830108831108832108833108834108835108836108837108838108839108840108841108842108843108844108845108846108847108848108849108850108851108852108853108854108855108856108857108858108859108860108861108862108863108864108865108866108867108868108869108870108871108872108873108874108875108876108877108878108879108880108881108882108883108884108885108886108887108888108889108890108891108892108893108894108895108896108897108898108899108900108901108902108903108904108905108906108907108908108909108910108911108912108913108914108915108916108917108918108919108920108921108922108923108924108925108926108927108928108929108930108931108932108933108934108935108936108937108938108939108940108941108942108943108944108945108946108947108948108949108950108951108952108953108954108955108956108957108958108959108960108961108962108963108964108965108966108967108968108969108970108971108972108973108974108975108976108977108978108979108980108981108982108983108984108985108986108987108988108989108990108991108992108993108994108995108996108997108998108999109000109001109002109003109004109005109006109007109008109009109010109011109012109013109014109015109016109017109018109019109020109021109022109023109024109025109026109027109028109029109030109031109032109033109034109035109036109037109038109039109040109041109042109043109044109045109046109047109048109049109050109051109052109053109054109055109056109057109058109059109060109061109062109063109064109065109066109067109068109069109070109071109072109073109074109075109076109077109078109079109080109081109082109083109084109085109086109087109088109089109090109091109092109093109094109095109096109097109098109099109100109101109102109103109104109105109106109107109108109109109110109111109112109113109114109115109116109117109118109119109120109121109122109123109124109125109126109127109128109129109130109131109132109133109134109135109136109137109138109139109140109141109142109143109144109145109146109147109148109149109150109151109152109153109154109155109156109157109158109159109160109161109162109163109164109165109166109167109168109169109170109171109172109173109174109175109176109177109178109179109180109181109182109183109184109185109186109187109188109189109190109191109192109193109194109195109196109197109198109199109200109201109202109203109204109205109206109207109208109209109210109211109212109213109214109215109216109217109218109219109220109221109222109223109224109225109226109227109228109229109230109231109232109233109234109235109236109237109238109239109240109241109242109243109244109245109246109247109248109249109250109251109252109253109254109255109256109257109258109259109260109261109262109263109264109265109266109267109268109269109270109271109272109273109274109275109276109277109278109279109280109281109282109283109284109285109286109287109288109289109290109291109292109293109294109295109296109297109298109299109300109301109302109303109304109305109306109307109308109309109310109311109312109313109314109315109316109317109318109319109320109321109322109323109324109325109326109327109328109329109330109331109332109333109334109335109336109337109338109339109340109341109342109343109344109345109346109347109348109349109350109351109352109353109354109355109356109357109358109359109360109361109362109363109364109365109366109367109368109369109370109371109372109373109374109375109376109377109378109379109380109381109382109383109384109385109386109387109388109389109390109391109392109393109394109395109396109397109398109399109400109401109402109403109404109405109406109407109408109409109410109411109412109413109414109415109416109417109418109419109420109421109422109423109424109425109426109427109428109429109430109431109432109433109434109435109436109437109438109439109440109441109442109443109444109445109446109447109448109449109450109451109452109453109454109455109456109457109458109459109460109461109462109463109464109465109466109467109468109469109470109471109472109473109474109475109476109477109478109479109480109481109482109483109484109485109486109487109488109489109490109491109492109493109494109495109496109497109498109499109500109501109502109503109504109505109506109507109508109509109510109511109512109513109514109515109516109517109518109519109520109521109522109523109524109525109526109527109528109529109530109531109532109533109534109535109536109537109538109539109540109541109542109543109544109545109546109547109548109549109550109551109552109553109554109555109556109557109558109559109560109561109562109563109564109565109566109567109568109569109570109571109572109573109574109575109576109577109578109579109580109581109582109583109584109585109586109587109588109589109590109591109592109593109594109595109596109597109598109599109600109601109602109603109604109605109606109607109608109609109610109611109612109613109614109615109616109617109618109619109620109621109622109623109624109625109626109627109628109629109630109631109632109633109634109635109636109637109638109639109640109641109642109643109644109645109646109647109648109649109650109651109652109653109654109655109656109657109658109659109660109661109662109663109664109665109666109667109668109669109670109671109672109673109674109675109676109677109678109679109680109681109682109683109684109685109686109687109688109689109690109691109692109693109694109695109696109697109698109699109700109701109702109703109704109705109706109707109708109709109710109711109712109713109714109715109716109717109718109719109720109721109722109723109724109725109726109727109728109729109730109731109732109733109734109735109736109737109738109739109740109741109742109743109744109745109746109747109748109749109750109751109752109753109754109755109756109757109758109759109760109761109762109763109764109765109766109767109768109769109770109771109772109773109774109775109776109777109778109779109780109781109782109783109784109785109786109787109788109789109790109791109792109793109794109795109796109797109798109799109800109801109802109803109804109805109806109807109808109809109810109811109812109813109814109815109816109817109818109819109820109821109822109823109824109825109826109827109828109829109830109831109832109833109834109835109836109837109838109839109840109841109842109843109844109845109846109847109848109849109850109851109852109853109854109855109856109857109858109859109860109861109862109863109864109865109866109867109868109869109870109871109872109873109874109875109876109877109878109879109880109881109882109883109884109885109886109887109888109889109890109891109892109893109894109895109896109897109898109899109900109901109902109903109904109905109906109907109908109909109910109911109912109913109914109915109916109917109918109919109920109921109922109923109924109925109926109927109928109929109930109931109932109933109934109935109936109937109938109939109940109941109942109943109944109945109946109947109948109949109950109951109952109953109954109955109956109957109958109959109960109961109962109963109964109965109966109967109968109969109970109971109972109973109974109975109976109977109978109979109980109981109982109983109984109985109986109987109988109989109990109991109992109993109994109995109996109997109998109999110000110001110002110003110004110005110006110007110008110009110010110011110012110013110014110015110016110017110018110019110020110021110022110023110024110025110026110027110028110029110030110031110032110033110034110035110036110037110038110039110040110041110042110043110044110045110046110047110048110049110050110051110052110053110054110055110056110057110058110059110060110061110062110063110064110065110066110067110068110069110070110071110072110073110074110075110076110077110078110079110080110081110082110083110084110085110086110087110088110089110090110091110092110093110094110095110096110097110098110099110100110101110102110103110104110105110106110107110108110109110110110111110112110113110114110115110116110117110118110119110120110121110122110123110124110125110126110127110128110129110130110131110132110133110134110135110136110137110138110139110140110141110142110143110144110145110146110147110148110149110150110151110152110153110154110155110156110157110158110159110160110161110162110163110164110165110166110167110168110169110170110171110172110173110174110175110176110177110178110179110180110181110182110183110184110185110186110187110188110189110190110191110192110193110194110195110196110197110198110199110200110201110202110203110204110205110206110207110208110209110210110211110212110213110214110215110216110217110218110219110220110221110222110223110224110225110226110227110228110229110230110231110232110233110234110235110236110237110238110239110240110241110242110243110244110245110246110247110248110249110250110251110252110253110254110255110256110257110258110259110260110261110262110263110264110265110266110267110268110269110270110271110272110273110274110275110276110277110278110279110280110281110282110283110284110285110286110287110288110289110290110291110292110293110294110295110296110297110298110299110300110301110302110303110304110305110306110307110308110309110310110311110312110313110314110315110316110317110318110319110320110321110322110323110324110325110326110327110328110329110330110331110332110333110334110335110336110337110338110339110340110341110342110343110344110345110346110347110348110349110350110351110352110353110354110355110356110357110358110359110360110361110362110363110364110365110366110367110368110369110370110371110372110373110374110375110376110377110378110379110380110381110382110383110384110385110386110387110388110389110390110391110392110393110394110395110396110397110398110399110400110401110402110403110404110405110406110407110408110409110410110411110412110413110414110415110416110417110418110419110420110421110422110423110424110425110426110427110428110429110430110431110432110433110434110435110436110437110438110439110440110441110442110443110444110445110446110447110448110449110450110451110452110453110454110455110456110457110458110459110460110461110462110463110464110465110466110467110468110469110470110471110472110473110474110475110476110477110478110479110480110481110482110483110484110485110486110487110488110489110490110491110492110493110494110495110496110497110498110499110500110501110502110503110504110505110506110507110508110509110510110511110512110513110514110515110516110517110518110519110520110521110522110523110524110525110526110527110528110529110530110531110532110533110534110535110536110537110538110539110540110541110542110543110544110545110546110547110548110549110550110551110552110553110554110555110556110557110558110559110560110561110562110563110564110565110566110567110568110569110570110571110572110573110574110575110576110577110578110579110580110581110582110583110584110585110586110587110588110589110590110591110592110593110594110595110596110597110598110599110600110601110602110603110604110605110606110607110608110609110610110611110612110613110614110615110616110617110618110619110620110621110622110623110624110625110626110627110628110629110630110631110632110633110634110635110636110637110638110639110640110641110642110643110644110645110646110647110648110649110650110651110652110653110654110655110656110657110658110659110660110661110662110663110664110665110666110667110668110669110670110671110672110673110674110675110676110677110678110679110680110681110682110683110684110685110686110687110688110689110690110691110692110693110694110695110696110697110698110699110700110701110702110703110704110705110706110707110708110709110710110711110712110713110714110715110716110717110718110719110720110721110722110723110724110725110726110727110728110729110730110731110732110733110734110735110736110737110738110739110740110741110742110743110744110745110746110747110748110749110750110751110752110753110754110755110756110757110758110759110760110761110762110763110764110765110766110767110768110769110770110771110772110773110774110775110776110777110778110779110780110781110782110783110784110785110786110787110788110789110790110791110792110793110794110795110796110797110798110799110800110801110802110803110804110805110806110807110808110809110810110811110812110813110814110815110816110817110818110819110820110821110822110823110824110825110826110827110828110829110830110831110832110833110834110835110836110837110838110839110840110841110842110843110844110845110846110847110848110849110850110851110852110853110854110855110856110857110858110859110860110861110862110863110864110865110866110867110868110869110870110871110872110873110874110875110876110877110878110879110880110881110882110883110884110885110886110887110888110889110890110891110892110893110894110895110896110897110898110899110900110901110902110903110904110905110906110907110908110909110910110911110912110913110914110915110916110917110918110919110920110921110922110923110924110925110926110927110928110929110930110931110932110933110934110935110936110937110938110939110940110941110942110943110944110945110946110947110948110949110950110951110952110953110954110955110956110957110958110959110960110961110962110963110964110965110966110967110968110969110970110971110972110973110974110975110976110977110978110979110980110981110982110983110984110985110986110987110988110989110990110991110992110993110994110995110996110997110998110999111000111001111002111003111004111005111006111007111008111009111010111011111012111013111014111015111016111017111018111019111020111021111022111023111024111025111026111027111028111029111030111031111032111033111034111035111036111037111038111039111040111041111042111043111044111045111046111047111048111049111050111051111052111053111054111055111056111057111058111059111060111061111062111063111064111065111066111067111068111069111070111071111072111073111074111075111076111077111078111079111080111081111082111083111084111085111086111087111088111089111090111091111092111093111094111095111096111097111098111099111100111101111102111103111104111105111106111107111108111109111110111111111112111113111114111115111116111117111118111119111120111121111122111123111124111125111126111127111128111129111130111131111132111133111134111135111136111137111138111139111140111141111142111143111144111145111146111147111148111149111150111151111152111153111154111155111156111157111158111159111160111161111162111163111164111165111166111167111168111169111170111171111172111173111174111175111176111177111178111179111180111181111182111183111184111185111186111187111188111189111190111191111192111193111194111195111196111197111198111199111200111201111202111203111204111205111206111207111208111209111210111211111212111213111214111215111216111217111218111219111220111221111222111223111224111225111226111227111228111229111230111231111232111233111234111235111236111237111238111239111240111241111242111243111244111245111246111247111248111249111250111251111252111253111254111255111256111257111258111259111260111261111262111263111264111265111266111267111268111269111270111271111272111273111274111275111276111277111278111279111280111281111282111283111284111285111286111287111288111289111290111291111292111293111294111295111296111297111298111299111300111301111302111303111304111305111306111307111308111309111310111311111312111313111314111315111316111317111318111319111320111321111322111323111324111325111326111327111328111329111330111331111332111333111334111335111336111337111338111339111340111341111342111343111344111345111346111347111348111349111350111351111352111353111354111355111356111357111358111359111360111361111362111363111364111365111366111367111368111369111370111371111372111373111374111375111376111377111378111379111380111381111382111383111384111385111386111387111388111389111390111391111392111393111394111395111396111397111398111399111400111401111402111403111404111405111406111407111408111409111410111411111412111413111414111415111416111417111418111419111420111421111422111423111424111425111426111427111428111429111430111431111432111433111434111435111436111437111438111439111440111441111442111443111444111445111446111447111448111449111450111451111452111453111454111455111456111457111458111459111460111461111462111463111464111465111466111467111468111469111470111471111472111473111474111475111476111477111478111479111480111481111482111483111484111485111486111487111488111489111490111491111492111493111494111495111496111497111498111499111500111501111502111503111504111505111506111507111508111509111510111511111512111513111514111515111516111517111518111519111520111521111522111523111524111525111526111527111528111529111530111531111532111533111534111535111536111537111538111539111540111541111542111543111544111545111546111547111548111549111550111551111552111553111554111555111556111557111558111559111560111561111562111563111564111565111566111567111568111569111570111571111572111573111574111575111576111577111578111579111580111581111582111583111584111585111586111587111588111589111590111591111592111593111594111595111596111597111598111599111600111601111602111603111604111605111606111607111608111609111610111611111612111613111614111615111616111617111618111619111620111621111622111623111624111625111626111627111628111629111630111631111632111633111634111635111636111637111638111639111640111641111642111643111644111645111646111647111648111649111650111651111652111653111654111655111656111657111658111659111660111661111662111663111664111665111666111667111668111669111670111671111672111673111674111675111676111677111678111679111680111681111682111683111684111685111686111687111688111689111690111691111692111693111694111695111696111697111698111699111700111701111702111703111704111705111706111707111708111709111710111711111712111713111714111715111716111717111718111719111720111721111722111723111724111725111726111727111728111729111730111731111732111733111734111735111736111737111738111739111740111741111742111743111744111745111746111747111748111749111750111751111752111753111754111755111756111757111758111759111760111761111762111763111764111765111766111767111768111769111770111771111772111773111774111775111776111777111778111779111780111781111782111783111784111785111786111787111788111789111790111791111792111793111794111795111796111797111798111799111800111801111802111803111804111805111806111807111808111809111810111811111812111813111814111815111816111817111818111819111820111821111822111823111824111825111826111827111828111829111830111831111832111833111834111835111836111837111838111839111840111841111842111843111844111845111846111847111848111849111850111851111852111853111854111855111856111857111858111859111860111861111862111863111864111865111866111867111868111869111870111871111872111873111874111875111876111877111878111879111880111881111882111883111884111885111886111887111888111889111890111891111892111893111894111895111896111897111898111899111900111901111902111903111904111905111906111907111908111909111910111911111912111913111914111915111916111917111918111919111920111921111922111923111924111925111926111927111928111929111930111931111932111933111934111935111936111937111938111939111940111941111942111943111944111945111946111947111948111949111950111951111952111953111954111955111956111957111958111959111960111961111962111963111964111965111966111967111968111969111970111971111972111973111974111975111976111977111978111979111980111981111982111983111984111985111986111987111988111989111990111991111992111993111994111995111996111997111998111999112000112001112002112003112004112005112006112007112008112009112010112011112012112013112014112015112016112017112018112019112020112021112022112023112024112025112026112027112028112029112030112031112032112033112034112035112036112037112038112039112040112041112042112043112044112045112046112047112048112049112050112051112052112053112054112055112056112057112058112059112060112061112062112063112064112065112066112067112068112069112070112071112072112073112074112075112076112077112078112079112080112081112082112083112084112085112086112087112088112089112090112091112092112093112094112095112096112097112098112099112100112101112102112103112104112105112106112107112108112109112110112111112112112113112114112115112116112117112118112119112120112121112122112123112124112125112126112127112128112129112130112131112132112133112134112135112136112137112138112139112140112141112142112143112144112145112146112147112148112149112150112151112152112153112154112155112156112157112158112159112160112161112162112163112164112165112166112167112168112169112170112171112172112173112174112175112176112177112178112179112180112181112182112183112184112185112186112187112188112189112190112191112192112193112194112195112196112197112198112199112200112201112202112203112204112205112206112207112208112209112210112211112212112213112214112215112216112217112218112219112220112221112222112223112224112225112226112227112228112229112230112231112232112233112234112235112236112237112238112239112240112241112242112243112244112245112246112247112248112249112250112251112252112253112254112255112256112257112258112259112260112261112262112263112264112265112266112267112268112269112270112271112272112273112274112275112276112277112278112279112280112281112282112283112284112285112286112287112288112289112290112291112292112293112294112295112296112297112298112299112300112301112302112303112304112305112306112307112308112309112310112311112312112313112314112315112316112317112318112319112320112321112322112323112324112325112326112327112328112329112330112331112332112333112334112335112336112337112338112339112340112341112342112343112344112345112346112347112348112349112350112351112352112353112354112355112356112357112358112359112360112361112362112363112364112365112366112367112368112369112370112371112372112373112374112375112376112377112378112379112380112381112382112383112384112385112386112387112388112389112390112391112392112393112394112395112396112397112398112399112400112401112402112403112404112405112406112407112408112409112410112411112412112413112414112415112416112417112418112419112420112421112422112423112424112425112426112427112428112429112430112431112432112433112434112435112436112437112438112439112440112441112442112443112444112445112446112447112448112449112450112451112452112453112454112455112456112457112458112459112460112461112462112463112464112465112466112467112468112469112470112471112472112473112474112475112476112477112478112479112480112481112482112483112484112485112486112487112488112489112490112491112492112493112494112495112496112497112498112499112500112501112502112503112504112505112506112507112508112509112510112511112512112513112514112515112516112517112518112519112520112521112522112523112524112525112526112527112528112529112530112531112532112533112534112535112536112537112538112539112540112541112542112543112544112545112546112547112548112549112550112551112552112553112554112555112556112557112558112559112560112561112562112563112564112565112566112567112568112569112570112571112572112573112574112575112576112577112578112579112580112581112582112583112584112585112586112587112588112589112590112591112592112593112594112595112596112597112598112599112600112601112602112603112604112605112606112607112608112609112610112611112612112613112614112615112616112617112618112619112620112621112622112623112624112625112626112627112628112629112630112631112632112633112634112635112636112637112638112639112640112641112642112643112644112645112646112647112648112649112650112651112652112653112654112655112656112657112658112659112660112661112662112663112664112665112666112667112668112669112670112671112672112673112674112675112676112677112678112679112680112681112682112683112684112685112686112687112688112689112690112691112692112693112694112695112696112697112698112699112700112701112702112703112704112705112706112707112708112709112710112711112712112713112714112715112716112717112718112719112720112721112722112723112724112725112726112727112728112729112730112731112732112733112734112735112736112737112738112739112740112741112742112743112744112745112746112747112748112749112750112751112752112753112754112755112756112757112758112759112760112761112762112763112764112765112766112767112768112769112770112771112772112773112774112775112776112777112778112779112780112781112782112783112784112785112786112787112788112789112790112791112792112793112794112795112796112797112798112799112800112801112802112803112804112805112806112807112808112809112810112811112812112813112814112815112816112817112818112819112820112821112822112823112824112825112826112827112828112829112830112831112832112833112834112835112836112837112838112839112840112841112842112843112844112845112846112847112848112849112850112851112852112853112854112855112856112857112858112859112860112861112862112863112864112865112866112867112868112869112870112871112872112873112874112875112876112877112878112879112880112881112882112883112884112885112886112887112888112889112890112891112892112893112894112895112896112897112898112899112900112901112902112903112904112905112906112907112908112909112910112911112912112913112914112915112916112917112918112919112920112921112922112923112924112925112926112927112928112929112930112931112932112933112934112935112936112937112938112939112940112941112942112943112944112945112946112947112948112949112950112951112952112953112954112955112956112957112958112959112960112961112962112963112964112965112966112967112968112969112970112971112972112973112974112975112976112977112978112979112980112981112982112983112984112985112986112987112988112989112990112991112992112993112994112995112996112997112998112999113000113001113002113003113004113005113006113007113008113009113010113011113012113013113014113015113016113017113018113019113020113021113022113023113024113025113026113027113028113029113030113031113032113033113034113035113036113037113038113039113040113041113042113043113044113045113046113047113048113049113050113051113052113053113054113055113056113057113058113059113060113061113062113063113064113065113066113067113068113069113070113071113072113073113074113075113076113077113078113079113080113081113082113083113084113085113086113087113088113089113090113091113092113093113094113095113096113097113098113099113100113101113102113103113104113105113106113107113108113109113110113111113112113113113114113115113116113117113118113119113120113121113122113123113124113125113126113127113128113129113130113131113132113133113134113135113136113137113138113139113140113141113142113143113144113145113146113147113148113149113150113151113152113153113154113155113156113157113158113159113160113161113162113163113164113165113166113167113168113169113170113171113172113173113174113175113176113177113178113179113180113181113182113183113184113185113186113187113188113189113190113191113192113193113194113195113196113197113198113199113200113201113202113203113204113205113206113207113208113209113210113211113212113213113214113215113216113217113218113219113220113221113222113223113224113225113226113227113228113229113230113231113232113233113234113235113236113237113238113239113240113241113242113243113244113245113246113247113248113249113250113251113252113253113254113255113256113257113258113259113260113261113262113263113264113265113266113267113268113269113270113271113272113273113274113275113276113277113278113279113280113281113282113283113284113285113286113287113288113289113290113291113292113293113294113295113296113297113298113299113300113301113302113303113304113305113306113307113308113309113310113311113312113313113314113315113316113317113318113319113320113321113322113323113324113325113326113327113328113329113330113331113332113333113334113335113336113337113338113339113340113341113342113343113344113345113346113347113348113349113350113351113352113353113354113355113356113357113358113359113360113361113362113363113364113365113366113367113368113369113370113371113372113373113374113375113376113377113378113379113380113381113382113383113384113385113386113387113388113389113390113391113392113393113394113395113396113397113398113399113400113401113402113403113404113405113406113407113408113409113410113411113412113413113414113415113416113417113418113419113420113421113422113423113424113425113426113427113428113429113430113431113432113433113434113435113436113437113438113439113440113441113442113443113444113445113446113447113448113449113450113451113452113453113454113455113456113457113458113459113460113461113462113463113464113465113466113467113468113469113470113471113472113473113474113475113476113477113478113479113480113481113482113483113484113485113486113487113488113489113490113491113492113493113494113495113496113497113498113499113500113501113502113503113504113505113506113507113508113509113510113511113512113513113514113515113516113517113518113519113520113521113522113523113524113525113526113527113528113529113530113531113532113533113534113535113536113537113538113539113540113541113542113543113544113545113546113547113548113549113550113551113552113553113554113555113556113557113558113559113560113561113562113563113564113565113566113567113568113569113570113571113572113573113574113575113576113577113578113579113580113581113582113583113584113585113586113587113588113589113590113591113592113593113594113595113596113597113598113599113600113601113602113603113604113605113606113607113608113609113610113611113612113613113614113615113616113617113618113619113620113621113622113623113624113625113626113627113628113629113630113631113632113633113634113635113636113637113638113639113640113641113642113643113644113645113646113647113648113649113650113651113652113653113654113655113656113657113658113659113660113661113662113663113664113665113666113667113668113669113670113671113672113673113674113675113676113677113678113679113680113681113682113683113684113685113686113687113688113689113690113691113692113693113694113695113696113697113698113699113700113701113702113703113704113705113706113707113708113709113710113711113712113713113714113715113716113717113718113719113720113721113722113723113724113725113726113727113728113729113730113731113732113733113734113735113736113737113738113739113740113741113742113743113744113745113746113747113748113749113750113751113752113753113754113755113756113757113758113759113760113761113762113763113764113765113766113767113768113769113770113771113772113773113774113775113776113777113778113779113780113781113782113783113784113785113786113787113788113789113790113791113792113793113794113795113796113797113798113799113800113801113802113803113804113805113806113807113808113809113810113811113812113813113814113815113816113817113818113819113820113821113822113823113824113825113826113827113828113829113830113831113832113833113834113835113836113837113838113839113840113841113842113843113844113845113846113847113848113849113850113851113852113853113854113855113856113857113858113859113860113861113862113863113864113865113866113867113868113869113870113871113872113873113874113875113876113877113878113879113880113881113882113883113884113885113886113887113888113889113890113891113892113893113894113895113896113897113898113899113900113901113902113903113904113905113906113907113908113909113910113911113912113913113914113915113916113917113918113919113920113921113922113923113924113925113926113927113928113929113930113931113932113933113934113935113936113937113938113939113940113941113942113943113944113945113946113947113948113949113950113951113952113953113954113955113956113957113958113959113960113961113962113963113964113965113966113967113968113969113970113971113972113973113974113975113976113977113978113979113980113981113982113983113984113985113986113987113988113989113990113991113992113993113994113995113996113997113998113999114000114001114002114003114004114005114006114007114008114009114010114011114012114013114014114015114016114017114018114019114020114021114022114023114024114025114026114027114028114029114030114031114032114033114034114035114036114037114038114039114040114041114042114043114044114045114046114047114048114049114050114051114052114053114054114055114056114057114058114059114060114061114062114063114064114065114066114067114068114069114070114071114072114073114074114075114076114077114078114079114080114081114082114083114084114085114086114087114088114089114090114091114092114093114094114095114096114097114098114099114100114101114102114103114104114105114106114107114108114109114110114111114112114113114114114115114116114117114118114119114120114121114122114123114124114125114126114127114128114129114130114131114132114133114134114135114136114137114138114139114140114141114142114143114144114145114146114147114148114149114150114151114152114153114154114155114156114157114158114159114160114161114162114163114164114165114166114167114168114169114170114171114172114173114174114175114176114177114178114179114180114181114182114183114184114185114186114187114188114189114190114191114192114193114194114195114196114197114198114199114200114201114202114203114204114205114206114207114208114209114210114211114212114213114214114215114216114217114218114219114220114221114222114223114224114225114226114227114228114229114230114231114232114233114234114235114236114237114238114239114240114241114242114243114244114245114246114247114248114249114250114251114252114253114254114255114256114257114258114259114260114261114262114263114264114265114266114267114268114269114270114271114272114273114274114275114276114277114278114279114280114281114282114283114284114285114286114287114288114289114290114291114292114293114294114295114296114297114298114299114300114301114302114303114304114305114306114307114308114309114310114311114312114313114314114315114316114317114318114319114320114321114322114323114324114325114326114327114328114329114330114331114332114333114334114335114336114337114338114339114340114341114342114343114344114345114346114347114348114349114350114351114352114353114354114355114356114357114358114359114360114361114362114363114364114365114366114367114368114369114370114371114372114373114374114375114376114377114378114379114380114381114382114383114384114385114386114387114388114389114390114391114392114393114394114395114396114397114398114399114400114401114402114403114404114405114406114407114408114409114410114411114412114413114414114415114416114417114418114419114420114421114422114423114424114425114426114427114428114429114430114431114432114433114434114435114436114437114438114439114440114441114442114443114444114445114446114447114448114449114450114451114452114453114454114455114456114457114458114459114460114461114462114463114464114465114466114467114468114469114470114471114472114473114474114475114476114477114478114479114480114481114482114483114484114485114486114487114488114489114490114491114492114493114494114495114496114497114498114499114500114501114502114503114504114505114506114507114508114509114510114511114512114513114514114515114516114517114518114519114520114521114522114523114524114525114526114527114528114529114530114531114532114533114534114535114536114537114538114539114540114541114542114543114544114545114546114547114548114549114550114551114552114553114554114555114556114557114558114559114560114561114562114563114564114565114566114567114568114569114570114571114572114573114574114575114576114577114578114579114580114581114582114583114584114585114586114587114588114589114590114591114592114593114594114595114596114597114598114599114600114601114602114603114604114605114606114607114608114609114610114611114612114613114614114615114616114617114618114619114620114621114622114623114624114625114626114627114628114629114630114631114632114633114634114635114636114637114638114639114640114641114642114643114644114645114646114647114648114649114650114651114652114653114654114655114656114657114658114659114660114661114662114663114664114665114666114667114668114669114670114671114672114673114674114675114676114677114678114679114680114681114682114683114684114685114686114687114688114689114690114691114692114693114694114695114696114697114698114699114700114701114702114703114704114705114706114707114708114709114710114711114712114713114714114715114716114717114718114719114720114721114722114723114724114725114726114727114728114729114730114731114732114733114734114735114736114737114738114739114740114741114742114743114744114745114746114747114748114749114750114751114752114753114754114755114756114757114758114759114760114761114762114763114764114765114766114767114768114769114770114771114772114773114774114775114776114777114778114779114780114781114782114783114784114785114786114787114788114789114790114791114792114793114794114795114796114797114798114799114800114801114802114803114804114805114806114807114808114809114810114811114812114813114814114815114816114817114818114819114820114821114822114823114824114825114826114827114828114829114830114831114832114833114834114835114836114837114838114839114840114841114842114843114844114845114846114847114848114849114850114851114852114853114854114855114856114857114858114859114860114861114862114863114864114865114866114867114868114869114870114871114872114873114874114875114876114877114878114879114880114881114882114883114884114885114886114887114888114889114890114891114892114893114894114895114896114897114898114899114900114901114902114903114904114905114906114907114908114909114910114911114912114913114914114915114916114917114918114919114920114921114922114923114924114925114926114927114928114929114930114931114932114933114934114935114936114937114938114939114940114941114942114943114944114945114946114947114948114949114950114951114952114953114954114955114956114957114958114959114960114961114962114963114964114965114966114967114968114969114970114971114972114973114974114975114976114977114978114979114980114981114982114983114984114985114986114987114988114989114990114991114992114993114994114995114996114997114998114999115000115001115002115003115004115005115006115007115008115009115010115011115012115013115014115015115016115017115018115019115020115021115022115023115024115025115026115027115028115029115030115031115032115033115034115035115036115037115038115039115040115041115042115043115044115045115046115047115048115049115050115051115052115053115054115055115056115057115058115059115060115061115062115063115064115065115066115067115068115069115070115071115072115073115074115075115076115077115078115079115080115081115082115083115084115085115086115087115088115089115090115091115092115093115094115095115096115097115098115099115100115101115102115103115104115105115106115107115108115109115110115111115112115113115114115115115116115117115118115119115120115121115122115123115124115125115126115127115128115129115130115131115132115133115134115135115136115137115138115139115140115141115142115143115144115145115146115147115148115149115150115151115152115153115154115155115156115157115158115159115160115161115162115163115164115165115166115167115168115169115170115171115172115173115174115175115176115177115178115179115180115181115182115183115184115185115186115187115188115189115190115191115192115193115194115195115196115197115198115199115200115201115202115203115204115205115206115207115208115209115210115211115212115213115214115215115216115217115218115219115220115221115222115223115224115225115226115227115228115229115230115231115232115233115234115235115236115237115238115239115240115241115242115243115244115245115246115247115248115249115250115251115252115253115254115255115256115257115258115259115260115261115262115263115264115265115266115267115268115269115270115271115272115273115274115275115276115277115278115279115280115281115282115283115284115285115286115287115288115289115290115291115292115293115294115295115296115297115298115299115300115301115302115303115304115305115306115307115308115309115310115311115312115313115314115315115316115317115318115319115320115321115322115323115324115325115326115327115328115329115330115331115332115333115334115335115336115337115338115339115340115341115342115343115344115345115346115347115348115349115350115351115352115353115354115355115356115357115358115359115360115361115362115363115364115365115366115367115368115369115370115371115372115373115374115375115376115377115378115379115380115381115382115383115384115385115386115387115388115389115390115391115392115393115394115395115396115397115398115399115400115401115402115403115404115405115406115407115408115409115410115411115412115413115414115415115416115417115418115419115420115421115422115423115424115425115426115427115428115429115430115431115432115433115434115435115436115437115438115439115440115441115442115443115444115445115446115447115448115449115450115451115452115453115454115455115456115457115458115459115460115461115462115463115464115465115466115467115468115469115470115471115472115473115474115475115476115477115478115479115480115481115482115483115484115485115486115487115488115489115490115491115492115493115494115495115496115497115498115499115500115501115502115503115504115505115506115507115508115509115510115511115512115513115514115515115516115517115518115519115520115521115522115523115524115525115526115527115528115529115530115531115532115533115534115535115536115537115538115539115540115541115542115543115544115545115546115547115548115549115550115551115552115553115554115555115556115557115558115559115560115561115562115563115564115565115566115567115568115569115570115571115572115573115574115575115576115577115578115579115580115581115582115583115584115585115586115587115588115589115590115591115592115593115594115595115596115597115598115599115600115601115602115603115604115605115606115607115608115609115610115611115612115613115614115615115616115617115618115619115620115621115622115623115624115625115626115627115628115629115630115631115632115633115634115635115636115637115638115639115640115641115642115643115644115645115646115647115648115649115650115651115652115653115654115655115656115657115658115659115660115661115662115663115664115665115666115667115668115669115670115671115672115673115674115675115676115677115678115679115680115681115682115683115684115685115686115687115688115689115690115691115692115693115694115695115696115697115698115699115700115701115702115703115704115705115706115707115708115709115710115711115712115713115714115715115716115717115718115719115720115721115722115723115724115725115726115727115728115729115730115731115732115733115734115735115736115737115738115739115740115741115742115743115744115745115746115747115748115749115750115751115752115753115754115755115756115757115758115759115760115761115762115763115764115765115766115767115768115769115770115771115772115773115774115775115776115777115778115779115780115781115782115783115784115785115786115787115788115789115790115791115792115793115794115795115796115797115798115799115800115801115802115803115804115805115806115807115808115809115810115811115812115813115814115815115816115817115818115819115820115821115822115823115824115825115826115827115828115829115830115831115832115833115834115835115836115837115838115839115840115841115842115843115844115845115846115847115848115849115850115851115852115853115854115855115856115857115858115859115860115861115862115863115864115865115866115867115868115869115870115871115872115873115874115875115876115877115878115879115880115881115882115883115884115885115886115887115888115889115890115891115892115893115894115895115896115897115898115899115900115901115902115903115904115905115906115907115908115909115910115911115912115913115914115915115916115917115918115919115920115921115922115923115924115925115926115927115928115929115930115931115932115933115934115935115936115937115938115939115940115941115942115943115944115945115946115947115948115949115950115951115952115953115954115955115956115957115958115959115960115961115962115963115964115965115966115967115968115969115970115971115972115973115974115975115976115977115978115979115980115981115982115983115984115985115986115987115988115989115990115991115992115993115994115995115996115997115998115999116000116001116002116003116004116005116006116007116008116009116010116011116012116013116014116015116016116017116018116019116020116021116022116023116024116025116026116027116028116029116030116031116032116033116034116035116036116037116038116039116040116041116042116043116044116045116046116047116048116049116050116051116052116053116054116055116056116057116058116059116060116061116062116063116064116065116066116067116068116069116070116071116072116073116074116075116076116077116078116079116080116081116082116083116084116085116086116087116088116089116090116091116092116093116094116095116096116097116098116099116100116101116102116103116104116105116106116107116108116109116110116111116112116113116114116115116116116117116118116119116120116121116122116123116124116125116126116127116128116129116130116131116132116133116134116135116136116137116138116139116140116141116142116143116144116145116146116147116148116149116150116151116152116153116154116155116156116157116158116159116160116161116162116163116164116165116166116167116168116169116170116171116172116173116174116175116176116177116178116179116180116181116182116183116184116185116186116187116188116189116190116191116192116193116194116195116196116197116198116199116200116201116202116203116204116205116206116207116208116209116210116211116212116213116214116215116216116217116218116219116220116221116222116223116224116225116226116227116228116229116230116231116232116233116234116235116236116237116238116239116240116241116242116243116244116245116246116247116248116249116250116251116252116253116254116255116256116257116258116259116260116261116262116263116264116265116266116267116268116269116270116271116272116273116274116275116276116277116278116279116280116281116282116283116284116285116286116287116288116289116290116291116292116293116294116295116296116297116298116299116300116301116302116303116304116305116306116307116308116309116310116311116312116313116314116315116316116317116318116319116320116321116322116323116324116325116326116327116328116329116330116331116332116333116334116335116336116337116338116339116340116341116342116343116344116345116346116347116348116349116350116351116352116353116354116355116356116357116358116359116360116361116362116363116364116365116366116367116368116369116370116371116372116373116374116375116376116377116378116379116380116381116382116383116384116385116386116387116388116389116390116391116392116393116394116395116396116397116398116399116400116401116402116403116404116405116406116407116408116409116410116411116412116413116414116415116416116417116418116419116420116421116422116423116424116425116426116427116428116429116430116431116432116433116434116435116436116437116438116439116440116441116442116443116444116445116446116447116448116449116450116451116452116453116454116455116456116457116458116459116460116461116462116463116464116465116466116467116468116469116470116471116472116473116474116475116476116477116478116479116480116481116482116483116484116485116486116487116488116489116490116491116492116493116494116495116496116497116498116499116500116501116502116503116504116505116506116507116508116509116510116511116512116513116514116515116516116517116518116519116520116521116522116523116524116525116526116527116528116529116530116531116532116533116534116535116536116537116538116539116540116541116542116543116544116545116546116547116548116549116550116551116552116553116554116555116556116557116558116559116560116561116562116563116564116565116566116567116568116569116570116571116572116573116574116575116576116577116578116579116580116581116582116583116584116585116586116587116588116589116590116591116592116593116594116595116596116597116598116599116600116601116602116603116604116605116606116607116608116609116610116611116612116613116614116615116616116617116618116619116620116621116622116623116624116625116626116627116628116629116630116631116632116633116634116635116636116637116638116639116640116641116642116643116644116645116646116647116648116649116650116651116652116653116654116655116656116657116658116659116660116661116662116663116664116665116666116667116668116669116670116671116672116673116674116675116676116677116678116679116680116681116682116683116684116685116686116687116688116689116690116691116692116693116694116695116696116697116698116699116700116701116702116703116704116705116706116707116708116709116710116711116712116713116714116715116716116717116718116719116720116721116722116723116724116725116726116727116728116729116730116731116732116733116734116735116736116737116738116739116740116741116742116743116744116745116746116747116748116749116750116751116752116753116754116755116756116757116758116759116760116761116762116763116764116765116766116767116768116769116770116771116772116773116774116775116776116777116778116779116780116781116782116783116784116785116786116787116788116789116790116791116792116793116794116795116796116797116798116799116800116801116802116803116804116805116806116807116808116809116810116811116812116813116814116815116816116817116818116819116820116821116822116823116824116825116826116827116828116829116830116831116832116833116834116835116836116837116838116839116840116841116842116843116844116845116846116847116848116849116850116851116852116853116854116855116856116857116858116859116860116861116862116863116864116865116866116867116868116869116870116871116872116873116874116875116876116877116878116879116880116881116882116883116884116885116886116887116888116889116890116891116892116893116894116895116896116897116898116899116900116901116902116903116904116905116906116907116908116909116910116911116912116913116914116915116916116917116918116919116920116921116922116923116924116925116926116927116928116929116930116931116932116933116934116935116936116937116938116939116940116941116942116943116944116945116946116947116948116949116950116951116952116953116954116955116956116957116958116959116960116961116962116963116964116965116966116967116968116969116970116971116972116973116974116975116976116977116978116979116980116981116982116983116984116985116986116987116988116989116990116991116992116993116994116995116996116997116998116999117000117001117002117003117004117005117006117007117008117009117010117011117012117013117014117015117016117017117018117019117020117021117022117023117024117025117026117027117028117029117030117031117032117033117034117035117036117037117038117039117040117041117042117043117044117045117046117047117048117049117050117051117052117053117054117055117056117057117058117059117060117061117062117063117064117065117066117067117068117069117070117071117072117073117074117075117076117077117078117079117080117081117082117083117084117085117086117087117088117089117090117091117092117093117094117095117096117097117098117099117100117101117102117103117104117105117106117107117108117109117110117111117112117113117114117115117116117117117118117119117120117121117122117123117124117125117126117127117128117129117130117131117132117133117134117135117136117137117138117139117140117141117142117143117144117145117146117147117148117149117150117151117152117153117154117155117156117157117158117159117160117161117162117163117164117165117166117167117168117169117170117171117172117173117174117175117176117177117178117179117180117181117182117183117184117185117186117187117188117189117190117191117192117193117194117195117196117197117198117199117200117201117202117203117204117205117206117207117208117209117210117211117212117213117214117215117216117217117218117219117220117221117222117223117224117225117226117227117228117229117230117231117232117233117234117235117236117237117238117239117240117241117242117243117244117245117246117247117248117249117250117251117252117253117254117255117256117257117258117259117260117261117262117263117264117265117266117267117268117269117270117271117272117273117274117275117276117277117278117279117280117281117282117283117284117285117286117287117288117289117290117291117292117293117294117295117296117297117298117299117300117301117302117303117304117305117306117307117308117309117310117311117312117313117314117315117316117317117318117319117320117321117322117323117324117325117326117327117328117329117330117331117332117333117334117335117336117337117338117339117340117341117342117343117344117345117346117347117348117349117350117351117352117353117354117355117356117357117358117359117360117361117362117363117364117365117366117367117368117369117370117371117372117373117374117375117376117377117378117379117380117381117382117383117384117385117386117387117388117389117390117391117392117393117394117395117396117397117398117399117400117401117402117403117404117405117406117407117408117409117410117411117412117413117414117415117416117417117418117419117420117421117422117423117424117425117426117427117428117429117430117431117432117433117434117435117436117437117438117439117440117441117442117443117444117445117446117447117448117449117450117451117452117453117454117455117456117457117458117459117460117461117462117463117464117465117466117467117468117469117470117471117472117473117474117475117476117477117478117479117480117481117482117483117484117485117486117487117488117489117490117491117492117493117494117495117496117497117498117499117500117501117502117503117504117505117506117507117508117509117510117511117512117513117514117515117516117517117518117519117520117521117522117523117524117525117526117527117528117529117530117531117532117533117534117535117536117537117538117539117540117541117542117543117544117545117546117547117548117549117550117551117552117553117554117555117556117557117558117559117560117561117562117563117564117565117566117567117568117569117570117571117572117573117574117575117576117577117578117579117580117581117582117583117584117585117586117587117588117589117590117591117592117593117594117595117596117597117598117599117600117601117602117603117604117605117606117607117608117609117610117611117612117613117614117615117616117617117618117619117620117621117622117623117624117625117626117627117628117629117630117631117632117633117634117635117636117637117638117639117640117641117642117643117644117645117646117647117648117649117650117651117652117653117654117655117656117657117658117659117660117661117662117663117664117665117666117667117668117669117670117671117672117673117674117675117676117677117678117679117680117681117682117683117684117685117686117687117688117689117690117691117692117693117694117695117696117697117698117699117700117701117702117703117704117705117706117707117708117709117710117711117712117713117714117715117716117717117718117719117720117721117722117723117724117725117726117727117728117729117730117731117732117733117734117735117736117737117738117739117740117741117742117743117744117745117746117747117748117749117750117751117752117753117754117755117756117757117758117759117760117761117762117763117764117765117766117767117768117769117770117771117772117773117774117775117776117777117778117779117780117781117782117783117784117785117786117787117788117789117790117791117792117793117794117795117796117797117798117799117800117801117802117803117804117805117806117807117808117809117810117811117812117813117814117815117816117817117818117819117820117821117822117823117824117825117826117827117828117829117830117831117832117833117834117835117836117837117838117839117840117841117842117843117844117845117846117847117848117849117850117851117852117853117854117855117856117857117858117859117860117861117862117863117864117865117866117867117868117869117870117871117872117873117874117875117876117877117878117879117880117881117882117883117884117885117886117887117888117889117890117891117892117893117894117895117896117897117898117899117900117901117902117903117904117905117906117907117908117909117910117911117912117913117914117915117916117917117918117919117920117921117922117923117924117925117926117927117928117929117930117931117932117933117934117935117936117937117938117939117940117941117942117943117944117945117946117947117948117949117950117951117952117953117954117955117956117957117958117959117960117961117962117963117964117965117966117967117968117969117970117971117972117973117974117975117976117977117978117979117980117981117982117983117984117985117986117987117988117989117990117991117992117993117994117995117996117997117998117999118000118001118002118003118004118005118006118007118008118009118010118011118012118013118014118015118016118017118018118019118020118021118022118023118024118025118026118027118028118029118030118031118032118033118034118035118036118037118038118039118040118041118042118043118044118045118046118047118048118049118050118051118052118053118054118055118056118057118058118059118060118061118062118063118064118065118066118067118068118069118070118071118072118073118074118075118076118077118078118079118080118081118082118083118084118085118086118087118088118089118090118091118092118093118094118095118096118097118098118099118100118101118102118103118104118105118106118107118108118109118110118111118112118113118114118115118116118117118118118119118120118121118122118123118124118125118126118127118128118129118130118131118132118133118134118135118136118137118138118139118140118141118142118143118144118145118146118147118148118149118150118151118152118153118154118155118156118157118158118159118160118161118162118163118164118165118166118167118168118169118170118171118172118173118174118175118176118177118178118179118180118181118182118183118184118185118186118187118188118189118190118191118192118193118194118195118196118197118198118199118200118201118202118203118204118205118206118207118208118209118210118211118212118213118214118215118216118217118218118219118220118221118222118223118224118225118226118227118228118229118230118231118232118233118234118235118236118237118238118239118240118241118242118243118244118245118246118247118248118249118250118251118252118253118254118255118256118257118258118259118260118261118262118263118264118265118266118267118268118269118270118271118272118273118274118275118276118277118278118279118280118281118282118283118284118285118286118287118288118289118290118291118292118293118294118295118296118297118298118299118300118301118302118303118304118305118306118307118308118309118310118311118312118313118314118315118316118317118318118319118320118321118322118323118324118325118326118327118328118329118330118331118332118333118334118335118336118337118338118339118340118341118342118343118344118345118346118347118348118349118350118351118352118353118354118355118356118357118358118359118360118361118362118363118364118365118366118367118368118369118370118371118372118373118374118375118376118377118378118379118380118381118382118383118384118385118386118387118388118389118390118391118392118393118394118395118396118397118398118399118400118401118402118403118404118405118406118407118408118409118410118411118412118413118414118415118416118417118418118419118420118421118422118423118424118425118426118427118428118429118430118431118432118433118434118435118436118437118438118439118440118441118442118443118444118445118446118447118448118449118450118451118452118453118454118455118456118457118458118459118460118461118462118463118464118465118466118467118468118469118470118471118472118473118474118475118476118477118478118479118480118481118482118483118484118485118486118487118488118489118490118491118492118493118494118495118496118497118498118499118500118501118502118503118504118505118506118507118508118509118510118511118512118513118514118515118516118517118518118519118520118521118522118523118524118525118526118527118528118529118530118531118532118533118534118535118536118537118538118539118540118541118542118543118544118545118546118547118548118549118550118551118552118553118554118555118556118557118558118559118560118561118562118563118564118565118566118567118568118569118570118571118572118573118574118575118576118577118578118579118580118581118582118583118584118585118586118587118588118589118590118591118592118593118594118595118596118597118598118599118600118601118602118603118604118605118606118607118608118609118610118611118612118613118614118615118616118617118618118619118620118621118622118623118624118625118626118627118628118629118630118631118632118633118634118635118636118637118638118639118640118641118642118643118644118645118646118647118648118649118650118651118652118653118654118655118656118657118658118659118660118661118662118663118664118665118666118667118668118669118670118671118672118673118674118675118676118677118678118679118680118681118682118683118684118685118686118687118688118689118690118691118692118693118694118695118696118697118698118699118700118701118702118703118704118705118706118707118708118709118710118711118712118713118714118715118716118717118718118719118720118721118722118723118724118725118726118727118728118729118730118731118732118733118734118735118736118737118738118739118740118741118742118743118744118745118746118747118748118749118750118751118752118753118754118755118756118757118758118759118760118761118762118763118764118765118766118767118768118769118770118771118772118773118774118775118776118777118778118779118780118781118782118783118784118785118786118787118788118789118790118791118792118793118794118795118796118797118798118799118800118801118802118803118804118805118806118807118808118809118810118811118812118813118814118815118816118817118818118819118820118821118822118823118824118825118826118827118828118829118830118831118832118833118834118835118836118837118838118839118840118841118842118843118844118845118846118847118848118849118850118851118852118853118854118855118856118857118858118859118860118861118862118863118864118865118866118867118868118869118870118871118872118873118874118875118876118877118878118879118880118881118882118883118884118885118886118887118888118889118890118891118892118893118894118895118896118897118898118899118900118901118902118903118904118905118906118907118908118909118910118911118912118913118914118915118916118917118918118919118920118921118922118923118924118925118926118927118928118929118930118931118932118933118934118935118936118937118938118939118940118941118942118943118944118945118946118947118948118949118950118951118952118953118954118955118956118957118958118959118960118961118962118963118964118965118966118967118968118969118970118971118972118973118974118975118976118977118978118979118980118981118982118983118984118985118986118987118988118989118990118991118992118993118994118995118996118997118998118999119000119001119002119003119004119005119006119007119008119009119010119011119012119013119014119015119016119017119018119019119020119021119022119023119024119025119026119027119028119029119030119031119032119033119034119035119036119037119038119039119040119041119042119043119044119045119046119047119048119049119050119051119052119053119054119055119056119057119058119059119060119061119062119063119064119065119066119067119068119069119070119071119072119073119074119075119076119077119078119079119080119081119082119083119084119085119086119087119088119089119090119091119092119093119094119095119096119097119098119099119100119101119102119103119104119105119106119107119108119109119110119111119112119113119114119115119116119117119118119119119120119121119122119123119124119125119126119127119128119129119130119131119132119133119134119135119136119137119138119139119140119141119142119143119144119145119146119147119148119149119150119151119152119153119154119155119156119157119158119159119160119161119162119163119164119165119166119167119168119169119170119171119172119173119174119175119176119177119178119179119180119181119182119183119184119185119186119187119188119189119190119191119192119193119194119195119196119197119198119199119200119201119202119203119204119205119206119207119208119209119210119211119212119213119214119215119216119217119218119219119220119221119222119223119224119225119226119227119228119229119230119231119232119233119234119235119236119237119238119239119240119241119242119243119244119245119246119247119248119249119250119251119252119253119254119255119256119257119258119259119260119261119262119263119264119265119266119267119268119269119270119271119272119273119274119275119276119277119278119279119280119281119282119283119284119285119286119287119288119289119290119291119292119293119294119295119296119297119298119299119300119301119302119303119304119305119306119307119308119309119310119311119312119313119314119315119316119317119318119319119320119321119322119323119324119325119326119327119328119329119330119331119332119333119334119335119336119337119338119339119340119341119342119343119344119345119346119347119348119349119350119351119352119353119354119355119356119357119358119359119360119361119362119363119364119365119366119367119368119369119370119371119372119373119374119375119376119377119378119379119380119381119382119383119384119385119386119387119388119389119390119391119392119393119394119395119396119397119398119399119400119401119402119403119404119405119406119407119408119409119410119411119412119413119414119415119416119417119418119419119420119421119422119423119424119425119426119427119428119429119430119431119432119433119434119435119436119437119438119439119440119441119442119443119444119445119446119447119448119449119450119451119452119453119454119455119456119457119458119459119460119461119462119463119464119465119466119467119468119469119470119471119472119473119474119475119476119477119478119479119480119481119482119483119484119485119486119487119488119489119490119491119492119493119494119495119496119497119498119499119500119501119502119503119504119505119506119507119508119509119510119511119512119513119514119515119516119517119518119519119520119521119522119523119524119525119526119527119528119529119530119531119532119533119534119535119536119537119538119539119540119541119542119543119544119545119546119547119548119549119550119551119552119553119554119555119556119557119558119559119560119561119562119563119564119565119566119567119568119569119570119571119572119573119574119575119576119577119578119579119580119581119582119583119584119585119586119587119588119589119590119591119592119593119594119595119596119597119598119599119600119601119602119603119604119605119606119607119608119609119610119611119612119613119614119615119616119617119618119619119620119621119622119623119624119625119626119627119628119629119630119631119632119633119634119635119636119637119638119639119640119641119642119643119644119645119646119647119648119649119650119651119652119653119654119655119656119657119658119659119660119661119662119663119664119665119666119667119668119669119670119671119672119673119674119675119676119677119678119679119680119681119682119683119684119685119686119687119688119689119690119691119692119693119694119695119696119697119698119699119700119701119702119703119704119705119706119707119708119709119710119711119712119713119714119715119716119717119718119719119720119721119722119723119724119725119726119727119728119729119730119731119732119733119734119735119736119737119738119739119740119741119742119743119744119745119746119747119748119749119750119751119752119753119754119755119756119757119758119759119760119761119762119763119764119765119766119767119768119769119770119771119772119773119774119775119776119777119778119779119780119781119782119783119784119785119786119787119788119789119790119791119792119793119794119795119796119797119798119799119800119801119802119803119804119805119806119807119808119809119810119811119812119813119814119815119816119817119818119819119820119821119822119823119824119825119826119827119828119829119830119831119832119833119834119835119836119837119838119839119840119841119842119843119844119845119846119847119848119849119850119851119852119853119854119855119856119857119858119859119860119861119862119863119864119865119866119867119868119869119870119871119872119873119874119875119876119877119878119879119880119881119882119883119884119885119886119887119888119889119890119891119892119893119894119895119896119897119898119899119900119901119902119903119904119905119906119907119908119909119910119911119912119913119914119915119916119917119918119919119920119921119922119923119924119925119926119927119928119929119930119931119932119933119934119935119936119937119938119939119940119941119942119943119944119945119946119947119948119949119950119951119952119953119954119955119956119957119958119959119960119961119962119963119964119965119966119967119968119969119970119971119972119973119974119975119976119977119978119979119980119981119982119983119984119985119986119987119988119989119990119991119992119993119994119995119996119997119998119999120000120001120002120003120004120005120006120007120008120009120010120011120012120013120014120015120016120017120018120019120020120021120022120023120024120025120026120027120028120029120030120031120032120033120034120035120036120037120038120039120040120041120042120043120044120045120046120047120048120049120050120051120052120053120054120055120056120057120058120059120060120061120062120063120064120065120066120067120068120069120070120071120072120073120074120075120076120077120078120079120080120081120082120083120084120085120086120087120088120089120090120091120092120093120094120095120096120097120098120099120100120101120102120103120104120105120106120107120108120109120110120111120112120113120114120115120116120117120118120119120120120121120122120123120124120125120126120127120128120129120130120131120132120133120134120135120136120137120138120139120140120141120142120143120144120145120146120147120148120149120150120151120152120153120154120155120156120157120158120159120160120161120162120163120164120165120166120167120168120169120170120171120172120173120174120175120176120177120178120179120180120181120182120183120184120185120186120187120188120189120190120191120192120193120194120195120196120197120198120199120200120201120202120203120204120205120206120207120208120209120210120211120212120213120214120215120216120217120218120219120220120221120222120223120224120225120226120227120228120229120230120231120232120233120234120235120236120237120238120239120240120241120242120243120244120245120246120247120248120249120250120251120252120253120254120255120256120257120258120259120260120261120262120263120264120265120266120267120268120269120270120271120272120273120274120275120276120277120278120279120280120281120282120283120284120285120286120287120288120289120290120291120292120293120294120295120296120297120298120299120300120301120302120303120304120305120306120307120308120309120310120311120312120313120314120315120316120317120318120319120320120321120322120323120324120325120326120327120328120329120330120331120332120333120334120335120336120337120338120339120340120341120342120343120344120345120346120347120348120349120350120351120352120353120354120355120356120357120358120359120360120361120362120363120364120365120366120367120368120369120370120371120372120373120374120375120376120377120378120379120380120381120382120383120384120385120386120387120388120389120390120391120392120393120394120395120396120397120398120399120400120401120402120403120404120405120406120407120408120409120410120411120412120413120414120415120416120417120418120419120420120421120422120423120424120425120426120427120428120429120430120431120432120433120434120435120436120437120438120439120440120441120442120443120444120445120446120447120448120449120450120451120452120453120454120455120456120457120458120459120460120461120462120463120464120465120466120467120468120469120470120471120472120473120474120475120476120477120478120479120480120481120482120483120484120485120486120487120488120489120490120491120492120493120494120495120496120497120498120499120500120501120502120503120504120505120506120507120508120509120510120511120512120513120514120515120516120517120518120519120520120521120522120523120524120525120526120527120528120529120530120531120532120533120534120535120536120537120538120539120540120541120542120543120544120545120546120547120548120549120550120551120552120553120554120555120556120557120558120559120560120561120562120563120564120565120566120567120568120569120570120571120572120573120574120575120576120577120578120579120580120581120582120583120584120585120586120587120588120589120590120591120592120593120594120595120596120597120598120599120600120601120602120603120604120605120606120607120608120609120610120611120612120613120614120615120616120617120618120619120620120621120622120623120624120625120626120627120628120629120630120631120632120633120634120635120636120637120638120639120640120641120642120643120644120645120646120647120648120649120650120651120652120653120654120655120656120657120658120659120660120661120662120663120664120665120666120667120668120669120670120671120672120673120674120675120676120677120678120679120680120681120682120683120684120685120686120687120688120689120690120691120692120693120694120695120696120697120698120699120700120701120702120703120704120705120706120707120708120709120710120711120712120713120714120715120716120717120718120719120720120721120722120723120724120725120726120727120728120729120730120731120732120733120734120735120736120737120738120739120740120741120742120743120744120745120746120747120748120749120750120751120752120753120754120755120756120757120758120759120760120761120762120763120764120765120766120767120768120769120770120771120772120773120774120775120776120777120778120779120780120781120782120783120784120785120786120787120788120789120790120791120792120793120794120795120796120797120798120799120800120801120802120803120804120805120806120807120808120809120810120811120812120813120814120815120816120817120818120819120820120821120822120823120824120825120826120827120828120829120830120831120832120833120834120835120836120837120838120839120840120841120842120843120844120845120846120847120848120849120850120851120852120853120854120855120856120857120858120859120860120861120862120863120864120865120866120867120868120869120870120871120872120873120874120875120876120877120878120879120880120881120882120883120884120885120886120887120888120889120890120891120892120893120894120895120896120897120898120899120900120901120902120903120904120905120906120907120908120909120910120911120912120913120914120915120916120917120918120919120920120921120922120923120924120925120926120927120928120929120930120931120932120933120934120935120936120937120938120939120940120941120942120943120944120945120946120947120948120949120950120951120952120953120954120955120956120957120958120959120960120961120962120963120964120965120966120967120968120969120970120971120972120973120974120975120976120977120978120979120980120981120982120983120984120985120986120987120988120989120990120991120992120993120994120995120996120997120998120999121000121001121002121003121004121005121006121007121008121009121010121011121012121013121014121015121016121017121018121019121020121021121022121023121024121025121026121027121028121029121030121031121032121033121034121035121036121037121038121039121040121041121042121043121044121045121046121047121048121049121050121051121052121053121054121055121056121057121058121059121060121061121062121063121064121065121066121067121068121069121070121071121072121073121074121075121076121077121078121079121080121081121082121083121084121085121086121087121088121089121090121091121092121093121094121095121096121097121098121099121100121101121102121103121104121105121106121107121108121109121110121111121112121113121114121115121116121117121118121119121120121121121122121123121124121125121126121127121128121129121130121131121132121133121134121135121136121137121138121139121140121141121142121143121144121145121146121147121148121149121150121151121152121153121154121155121156121157121158121159121160121161121162121163121164121165121166121167121168121169121170121171121172121173121174121175121176121177121178121179121180121181121182121183121184121185121186121187121188121189121190121191121192121193121194121195121196121197121198121199121200121201121202121203121204121205121206121207121208121209121210121211121212121213121214121215121216121217121218121219121220121221121222121223121224121225121226121227121228121229121230121231121232121233121234121235121236121237121238121239121240121241121242121243121244121245121246121247121248121249121250121251121252121253121254121255121256121257121258121259121260121261121262121263121264121265121266121267121268121269121270121271121272121273121274121275121276121277121278121279121280121281121282121283121284121285121286121287121288121289121290121291121292121293121294121295121296121297121298121299121300121301121302121303121304121305121306121307121308121309121310121311121312121313121314121315121316121317121318121319121320121321121322121323121324121325121326121327121328121329121330121331121332121333121334121335121336121337121338121339121340121341121342121343121344121345121346121347121348121349121350121351121352121353121354121355121356121357121358121359121360121361121362121363121364121365121366121367121368121369121370121371121372121373121374121375121376121377121378121379121380121381121382121383121384121385121386121387121388121389121390121391121392121393121394121395121396121397121398121399121400121401121402121403121404121405121406121407121408121409121410121411121412121413121414121415121416121417121418121419121420121421121422121423121424121425121426121427121428121429121430121431121432121433121434121435121436121437121438121439121440121441121442121443121444121445121446121447121448121449121450121451121452121453121454121455121456121457121458121459121460121461121462121463121464121465121466121467121468121469121470121471121472121473121474121475121476121477121478121479121480121481121482121483121484121485121486121487121488121489121490121491121492121493121494121495121496121497121498121499121500121501121502121503121504121505121506121507121508121509121510121511121512121513121514121515121516121517121518121519121520121521121522121523121524121525121526121527121528121529121530121531121532121533121534121535121536121537121538121539121540121541121542121543121544121545121546121547121548121549121550121551121552121553121554121555121556121557121558121559121560121561121562121563121564121565121566121567121568121569121570121571121572121573121574121575121576121577121578121579121580121581121582121583121584121585121586121587121588121589121590121591121592121593121594121595121596121597121598121599121600121601121602121603121604121605121606121607121608121609121610121611121612121613121614121615121616121617121618121619121620121621121622121623121624121625121626121627121628121629121630121631121632121633121634121635121636121637121638121639121640121641121642121643121644121645121646121647121648121649121650121651121652121653121654121655121656121657121658121659121660121661121662121663121664121665121666121667121668121669121670121671121672121673121674121675121676121677121678121679121680121681121682121683121684121685121686121687121688121689121690121691121692121693121694121695121696121697121698121699121700121701121702121703121704121705121706121707121708121709121710121711121712121713121714121715121716121717121718121719121720121721121722121723121724121725121726121727121728121729121730121731121732121733121734121735121736121737121738121739121740121741121742121743121744121745121746121747121748121749121750121751121752121753121754121755121756121757121758121759121760121761121762121763121764121765121766121767121768121769121770121771121772121773121774121775121776121777121778121779121780121781121782121783121784121785121786121787121788121789121790121791121792121793121794121795121796121797121798121799121800121801121802121803121804121805121806121807121808121809121810121811121812121813121814121815121816121817121818121819121820121821121822121823121824121825121826121827121828121829121830121831121832121833121834121835121836121837121838121839121840121841121842121843121844121845121846121847121848121849121850121851121852121853121854121855121856121857121858121859121860121861121862121863121864121865121866121867121868121869121870121871121872121873121874121875121876121877121878121879121880121881121882121883121884121885121886121887121888121889121890121891121892121893121894121895121896121897121898121899121900121901121902121903121904121905121906121907121908121909121910121911121912121913121914121915121916121917121918121919121920121921121922121923121924121925121926121927121928121929121930121931121932121933121934121935121936121937121938121939121940121941121942121943121944121945121946121947121948121949121950121951121952121953121954121955121956121957121958121959121960121961121962121963121964121965121966121967121968121969121970121971121972121973121974121975121976121977121978121979121980121981121982121983121984121985121986121987121988121989121990121991121992121993121994121995121996121997121998121999122000122001122002122003122004122005122006122007122008122009122010122011122012122013122014122015122016122017122018122019122020122021122022122023122024122025122026122027122028122029122030122031122032122033122034122035122036122037122038122039122040122041122042122043122044122045122046122047122048122049122050122051122052122053122054122055122056122057122058122059122060122061122062122063122064122065122066122067122068122069122070122071122072122073122074122075122076122077122078122079122080122081122082122083122084122085122086122087122088122089122090122091122092122093122094122095122096122097122098122099122100122101122102122103122104122105122106122107122108122109122110122111122112122113122114122115122116122117122118122119122120122121122122122123122124122125122126122127122128122129122130122131122132122133122134122135122136122137122138122139122140122141122142122143122144122145122146122147122148122149122150122151122152122153122154122155122156122157122158122159122160122161122162122163122164122165122166122167122168122169122170122171122172122173122174122175122176122177122178122179122180122181122182122183122184122185122186122187122188122189122190122191122192122193122194122195122196122197122198122199122200122201122202122203122204122205122206122207122208122209122210122211122212122213122214122215122216122217122218122219122220122221122222122223122224122225122226122227122228122229122230122231122232122233122234122235122236122237122238122239122240122241122242122243122244122245122246122247122248122249122250122251122252122253122254122255122256122257122258122259122260122261122262122263122264122265122266122267122268122269122270122271122272122273122274122275122276122277122278122279122280122281122282122283122284122285122286122287122288122289122290122291122292122293122294122295122296122297122298122299122300122301122302122303122304122305122306122307122308122309122310122311122312122313122314122315122316122317122318122319122320122321122322122323122324122325122326122327122328122329122330122331122332122333122334122335122336122337122338122339122340122341122342122343122344122345122346122347122348122349122350122351122352122353122354122355122356122357122358122359122360122361122362122363122364122365122366122367122368122369122370122371122372122373122374122375122376122377122378122379122380122381122382122383122384122385122386122387122388122389122390122391122392122393122394122395122396122397122398122399122400122401122402122403122404122405122406122407122408122409122410122411122412122413122414122415122416122417122418122419122420122421122422122423122424122425122426122427122428122429122430122431122432122433122434122435122436122437122438122439122440122441122442122443122444122445122446122447122448122449122450122451122452122453122454122455122456122457122458122459122460122461122462122463122464122465122466122467122468122469122470122471122472122473122474122475122476122477122478122479122480122481122482122483122484122485122486122487122488122489122490122491122492122493122494122495122496122497122498122499122500122501122502122503122504122505122506122507122508122509122510122511122512122513122514122515122516122517122518122519122520122521122522122523122524122525122526122527122528122529122530122531122532122533122534122535122536122537122538122539122540122541122542122543122544122545122546122547122548122549122550122551122552122553122554122555122556122557122558122559122560122561122562122563122564122565122566122567122568122569122570122571122572122573122574122575122576122577122578122579122580122581122582122583122584122585122586122587122588122589122590122591122592122593122594122595122596122597122598122599122600122601122602122603122604122605122606122607122608122609122610122611122612122613122614122615122616122617122618122619122620122621122622122623122624122625122626122627122628122629122630122631122632122633122634122635122636122637122638122639122640122641122642122643122644122645122646122647122648122649122650122651122652122653122654122655122656122657122658122659122660122661122662122663122664122665122666122667122668122669122670122671122672122673122674122675122676122677122678122679122680122681122682122683122684122685122686122687122688122689122690122691122692122693122694122695122696122697122698122699122700122701122702122703122704122705122706122707122708122709122710122711122712122713122714122715122716122717122718122719122720122721122722122723122724122725122726122727122728122729122730122731122732122733122734122735122736122737122738122739122740122741122742122743122744122745122746122747122748122749122750122751122752122753122754122755122756122757122758122759122760122761122762122763122764122765122766122767122768122769122770122771122772122773122774122775122776122777122778122779122780122781122782122783122784122785122786122787122788122789122790122791122792122793122794122795122796122797122798122799122800122801122802122803122804122805122806122807122808122809122810122811122812122813122814122815122816122817122818122819122820122821122822122823122824122825122826122827122828122829122830122831122832122833122834122835122836122837122838122839122840122841122842122843122844122845122846122847122848122849122850122851122852122853122854122855122856122857122858122859122860122861122862122863122864122865122866122867122868122869122870122871122872122873122874122875122876122877122878122879122880122881122882122883122884122885122886122887122888122889122890122891122892122893122894122895122896122897122898122899122900122901122902122903122904122905122906122907122908122909122910122911122912122913122914122915122916122917122918122919122920122921122922122923122924122925122926122927122928122929122930122931122932122933122934122935122936122937122938122939122940122941122942122943122944122945122946122947122948122949122950122951122952122953122954122955122956122957122958122959122960122961122962122963122964122965122966122967122968122969122970122971122972122973122974122975122976122977122978122979122980122981122982122983122984122985122986122987122988122989122990122991122992122993122994122995122996122997122998122999123000123001123002123003123004123005123006123007123008123009123010123011123012123013123014123015123016123017123018123019123020123021123022123023123024123025123026123027123028123029123030123031123032123033123034123035123036123037123038123039123040123041123042123043123044123045123046123047123048123049123050123051123052123053123054123055123056123057123058123059123060123061123062123063123064123065123066123067123068123069123070123071123072123073123074123075123076123077123078123079123080123081123082123083123084123085123086123087123088123089123090123091123092123093123094123095123096123097123098123099123100123101123102123103123104123105123106123107123108123109123110123111123112123113123114123115123116123117123118123119123120123121123122123123123124123125123126123127123128123129123130123131123132123133123134123135123136123137123138123139123140123141123142123143123144123145123146123147123148123149123150123151123152123153123154123155123156123157123158123159123160123161123162123163123164123165123166123167123168123169123170123171123172123173123174123175123176123177123178123179123180123181123182123183123184123185123186123187123188123189123190123191123192123193123194123195123196123197123198123199123200123201123202123203123204123205123206123207123208123209123210123211123212123213123214123215123216123217123218123219123220123221123222123223123224123225123226123227123228123229123230123231123232123233123234123235123236123237123238123239123240123241123242123243123244123245123246123247123248123249123250123251123252123253123254123255123256123257123258123259123260123261123262123263123264123265123266123267123268123269123270123271123272123273123274123275123276123277123278123279123280123281123282123283123284123285123286123287123288123289123290123291123292123293123294123295123296123297123298123299123300123301123302123303123304123305123306123307123308123309123310123311123312123313123314123315123316123317123318123319123320123321123322123323123324123325123326123327123328123329123330123331123332123333123334123335123336123337123338123339123340123341123342123343123344123345123346123347123348123349123350123351123352123353123354123355123356123357123358123359123360123361123362123363123364123365123366123367123368123369123370123371123372123373123374123375123376123377123378123379123380123381123382123383123384123385123386123387123388123389123390123391123392123393123394123395123396123397123398123399123400123401123402123403123404123405123406123407123408123409123410123411123412123413123414123415123416123417123418123419123420123421123422123423123424123425123426123427123428123429123430123431123432123433123434123435123436123437123438123439123440123441123442123443123444123445123446123447123448123449123450123451123452123453123454123455123456123457123458123459123460123461123462123463123464123465123466123467123468123469123470123471123472123473123474123475123476123477123478123479123480123481123482123483123484123485123486123487123488123489123490123491123492123493123494123495123496123497123498123499123500123501123502123503123504123505123506123507123508123509123510123511123512123513123514123515123516123517123518123519123520123521123522123523123524123525123526123527123528123529123530123531123532123533123534123535123536123537123538123539123540123541123542123543123544123545123546123547123548123549123550123551123552123553123554123555123556123557123558123559123560123561123562123563123564123565123566123567123568123569123570123571123572123573123574123575123576123577123578123579123580123581123582123583123584123585123586123587123588123589123590123591123592123593123594123595123596123597123598123599123600123601123602123603123604123605123606123607123608123609123610123611123612123613123614123615123616123617123618123619123620123621123622123623123624123625123626123627123628123629123630123631123632123633123634123635123636123637123638123639123640123641123642123643123644123645123646123647123648123649123650123651123652123653123654123655123656123657123658123659123660123661123662123663123664123665123666123667123668123669123670123671123672123673123674123675123676123677123678123679123680123681123682123683123684123685123686123687123688123689123690123691123692123693123694123695123696123697123698123699123700123701123702123703123704123705123706123707123708123709123710123711123712123713123714123715123716123717123718123719123720123721123722123723123724123725123726123727123728123729123730123731123732123733123734123735123736123737123738123739123740123741123742123743123744123745123746123747123748123749123750123751123752123753123754123755123756123757123758123759123760123761123762123763123764123765123766123767123768123769123770123771123772123773123774123775123776123777123778123779123780123781123782123783123784123785123786123787123788123789123790123791123792123793123794123795123796123797123798123799123800123801123802123803123804123805123806123807123808123809123810123811123812123813123814123815123816123817123818123819123820123821123822123823123824123825123826123827123828123829123830123831123832123833123834123835123836123837123838123839123840123841123842123843123844123845123846123847123848123849123850123851123852123853123854123855123856123857123858123859123860123861123862123863123864123865123866123867123868123869123870123871123872123873123874123875123876123877123878123879123880123881123882123883123884123885123886123887123888123889123890123891123892123893123894123895123896123897123898123899123900123901123902123903123904123905123906123907123908123909123910123911123912123913123914123915123916123917123918123919123920123921123922123923123924123925123926123927123928123929123930123931123932123933123934123935123936123937123938123939123940123941123942123943123944123945123946123947123948123949123950123951123952123953123954123955123956123957123958123959123960123961123962123963123964123965123966123967123968123969123970123971123972123973123974123975123976123977123978123979123980123981123982123983123984123985123986123987123988123989123990123991123992123993123994123995123996123997123998123999124000124001124002124003124004124005124006124007124008124009124010124011124012124013124014124015124016124017124018124019124020124021124022124023124024124025124026124027124028124029124030124031124032124033124034124035124036124037124038124039124040124041124042124043124044124045124046124047124048124049124050124051124052124053124054124055124056124057124058124059124060124061124062124063124064124065124066124067124068124069124070124071124072124073124074124075124076124077124078124079124080124081124082124083124084124085124086124087124088124089124090124091124092124093124094124095124096124097124098124099124100124101124102124103124104124105124106124107124108124109124110124111124112124113124114124115124116124117124118124119124120124121124122124123124124124125124126124127124128124129124130124131124132124133124134124135124136124137124138124139124140124141124142124143124144124145124146124147124148124149124150124151124152124153124154124155124156124157124158124159124160124161124162124163124164124165124166124167124168124169124170124171124172124173124174124175124176124177124178124179124180124181124182124183124184124185124186124187124188124189124190124191124192124193124194124195124196124197124198124199124200124201124202124203124204124205124206124207124208124209124210124211124212124213124214124215124216124217124218124219124220124221124222124223124224124225124226124227124228124229124230124231124232124233124234124235124236124237124238124239124240124241124242124243124244124245124246124247124248124249124250124251124252124253124254124255124256124257124258124259124260124261124262124263124264124265124266124267124268124269124270124271124272124273124274124275124276124277124278124279124280124281124282124283124284124285124286124287124288124289124290124291124292124293124294124295124296124297124298124299124300124301124302124303124304124305124306124307124308124309124310124311124312124313124314124315124316124317124318124319124320124321124322124323124324124325124326124327124328124329124330124331124332124333124334124335124336124337124338124339124340124341124342124343124344124345124346124347124348124349124350124351124352124353124354124355124356124357124358124359124360124361124362124363124364124365124366124367124368124369124370124371124372124373124374124375124376124377124378124379124380124381124382124383124384124385124386124387124388124389124390124391124392124393124394124395124396124397124398124399124400124401124402124403124404124405124406124407124408124409124410124411124412124413124414124415124416124417124418124419124420124421124422124423124424124425124426124427124428124429124430124431124432124433124434124435124436124437124438124439124440124441124442124443124444124445124446124447124448124449124450124451124452124453124454124455124456124457124458124459124460124461124462124463124464124465124466124467124468124469124470124471124472124473124474124475124476124477124478124479124480124481124482124483124484124485124486124487124488124489124490124491124492124493124494124495124496124497124498124499124500124501124502124503124504124505124506124507124508124509124510124511124512124513124514124515124516124517124518124519124520124521124522124523124524124525124526124527124528124529124530124531124532124533124534124535124536124537124538124539124540124541124542124543124544124545124546124547124548124549124550124551124552124553124554124555124556124557124558124559124560124561124562124563124564124565124566124567124568124569124570124571124572124573124574124575124576124577124578124579124580124581124582124583124584124585124586124587124588124589124590124591124592124593124594124595124596124597124598124599124600124601124602124603124604124605124606124607124608124609124610124611124612124613124614124615124616124617124618124619124620124621124622124623124624124625124626124627124628124629124630124631124632124633124634124635124636124637124638124639124640124641124642124643124644124645124646124647124648124649124650124651124652124653124654124655124656124657124658124659124660124661124662124663124664124665124666124667124668124669124670124671124672124673124674124675124676124677124678124679124680124681124682124683124684124685124686124687124688124689124690124691124692124693124694124695124696124697124698124699124700124701124702124703124704124705124706124707124708124709124710124711124712124713124714124715124716124717124718124719124720124721124722124723124724124725124726124727124728124729124730124731124732124733124734124735124736124737124738124739124740124741124742124743124744124745124746124747124748124749124750124751124752124753124754124755124756124757124758124759124760124761124762124763124764124765124766124767124768124769124770124771124772124773124774124775124776124777124778124779124780124781124782124783124784124785124786124787124788124789124790124791124792124793124794124795124796124797124798124799124800124801124802124803124804124805124806124807124808124809124810124811124812124813124814124815124816124817124818124819124820124821124822124823124824124825124826124827124828124829124830124831124832124833124834124835124836124837124838124839124840124841124842124843124844124845124846124847124848124849124850124851124852124853124854124855124856124857124858124859124860124861124862124863124864124865124866124867124868124869124870124871124872124873124874124875124876124877124878124879124880124881124882124883124884124885124886124887124888124889124890124891124892124893124894124895124896124897124898124899124900124901124902124903124904124905124906124907124908124909124910124911124912124913124914124915124916124917124918124919124920124921124922124923124924124925124926124927124928124929124930124931124932124933124934124935124936124937124938124939124940124941124942124943124944124945124946124947124948124949124950124951124952124953124954124955124956124957124958124959124960124961124962124963124964124965124966124967124968124969124970124971124972124973124974124975124976124977124978124979124980124981124982124983124984124985124986124987124988124989124990124991124992124993124994124995124996124997124998124999125000125001125002125003125004125005125006125007125008125009125010125011125012125013125014125015125016125017125018125019125020125021125022125023125024125025125026125027125028125029125030125031125032125033125034125035125036125037125038125039125040125041125042125043125044125045125046125047125048125049125050125051125052125053125054125055125056125057125058125059125060125061125062125063125064125065125066125067125068125069125070125071125072125073125074125075125076125077125078125079125080125081125082125083125084125085125086125087125088125089125090125091125092125093125094125095125096125097125098125099125100125101125102125103125104125105125106125107125108125109125110125111125112125113125114125115125116125117125118125119125120125121125122125123125124125125125126125127125128125129125130125131125132125133125134125135125136125137125138125139125140125141125142125143125144125145125146125147125148125149125150125151125152125153125154125155125156125157125158125159125160125161125162125163125164125165125166125167125168125169125170125171125172125173125174125175125176125177125178125179125180125181125182125183125184125185125186125187125188125189125190125191125192125193125194125195125196125197125198125199125200125201125202125203125204125205125206125207125208125209125210125211125212125213125214125215125216125217125218125219125220125221125222125223125224125225125226125227125228125229125230125231125232125233125234125235125236125237125238125239125240125241125242125243125244125245125246125247125248125249125250125251125252125253125254125255125256125257125258125259125260125261125262125263125264125265125266125267125268125269125270125271125272125273125274125275125276125277125278125279125280125281125282125283125284125285125286125287125288125289125290125291125292125293125294125295125296125297125298125299125300125301125302125303125304125305125306125307125308125309125310125311125312125313125314125315125316125317125318125319125320125321125322125323125324125325125326125327125328125329125330125331125332125333125334125335125336125337125338125339125340125341125342125343125344125345125346125347125348125349125350125351125352125353125354125355125356125357125358125359125360125361125362125363125364125365125366125367125368125369125370125371125372125373125374125375125376125377125378125379125380125381125382125383125384125385125386125387125388125389125390125391125392125393125394125395125396125397125398125399125400125401125402125403125404125405125406125407125408125409125410125411125412125413125414125415125416125417125418125419125420125421125422125423125424125425125426125427125428125429125430125431125432125433125434125435125436125437125438125439125440125441125442125443125444125445125446125447125448125449125450125451125452125453125454125455125456125457125458125459125460125461125462125463125464125465125466125467125468125469125470125471125472125473125474125475125476125477125478125479125480125481125482125483125484125485125486125487125488125489125490125491125492125493125494125495125496125497125498125499125500125501125502125503125504125505125506125507125508125509125510125511125512125513125514125515125516125517125518125519125520125521125522125523125524125525125526125527125528125529125530125531125532125533125534125535125536125537125538125539125540125541125542125543125544125545125546125547125548125549125550125551125552125553125554125555125556125557125558125559125560125561125562125563125564125565125566125567125568125569125570125571125572125573125574125575125576125577125578125579125580125581125582125583125584125585125586125587125588125589125590125591125592125593125594125595125596125597125598125599125600125601125602125603125604125605125606125607125608125609125610125611125612125613125614125615125616125617125618125619125620125621125622125623125624125625125626125627125628125629125630125631125632125633125634125635125636125637125638125639125640125641125642125643125644125645125646125647125648125649125650125651125652125653125654125655125656125657125658125659125660125661125662125663125664125665125666125667125668125669125670125671125672125673125674125675125676125677125678125679125680125681125682125683125684125685125686125687125688125689125690125691125692125693125694125695125696125697125698125699125700125701125702125703125704125705125706125707125708125709125710125711125712125713125714125715125716125717125718125719125720125721125722125723125724125725125726125727125728125729125730125731125732125733125734125735125736125737125738125739125740125741125742125743125744125745125746125747125748125749125750125751125752125753125754125755125756125757125758125759125760125761125762125763125764125765125766125767125768125769125770125771125772125773125774125775125776125777125778125779125780125781125782125783125784125785125786125787125788125789125790125791125792125793125794125795125796125797125798125799125800125801125802125803125804125805125806125807125808125809125810125811125812125813125814125815125816125817125818125819125820125821125822125823125824125825125826125827125828125829125830125831125832125833125834125835125836125837125838125839125840125841125842125843125844125845125846125847125848125849125850125851125852125853125854125855125856125857125858125859125860125861125862125863125864125865125866125867125868125869125870125871125872125873125874125875125876125877125878125879125880125881125882125883125884125885125886125887125888125889125890125891125892125893125894125895125896125897125898125899125900125901125902125903125904125905125906125907125908125909125910125911125912125913125914125915125916125917125918125919125920125921125922125923125924125925125926125927125928125929125930125931125932125933125934125935125936125937125938125939125940125941125942125943125944125945125946125947125948125949125950125951125952125953125954125955125956125957125958125959125960125961125962125963125964125965125966125967125968125969125970125971125972125973125974125975125976125977125978125979125980125981125982125983125984125985125986125987125988125989125990125991125992125993125994125995125996125997125998125999126000126001126002126003126004126005126006126007126008126009126010126011126012126013126014126015126016126017126018126019126020126021126022126023126024126025126026126027126028126029126030126031126032126033126034126035126036126037126038126039126040126041126042126043126044126045126046126047126048126049126050126051126052126053126054126055126056126057126058126059126060126061126062126063126064126065126066126067126068126069126070126071126072126073126074126075126076126077126078126079126080126081126082126083126084126085126086126087126088126089126090126091126092126093126094126095126096126097126098126099126100126101126102126103126104126105126106126107126108126109126110126111126112126113126114126115126116126117126118126119126120126121126122126123126124126125126126126127126128126129126130126131126132126133126134126135126136126137126138126139126140126141126142126143126144126145126146126147126148126149126150126151126152126153126154126155126156126157126158126159126160126161126162126163126164126165126166126167126168126169126170126171126172126173126174126175126176126177126178126179126180126181126182126183126184126185126186126187126188126189126190126191126192126193126194126195126196126197126198126199126200126201126202126203126204126205126206126207126208126209126210126211126212126213126214126215126216126217126218126219126220126221126222126223126224126225126226126227126228126229126230126231126232126233126234126235126236126237126238126239126240126241126242126243126244126245126246126247126248126249126250126251126252126253126254126255126256126257126258126259126260126261126262126263126264126265126266126267126268126269126270126271126272126273126274126275126276126277126278126279126280126281126282126283126284126285126286126287126288126289126290126291126292126293126294126295126296126297126298126299126300126301126302126303126304126305126306126307126308126309126310126311126312126313126314126315126316126317126318126319126320126321126322126323126324126325126326126327126328126329126330126331126332126333126334126335126336126337126338126339126340126341126342126343126344126345126346126347126348126349126350126351126352126353126354126355126356126357126358126359126360126361126362126363126364126365126366126367126368126369126370126371126372126373126374126375126376126377126378126379126380126381126382126383126384126385126386126387126388126389126390126391126392126393126394126395126396126397126398126399126400126401126402126403126404126405126406126407126408126409126410126411126412126413126414126415126416126417126418126419126420126421126422126423126424126425126426126427126428126429126430126431126432126433126434126435126436126437126438126439126440126441126442126443126444126445126446126447126448126449126450126451126452126453126454126455126456126457126458126459126460126461126462126463126464126465126466126467126468126469126470126471126472126473126474126475126476126477126478126479126480126481126482126483126484126485126486126487126488126489126490126491126492126493126494126495126496126497126498126499126500126501126502126503126504126505126506126507126508126509126510126511126512126513126514126515126516126517126518126519126520126521126522126523126524126525126526126527126528126529126530126531126532126533126534126535126536126537126538126539126540126541126542126543126544126545126546126547126548126549126550126551126552126553126554126555126556126557126558126559126560126561126562126563126564126565126566126567126568126569126570126571126572126573126574126575126576126577126578126579126580126581126582126583126584126585126586126587126588126589126590126591126592126593126594126595126596126597126598126599126600126601126602126603126604126605126606126607126608126609126610126611126612126613126614126615126616126617126618126619126620126621126622126623126624126625126626126627126628126629126630126631126632126633126634126635126636126637126638126639126640126641126642126643126644126645126646126647126648126649126650126651126652126653126654126655126656126657126658126659126660126661126662126663126664126665126666126667126668126669126670126671126672126673126674126675126676126677126678126679126680126681126682126683126684126685126686126687126688126689126690126691126692126693126694126695126696126697126698126699126700126701126702126703126704126705126706126707126708126709126710126711126712126713126714126715126716126717126718126719126720126721126722126723126724126725126726126727126728126729126730126731126732126733126734126735126736126737126738126739126740126741126742126743126744126745126746126747126748126749126750126751126752126753126754126755126756126757126758126759126760126761126762126763126764126765126766126767126768126769126770126771126772126773126774126775126776126777126778126779126780126781126782126783126784126785126786126787126788126789126790126791126792126793126794126795126796126797126798126799126800126801126802126803126804126805126806126807126808126809126810126811126812126813126814126815126816126817126818126819126820126821126822126823126824126825126826126827126828126829126830126831126832126833126834126835126836126837126838126839126840126841126842126843126844126845126846126847126848126849126850126851126852126853126854126855126856126857126858126859126860126861126862126863126864126865126866126867126868126869126870126871126872126873126874126875126876126877126878126879126880126881126882126883126884126885126886126887126888126889126890126891126892126893126894126895126896126897126898126899126900126901126902126903126904126905126906126907126908126909126910126911126912126913126914126915126916126917126918126919126920126921126922126923126924126925126926126927126928126929126930126931126932126933126934126935126936126937126938126939126940126941126942126943126944126945126946126947126948126949126950126951126952126953126954126955126956126957126958126959126960126961126962126963126964126965126966126967126968126969126970126971126972126973126974126975126976126977126978126979126980126981126982126983126984126985126986126987126988126989126990126991126992126993126994126995126996126997126998126999127000127001127002127003127004127005127006127007127008127009127010127011127012127013127014127015127016127017127018127019127020127021127022127023127024127025127026127027127028127029127030127031127032127033127034127035127036127037127038127039127040127041127042127043127044127045127046127047127048127049127050127051127052127053127054127055127056127057127058127059127060127061127062127063127064127065127066127067127068127069127070127071127072127073127074127075127076127077127078127079127080127081127082127083127084127085127086127087127088127089127090127091127092127093127094127095127096127097127098127099127100127101127102127103127104127105127106127107127108127109127110127111127112127113127114127115127116127117127118127119127120127121127122127123127124127125127126127127127128127129127130127131127132127133127134127135127136127137127138127139127140127141127142127143127144127145127146127147127148127149127150127151127152127153127154127155127156127157127158127159127160127161127162127163127164127165127166127167127168127169127170127171127172127173127174127175127176127177127178127179127180127181127182127183127184127185127186127187127188127189127190127191127192127193127194127195127196127197127198127199127200127201127202127203127204127205127206127207127208127209127210127211127212127213127214127215127216127217127218127219127220127221127222127223127224127225127226127227127228127229127230127231127232127233127234127235127236127237127238127239127240127241127242127243127244127245127246127247127248127249127250127251127252127253127254127255127256127257127258127259127260127261127262127263127264127265127266127267127268127269127270127271127272127273127274127275127276127277127278127279127280127281127282127283127284127285127286127287127288127289127290127291127292127293127294127295127296127297127298127299127300127301127302127303127304127305127306127307127308127309127310127311127312127313127314127315127316127317127318127319127320127321127322127323127324127325127326127327127328127329127330127331127332127333127334127335127336127337127338127339127340127341127342127343127344127345127346127347127348127349127350127351127352127353127354127355127356127357127358127359127360127361127362127363127364127365127366127367127368127369127370127371127372127373127374127375127376127377127378127379127380127381127382127383127384127385127386127387127388127389127390127391127392127393127394127395127396127397127398127399127400127401127402127403127404127405127406127407127408127409127410127411127412127413127414127415127416127417127418127419127420127421127422127423127424127425127426127427127428127429127430127431127432127433127434127435127436127437127438127439127440127441127442127443127444127445127446127447127448127449127450127451127452127453127454127455127456127457127458127459127460127461127462127463127464127465127466127467127468127469127470127471127472127473127474127475127476127477127478127479127480127481127482127483127484127485127486127487127488127489127490127491127492127493127494127495127496127497127498127499127500127501127502127503127504127505127506127507127508127509127510127511127512127513127514127515127516127517127518127519127520127521127522127523127524127525127526127527127528127529127530127531127532127533127534127535127536127537127538127539127540127541127542127543127544127545127546127547127548127549127550127551127552127553127554127555127556127557127558127559127560127561127562127563127564127565127566127567127568127569127570127571127572127573127574127575127576127577127578127579127580127581127582127583127584127585127586127587127588127589127590127591127592127593127594127595127596127597127598127599127600127601127602127603127604127605127606127607127608127609127610127611127612127613127614127615127616127617127618127619127620127621127622127623127624127625127626127627127628127629127630127631127632127633127634127635127636127637127638127639127640127641127642127643127644127645127646127647127648127649127650127651127652127653127654127655127656127657127658127659127660127661127662127663127664127665127666127667127668127669127670127671127672127673127674127675127676127677127678127679127680127681127682127683127684127685127686127687127688127689127690127691127692127693127694127695127696127697127698127699127700127701127702127703127704127705127706127707127708127709127710127711127712127713127714127715127716127717127718127719127720127721127722127723127724127725127726127727127728127729127730127731127732127733127734127735127736127737127738127739127740127741127742127743127744127745127746127747127748127749127750127751127752127753127754127755127756127757127758127759127760127761127762127763127764127765127766127767127768127769127770127771127772127773127774127775127776127777127778127779127780127781127782127783127784127785127786127787127788127789127790127791127792127793127794127795127796127797127798127799127800127801127802127803127804127805127806127807127808127809127810127811127812127813127814127815127816127817127818127819127820127821127822127823127824127825127826127827127828127829127830127831127832127833127834127835127836127837127838127839127840127841127842127843127844127845127846127847127848127849127850127851127852127853127854127855127856127857127858127859127860127861127862127863127864127865127866127867127868127869127870127871127872127873127874127875127876127877127878127879127880127881127882127883127884127885127886127887127888127889127890127891127892127893127894127895127896127897127898127899127900127901127902127903127904127905127906127907127908127909127910127911127912127913127914127915127916127917127918127919127920127921127922127923127924127925127926127927127928127929127930127931127932127933127934127935127936127937127938127939127940127941127942127943127944127945127946127947127948127949127950127951127952127953127954127955127956127957127958127959127960127961127962127963127964127965127966127967127968127969127970127971127972127973127974127975127976127977127978127979127980127981127982127983127984127985127986127987127988127989127990127991127992127993127994127995127996127997127998127999128000128001128002128003128004128005128006128007128008128009128010128011128012128013128014128015128016128017128018128019128020128021128022128023128024128025128026128027128028128029128030128031128032128033128034128035128036128037128038128039128040128041128042128043128044128045128046128047128048128049128050128051128052128053128054128055128056128057128058128059128060128061128062128063128064128065128066128067128068128069128070128071128072128073128074128075128076128077128078128079128080128081128082128083128084128085128086128087128088128089128090128091128092128093128094128095128096128097128098128099128100128101128102128103128104128105128106128107128108128109128110128111128112128113128114128115128116128117128118128119128120128121128122128123128124128125128126128127128128128129128130128131128132128133128134128135128136128137128138128139128140128141128142128143128144128145128146128147128148128149128150128151128152128153128154128155128156128157128158128159128160128161128162128163128164128165128166128167128168128169128170128171128172128173128174128175128176128177128178128179128180128181128182128183128184128185128186128187128188128189128190128191128192128193128194128195128196128197128198128199128200128201128202128203128204128205128206128207128208128209128210128211128212128213128214128215128216128217128218128219128220128221128222128223128224128225128226128227128228128229128230128231128232128233128234128235128236128237128238128239128240128241128242128243128244128245128246128247128248128249128250128251128252128253128254128255128256128257128258128259128260128261128262128263128264128265128266128267128268128269128270128271128272128273128274128275128276128277128278128279128280128281128282128283128284128285128286128287128288128289128290128291128292128293128294128295128296128297128298128299128300128301128302128303128304128305128306128307128308128309128310128311128312128313128314128315128316128317128318128319128320128321128322128323128324128325128326128327128328128329128330128331128332128333128334128335128336128337128338128339128340128341128342128343128344128345128346128347128348128349128350128351128352128353128354128355128356128357128358128359128360128361128362128363128364128365128366128367128368128369128370128371128372128373128374128375128376128377128378128379128380128381128382128383128384128385128386128387128388128389128390128391128392128393128394128395128396128397128398128399128400128401128402128403128404128405128406128407128408128409128410128411128412128413128414128415128416128417128418128419128420128421128422128423128424128425128426128427128428128429128430128431128432128433128434128435128436128437128438128439128440128441128442128443128444128445128446128447128448128449128450128451128452128453128454128455128456128457128458128459128460128461128462128463128464128465128466128467128468128469128470128471128472128473128474128475128476128477128478128479128480128481128482128483128484128485128486128487128488128489128490128491128492128493128494128495128496128497128498128499128500128501128502128503128504128505128506128507128508128509128510128511128512128513128514128515128516128517128518128519128520128521128522128523128524128525128526128527128528128529128530128531128532128533128534128535128536128537128538128539128540128541128542128543128544128545128546128547128548128549128550128551128552128553128554128555128556128557128558128559128560128561128562128563128564128565128566128567128568128569128570128571128572128573128574128575128576128577128578128579128580128581128582128583128584128585128586128587128588128589128590128591128592128593128594128595128596128597128598128599128600128601128602128603128604128605128606128607128608128609128610128611128612128613128614128615128616128617128618128619128620128621128622128623128624128625128626128627128628128629128630128631128632128633128634128635128636128637128638128639128640128641128642128643128644128645128646128647128648128649128650128651128652128653128654128655128656128657128658128659128660128661128662128663128664128665128666128667128668128669128670128671128672128673128674128675128676128677128678128679128680128681128682128683128684128685128686128687128688128689128690128691128692128693128694128695128696128697128698128699128700128701128702128703128704128705128706128707128708128709128710128711128712128713128714128715128716128717128718128719128720128721128722128723128724128725128726128727128728128729128730128731128732128733128734128735128736128737128738128739128740128741128742128743128744128745128746128747128748128749128750128751128752128753128754128755128756128757128758128759128760128761128762128763128764128765128766128767128768128769128770128771128772128773128774128775128776128777128778128779128780128781128782128783128784128785128786128787128788128789128790128791128792128793128794128795128796128797128798128799128800128801128802128803128804128805128806128807128808128809128810128811128812128813128814128815128816128817128818128819128820128821128822128823128824128825128826128827128828128829128830128831128832128833128834128835128836128837128838128839128840128841128842128843128844128845128846128847128848128849128850128851128852128853128854128855128856128857128858128859128860128861128862128863128864128865128866128867128868128869128870128871128872128873128874128875128876128877128878128879128880128881128882128883128884128885128886128887128888128889128890128891128892128893128894128895128896128897128898128899128900128901128902128903128904128905128906128907128908128909128910128911128912128913128914128915128916128917128918128919128920128921128922128923128924128925128926128927128928128929128930128931128932128933128934128935128936128937128938128939128940128941128942128943128944128945128946128947128948128949128950128951128952128953128954128955128956128957128958128959128960128961128962128963128964128965128966128967128968128969128970128971128972128973128974128975128976128977128978128979128980128981128982128983128984128985128986128987128988128989128990128991128992128993128994128995128996128997128998128999129000129001129002129003129004129005129006129007129008129009129010129011129012129013129014129015129016129017129018129019129020129021129022129023129024129025129026129027129028129029129030129031129032129033129034129035129036129037129038129039129040129041129042129043129044129045129046129047129048129049129050129051129052129053129054129055129056129057129058129059129060129061129062129063129064129065129066129067129068129069129070129071129072129073129074129075129076129077129078129079129080129081129082129083129084129085129086129087129088129089129090129091129092129093129094129095129096129097129098129099129100129101129102129103129104129105129106129107129108129109129110129111129112129113129114129115129116129117129118129119129120129121129122129123129124129125129126129127129128129129129130129131129132129133129134129135129136129137129138129139129140129141129142129143129144129145129146129147129148129149129150129151129152129153129154129155129156129157129158129159129160129161129162129163129164129165129166129167129168129169129170129171129172129173129174129175129176129177129178129179129180129181129182129183129184129185129186129187129188129189129190129191129192129193129194129195129196129197129198129199129200129201129202129203129204129205129206129207129208129209129210129211129212129213129214129215129216129217129218129219129220129221129222129223129224129225129226129227129228129229129230129231129232129233129234129235129236129237129238129239129240129241129242129243129244129245129246129247129248129249129250129251129252129253129254129255129256129257129258129259129260129261129262129263129264129265129266129267129268129269129270129271129272129273129274129275129276129277129278129279129280129281129282129283129284129285129286129287129288129289129290129291129292129293129294129295129296129297129298129299129300129301129302129303129304129305129306129307129308129309129310129311129312129313129314129315129316129317129318129319129320129321129322129323129324129325129326129327129328129329129330129331129332129333129334129335129336129337129338129339129340129341129342129343129344129345129346129347129348129349129350129351129352129353129354129355129356129357129358129359129360129361129362129363129364129365129366129367129368129369129370129371129372129373129374129375129376129377129378129379129380129381129382129383129384129385129386129387129388129389129390129391129392129393129394129395129396129397129398129399129400129401129402129403129404129405129406129407129408129409129410129411129412129413129414129415129416129417129418129419129420129421129422129423129424129425129426129427129428129429129430129431129432129433129434129435129436129437129438129439129440129441129442129443129444129445129446129447129448129449129450129451129452129453129454129455129456129457129458129459129460129461129462129463129464129465129466129467129468129469129470129471129472129473129474129475129476129477129478129479129480129481129482129483129484129485129486129487129488129489129490129491129492129493129494129495129496129497129498129499129500129501129502129503129504129505129506129507129508129509129510129511129512129513129514129515129516129517129518129519129520129521129522129523129524129525129526129527129528129529129530129531129532129533129534129535129536129537129538129539129540129541129542129543129544129545129546129547129548129549129550129551129552129553129554129555129556129557129558129559129560129561129562129563129564129565129566129567129568129569129570129571129572129573129574129575129576129577129578129579129580129581129582129583129584129585129586129587129588129589129590129591129592129593129594129595129596129597129598129599129600129601129602129603129604129605129606129607129608129609129610129611129612129613129614129615129616129617129618129619129620129621129622129623129624129625129626129627129628129629129630129631129632129633129634129635129636129637129638129639129640129641129642129643129644129645129646129647129648129649129650129651129652129653129654129655129656129657129658129659129660129661129662129663129664129665129666129667129668129669129670129671129672129673129674129675129676129677129678129679129680129681129682129683129684129685129686129687129688129689129690129691129692129693129694129695129696129697129698129699129700129701129702129703129704129705129706129707129708129709129710129711129712129713129714129715129716129717129718129719129720129721129722129723129724129725129726129727129728129729129730129731129732129733129734129735129736129737129738129739129740129741129742129743129744129745129746129747129748129749129750129751129752129753129754129755129756129757129758129759129760129761129762129763129764129765129766129767129768129769129770129771129772129773129774129775129776129777129778129779129780129781129782129783129784129785129786129787129788129789129790129791129792129793129794129795129796129797129798129799129800129801129802129803129804129805129806129807129808129809129810129811129812129813129814129815129816129817129818129819129820129821129822129823129824129825129826129827129828129829129830129831129832129833129834129835129836129837129838129839129840129841129842129843129844129845129846129847129848129849129850129851129852129853129854129855129856129857129858129859129860129861129862129863129864129865129866129867129868129869129870129871129872129873129874129875129876129877129878129879129880129881129882129883129884129885129886129887129888129889129890129891129892129893129894129895129896129897129898129899129900129901129902129903129904129905129906129907129908129909129910129911129912129913129914129915129916129917129918129919129920129921129922129923129924129925129926129927129928129929129930129931129932129933129934129935129936129937129938129939129940129941129942129943129944129945129946129947129948129949129950129951129952129953129954129955129956129957129958129959129960129961129962129963129964129965129966129967129968129969129970129971129972129973129974129975129976129977129978129979129980129981129982129983129984129985129986129987129988129989129990129991129992129993129994129995129996129997129998129999130000130001130002130003130004130005130006130007130008130009130010130011130012130013130014130015130016130017130018130019130020130021130022130023130024130025130026130027130028130029130030130031130032130033130034130035130036130037130038130039130040130041130042130043130044130045130046130047130048130049130050130051130052130053130054130055130056130057130058130059130060130061130062130063130064130065130066130067130068130069130070130071130072130073130074130075130076130077130078130079130080130081130082130083130084130085130086130087130088130089130090130091130092130093130094130095130096130097130098130099130100130101130102130103130104130105130106130107130108130109130110130111130112130113130114130115130116130117130118130119130120130121130122130123130124130125130126130127130128130129130130130131130132130133130134130135130136130137130138130139130140130141130142130143130144130145130146130147130148130149130150130151130152130153130154130155130156130157130158130159130160130161130162130163130164130165130166130167130168130169130170130171130172130173130174130175130176130177130178130179130180130181130182130183130184130185130186130187130188130189130190130191130192130193130194130195130196130197130198130199130200130201130202130203130204130205130206130207130208130209130210130211130212130213130214130215130216130217130218130219130220130221130222130223130224130225130226130227130228130229130230130231130232130233130234130235130236130237130238130239130240130241130242130243130244130245130246130247130248130249130250130251130252130253130254130255130256130257130258130259130260130261130262130263130264130265130266130267130268130269130270130271130272130273130274130275130276130277130278130279130280130281130282130283130284130285130286130287130288130289130290130291130292130293130294130295130296130297130298130299130300130301130302130303130304130305130306130307130308130309130310130311130312130313130314130315130316130317130318130319130320130321130322130323130324130325130326130327130328130329130330130331130332130333130334130335130336130337130338130339130340130341130342130343130344130345130346130347130348130349130350130351130352130353130354130355130356130357130358130359130360130361130362130363130364130365130366130367130368130369130370130371130372130373130374130375130376130377130378130379130380130381130382130383130384130385130386130387130388130389130390130391130392130393130394130395130396130397130398130399130400130401130402130403130404130405130406130407130408130409130410130411130412130413130414130415130416130417130418130419130420130421130422130423130424130425130426130427130428130429130430130431130432130433130434130435130436130437130438130439130440130441130442130443130444130445130446130447130448130449130450130451130452130453130454130455130456130457130458130459130460130461130462130463130464130465130466130467130468130469130470130471130472130473130474130475130476130477130478130479130480130481130482130483130484130485130486130487130488130489130490130491130492130493130494130495130496130497130498130499130500130501130502130503130504130505130506130507130508130509130510130511130512130513130514130515130516130517130518130519130520130521130522130523130524130525130526130527130528130529130530130531130532130533130534130535130536130537130538130539130540130541130542130543130544130545130546130547130548130549130550130551130552130553130554130555130556130557130558130559130560130561130562130563130564130565130566130567130568130569130570130571130572130573130574130575130576130577130578130579130580130581130582130583130584130585130586130587130588130589130590130591130592130593130594130595130596130597130598130599130600130601130602130603130604130605130606130607130608130609130610130611130612130613130614130615130616130617130618130619130620130621130622130623130624130625130626130627130628130629130630130631130632130633130634130635130636130637130638130639130640130641130642130643130644130645130646130647130648130649130650130651130652130653130654130655130656130657130658130659130660130661130662130663130664130665130666130667130668130669130670130671130672130673130674130675130676130677130678130679130680130681130682130683130684130685130686130687130688130689130690130691130692130693130694130695130696130697130698130699130700130701130702130703130704130705130706130707130708130709130710130711130712130713130714130715130716130717130718130719130720130721130722130723130724130725130726130727130728130729130730130731130732130733130734130735130736130737130738130739130740130741130742130743130744130745130746130747130748130749130750130751130752130753130754130755130756130757130758130759130760130761130762130763130764130765130766130767130768130769130770130771130772130773130774130775130776130777130778130779130780130781130782130783130784130785130786130787130788130789130790130791130792130793130794130795130796130797130798130799130800130801130802130803130804130805130806130807130808130809130810130811130812130813130814130815130816130817130818130819130820130821130822130823130824130825130826130827130828130829130830130831130832130833130834130835130836130837130838130839130840130841130842130843130844130845130846130847130848130849130850130851130852130853130854130855130856130857130858130859130860130861130862130863130864130865130866130867130868130869130870130871130872130873130874130875130876130877130878130879130880130881130882130883130884130885130886130887130888130889130890130891130892130893130894130895130896130897130898130899130900130901130902130903130904130905130906130907130908130909130910130911130912130913130914130915130916130917130918130919130920130921130922130923130924130925130926130927130928130929130930130931130932130933130934130935130936130937130938130939130940130941130942130943130944130945130946130947130948130949130950130951130952130953130954130955130956130957130958130959130960130961130962130963130964130965130966130967130968130969130970130971130972130973130974130975130976130977130978130979130980130981130982130983130984130985130986130987130988130989130990130991130992130993130994130995130996130997130998130999131000131001131002131003131004131005131006131007131008131009131010131011131012131013131014131015131016131017131018131019131020131021131022131023131024131025131026131027131028131029131030131031131032131033131034131035131036131037131038131039131040131041131042131043131044131045131046131047131048131049131050131051131052131053131054131055131056131057131058131059131060131061131062131063131064131065131066131067131068131069131070131071131072131073131074131075131076131077131078131079131080131081131082131083131084131085131086131087131088131089131090131091131092131093131094131095131096131097131098131099131100131101131102131103131104131105131106131107131108131109131110131111131112131113131114131115131116131117131118131119131120131121131122131123131124131125131126131127131128131129131130131131131132131133131134131135131136131137131138131139131140131141131142131143131144131145131146131147131148131149131150131151131152131153131154131155131156131157131158131159131160131161131162131163131164131165131166131167131168131169131170131171131172131173131174131175131176131177131178131179131180131181131182131183131184131185131186131187131188131189131190131191131192131193131194131195131196131197131198131199131200131201131202131203131204131205131206131207131208131209131210131211131212131213131214131215131216131217131218131219131220131221131222131223131224131225131226131227131228131229131230131231131232131233131234131235131236131237131238131239131240131241131242131243131244131245131246131247131248131249131250131251131252131253131254131255131256131257131258131259131260131261131262131263131264131265131266131267131268131269131270131271131272131273131274131275131276131277131278131279131280131281131282131283131284131285131286131287131288131289131290131291131292131293131294131295131296131297131298131299131300131301131302131303131304131305131306131307131308131309131310131311131312131313131314131315131316131317131318131319131320131321131322131323131324131325131326131327131328131329131330131331131332131333131334131335131336131337131338131339131340131341131342131343131344131345131346131347131348131349131350131351131352131353131354131355131356131357131358131359131360131361131362131363131364131365131366131367131368131369131370131371131372131373131374131375131376131377131378131379131380131381131382131383131384131385131386131387131388131389131390131391131392131393131394131395131396131397131398131399131400131401131402131403131404131405131406131407131408131409131410131411131412131413131414131415131416131417131418131419131420131421131422131423131424131425131426131427131428131429131430131431131432131433131434131435131436131437131438131439131440131441131442131443131444131445131446131447131448131449131450131451131452131453131454131455131456131457131458131459131460131461131462131463131464131465131466131467131468131469131470131471131472131473131474131475131476131477131478131479131480131481131482131483131484131485131486131487131488131489131490131491131492131493131494131495131496131497131498131499131500131501131502131503131504131505131506131507131508131509131510131511131512131513131514131515131516131517131518131519131520131521131522131523131524131525131526131527131528131529131530131531131532131533131534131535131536131537131538131539131540131541131542131543131544131545131546131547131548131549131550131551131552131553131554131555131556131557131558131559131560131561131562131563131564131565131566131567131568131569131570131571131572131573131574131575131576131577131578131579131580131581131582131583131584131585131586131587131588131589131590131591131592131593131594131595131596131597131598131599131600131601131602131603131604131605131606131607131608131609131610131611131612131613131614131615131616131617131618131619131620131621131622131623131624131625131626131627131628131629131630131631131632131633131634131635131636131637131638131639131640131641131642131643131644131645131646131647131648131649131650131651131652131653131654131655131656131657131658131659131660131661131662131663131664131665131666131667131668131669131670131671131672131673131674131675131676131677131678131679131680131681131682131683131684131685131686131687131688131689131690131691131692131693131694131695131696131697131698131699131700131701131702131703131704131705131706131707131708131709131710131711131712131713131714131715131716131717131718131719131720131721131722131723131724131725131726131727131728131729131730131731131732131733131734131735131736131737131738131739131740131741131742131743131744131745131746131747131748131749131750131751131752131753131754131755131756131757131758131759131760131761131762131763131764131765131766131767131768131769131770131771131772131773131774131775131776131777131778131779131780131781131782131783131784131785131786131787131788131789131790131791131792131793131794131795131796131797131798131799131800131801131802131803131804131805131806131807131808131809131810131811131812131813131814131815131816131817131818131819131820131821131822131823131824131825131826131827131828131829131830131831131832131833131834131835131836131837131838131839131840131841131842131843131844131845131846131847131848131849131850131851131852131853131854131855131856131857131858131859131860131861131862131863131864131865131866131867131868131869131870131871131872131873131874131875131876131877131878131879131880131881131882131883131884131885131886131887131888131889131890131891131892131893131894131895131896131897131898131899131900131901131902131903131904131905131906131907131908131909131910131911131912131913131914131915131916131917131918131919131920131921131922131923131924131925131926131927131928131929131930131931131932131933131934131935131936131937131938131939131940131941131942131943131944131945131946131947131948131949131950131951131952131953131954131955131956131957131958131959131960131961131962131963131964131965131966131967131968131969131970131971131972131973131974131975131976131977131978131979131980131981131982131983131984131985131986131987131988131989131990131991131992131993131994131995131996131997131998131999132000132001132002132003132004132005132006132007132008132009132010132011132012132013132014132015132016132017132018132019132020132021132022132023132024132025132026132027132028132029132030132031132032132033132034132035132036132037132038132039132040132041132042132043132044132045132046132047132048132049132050132051132052132053132054132055132056132057132058132059132060132061132062132063132064132065132066132067132068132069132070132071132072132073132074132075132076132077132078132079132080132081132082132083132084132085132086132087132088132089132090132091132092132093132094132095132096132097132098132099132100132101132102132103132104132105132106132107132108132109132110132111132112132113132114132115132116132117132118132119132120132121132122132123132124132125132126132127132128132129132130132131132132132133132134132135132136132137132138132139132140132141132142132143132144132145132146132147132148132149132150132151132152132153132154132155132156132157132158132159132160132161132162132163132164132165132166132167132168132169132170132171132172132173132174132175132176132177132178132179132180132181132182132183132184132185132186132187132188132189132190132191132192132193132194132195132196132197132198132199132200132201132202132203132204132205132206132207132208132209132210132211132212132213132214132215132216132217132218132219132220132221132222132223132224132225132226132227132228132229132230132231132232132233132234132235132236132237132238132239132240132241132242132243132244132245132246132247132248132249132250132251132252132253132254132255132256132257132258132259132260132261132262132263132264132265132266132267132268132269132270132271132272132273132274132275132276132277132278132279132280132281132282132283132284132285132286132287132288132289132290132291132292132293132294132295132296132297132298132299132300132301132302132303132304132305132306132307132308132309132310132311132312132313132314132315132316132317132318132319132320132321132322132323132324132325132326132327132328132329132330132331132332132333132334132335132336132337132338132339132340132341132342132343132344132345132346132347132348132349132350132351132352132353132354132355132356132357132358132359132360132361132362132363132364132365132366132367132368132369132370132371132372132373132374132375132376132377132378132379132380132381132382132383132384132385132386132387132388132389132390132391132392132393132394132395132396132397132398132399132400132401132402132403132404132405132406132407132408132409132410132411132412132413132414132415132416132417132418132419132420132421132422132423132424132425132426132427132428132429132430132431132432132433132434132435132436132437132438132439132440132441132442132443132444132445132446132447132448132449132450132451132452132453132454132455132456132457132458132459132460132461132462132463132464132465132466132467132468132469132470132471132472132473132474132475132476132477132478132479132480132481132482132483132484132485132486132487132488132489132490132491132492132493132494132495132496132497132498132499132500132501132502132503132504132505132506132507132508132509132510132511132512132513132514132515132516132517132518132519132520132521132522132523132524132525132526132527132528132529132530132531132532132533132534132535132536132537132538132539132540132541132542132543132544132545132546132547132548132549132550132551132552132553132554132555132556132557132558132559132560132561132562132563132564132565132566132567132568132569132570132571132572132573132574132575132576132577132578132579132580132581132582132583132584132585132586132587132588132589132590132591132592132593132594132595132596132597132598132599132600132601132602132603132604132605132606132607132608132609132610132611132612132613132614132615132616132617132618132619132620132621132622132623132624132625132626132627132628132629132630132631132632132633132634132635132636132637132638132639132640132641132642132643132644132645132646132647132648132649132650132651132652132653132654132655132656132657132658132659132660132661132662132663132664132665132666132667132668132669132670132671132672132673132674132675132676132677132678132679132680132681132682132683132684132685132686132687132688132689132690132691132692132693132694132695132696132697132698132699132700132701132702132703132704132705132706132707132708132709132710132711132712132713132714132715132716132717132718132719132720132721132722132723132724132725132726132727132728132729132730132731132732132733132734132735132736132737132738132739132740132741132742132743132744132745132746132747132748132749132750132751132752132753132754132755132756132757132758132759132760132761132762132763132764132765132766132767132768132769132770132771132772132773132774132775132776132777132778132779132780132781132782132783132784132785132786132787132788132789132790132791132792132793132794132795132796132797132798132799132800132801132802132803132804132805132806132807132808132809132810132811132812132813132814132815132816132817132818132819132820132821132822132823132824132825132826132827132828132829132830132831132832132833132834132835132836132837132838132839132840132841132842132843132844132845132846132847132848132849132850132851132852132853132854132855132856132857132858132859132860132861132862132863132864132865132866132867132868132869132870132871132872132873132874132875132876132877132878132879132880132881132882132883132884132885132886132887132888132889132890132891132892132893132894132895132896132897132898132899132900132901132902132903132904132905132906132907132908132909132910132911132912132913132914132915132916132917132918132919132920132921132922132923132924132925132926132927132928132929132930132931132932132933132934132935132936132937132938132939132940132941132942132943132944132945132946132947132948132949132950132951132952132953132954132955132956132957132958132959132960132961132962132963132964132965132966132967132968132969132970132971132972132973132974132975132976132977132978132979132980132981132982132983132984132985132986132987132988132989132990132991132992132993132994132995132996132997132998132999133000133001133002133003133004133005133006133007133008133009133010133011133012133013133014133015133016133017133018133019133020133021133022133023133024133025133026133027133028133029133030133031133032133033133034133035133036133037133038133039133040133041133042133043133044133045133046133047133048133049133050133051133052133053133054133055133056133057133058133059133060133061133062133063133064133065133066133067133068133069133070133071133072133073133074133075133076133077133078133079133080133081133082133083133084133085133086133087133088133089133090133091133092133093133094133095133096133097133098133099133100133101133102133103133104133105133106133107133108133109133110133111133112133113133114133115133116133117133118133119133120133121133122133123133124133125133126133127133128133129133130133131133132133133133134133135133136133137133138133139133140133141133142133143133144133145133146133147133148133149133150133151133152133153133154133155133156133157133158133159133160133161133162133163133164133165133166133167133168133169133170133171133172133173133174133175133176133177133178133179133180133181133182133183133184133185133186133187133188133189133190133191133192133193133194133195133196133197133198133199133200133201133202133203133204133205133206133207133208133209133210133211133212133213133214133215133216133217133218133219133220133221133222133223133224133225133226133227133228133229133230133231133232133233133234133235133236133237133238133239133240133241133242133243133244133245133246133247133248133249133250133251133252133253133254133255133256133257133258133259133260133261133262133263133264133265133266133267133268133269133270133271133272133273133274133275133276133277133278133279133280133281133282133283133284133285133286133287133288133289133290133291133292133293133294133295133296133297133298133299133300133301133302133303133304133305133306133307133308133309133310133311133312133313133314133315133316133317133318133319133320133321133322133323133324133325133326133327133328133329133330133331133332133333133334133335133336133337133338133339133340133341133342133343133344133345133346133347133348133349133350133351133352133353133354133355133356133357133358133359133360133361133362133363133364133365133366133367133368133369133370133371133372133373133374133375133376133377133378133379133380133381133382133383133384133385133386133387133388133389133390133391133392133393133394133395133396133397133398133399133400133401133402133403133404133405133406133407133408133409133410133411133412133413133414133415133416133417133418133419133420133421133422133423133424133425133426133427133428133429133430133431133432133433133434133435133436133437133438133439133440133441133442133443133444133445133446133447133448133449133450133451133452133453133454133455133456133457133458133459133460133461133462133463133464133465133466133467133468133469133470133471133472133473133474133475133476133477133478133479133480133481133482133483133484133485133486133487133488133489133490133491133492133493133494133495133496133497133498133499133500133501133502133503133504133505133506133507133508133509133510133511133512133513133514133515133516133517133518133519133520133521133522133523133524133525133526133527133528133529133530133531133532133533133534133535133536133537133538133539133540133541133542133543133544133545133546133547133548133549133550133551133552133553133554133555133556133557133558133559133560133561133562133563133564133565133566133567133568133569133570133571133572133573133574133575133576133577133578133579133580133581133582133583133584133585133586133587133588133589133590133591133592133593133594133595133596133597133598133599133600133601133602133603133604133605133606133607133608133609133610133611133612133613133614133615133616133617133618133619133620133621133622133623133624133625133626133627133628133629133630133631133632133633133634133635133636133637133638133639133640133641133642133643133644133645133646133647133648133649133650133651133652133653133654133655133656133657133658133659133660133661133662133663133664133665133666133667133668133669133670133671133672133673133674133675133676133677133678133679133680133681133682133683133684133685133686133687133688133689133690133691133692133693133694133695133696133697133698133699133700133701133702133703133704133705133706133707133708133709133710133711133712133713133714133715133716133717133718133719133720133721133722133723133724133725133726133727133728133729133730133731133732133733133734133735133736133737133738133739133740133741133742133743133744133745133746133747133748133749133750133751133752133753133754133755133756133757133758133759133760133761133762133763133764133765133766133767133768133769133770133771133772133773133774133775133776133777133778133779133780133781133782133783133784133785133786133787133788133789133790133791133792133793133794133795133796133797133798133799133800133801133802133803133804133805133806133807133808133809133810133811133812133813133814133815133816133817133818133819133820133821133822133823133824133825133826133827133828133829133830133831133832133833133834133835133836133837133838133839133840133841133842133843133844133845133846133847133848133849133850133851133852133853133854133855133856133857133858133859133860133861133862133863133864133865133866133867133868133869133870133871133872133873133874133875133876133877133878133879133880133881133882133883133884133885133886133887133888133889133890133891133892133893133894133895133896133897133898133899133900133901133902133903133904133905133906133907133908133909133910133911133912133913133914133915133916133917133918133919133920133921133922133923133924133925133926133927133928133929133930133931133932133933133934133935133936133937133938133939133940133941133942133943133944133945133946133947133948133949133950133951133952133953133954133955133956133957133958133959133960133961133962133963133964133965133966133967133968133969133970133971133972133973133974133975133976133977133978133979133980133981133982133983133984133985133986133987133988133989133990133991133992133993133994133995133996133997133998133999134000134001134002134003134004134005134006134007134008134009134010134011134012134013134014134015134016134017134018134019134020134021134022134023134024134025134026134027134028134029134030134031134032134033134034134035134036134037134038134039134040134041134042134043134044134045134046134047134048134049134050134051134052134053134054134055134056134057134058134059134060134061134062134063134064134065134066134067134068134069134070134071134072134073134074134075134076134077134078134079134080134081134082134083134084134085134086134087134088134089134090134091134092134093134094134095134096134097134098134099134100134101134102134103134104134105134106134107134108134109134110134111134112134113134114134115134116134117134118134119134120134121134122134123134124134125134126134127134128134129134130134131134132134133134134134135134136134137134138134139134140134141134142134143134144134145134146134147134148134149134150134151134152134153134154134155134156134157134158134159134160134161134162134163134164134165134166134167134168134169134170134171134172134173134174134175134176134177134178134179134180134181134182134183134184134185134186134187134188134189134190134191134192134193134194134195134196134197134198134199134200134201134202134203134204134205134206134207134208134209134210134211134212134213134214134215134216134217134218134219134220134221134222134223134224134225134226134227134228134229134230134231134232134233134234134235134236134237134238134239134240134241134242134243134244134245134246134247134248134249134250134251134252134253134254134255134256134257134258134259134260134261134262134263134264134265134266134267134268134269134270134271134272134273134274134275134276134277134278134279134280134281134282134283134284134285134286134287134288134289134290134291134292134293134294134295134296134297134298134299134300134301134302134303134304134305134306134307134308134309134310134311134312134313134314134315134316134317134318134319134320134321134322134323134324134325134326134327134328134329134330134331134332134333134334134335134336134337134338134339134340134341134342134343134344134345134346134347134348134349134350134351134352134353134354134355134356134357134358134359134360134361134362134363134364134365134366134367134368134369134370134371134372134373134374134375134376134377134378134379134380134381134382134383134384134385134386134387134388134389134390134391134392134393134394134395134396134397134398134399134400134401134402134403134404134405134406134407134408134409134410134411134412134413134414134415134416134417134418134419134420134421134422134423134424134425134426134427134428134429134430134431134432134433134434134435134436134437134438134439134440134441134442134443134444134445134446134447134448134449134450134451134452134453134454134455134456134457134458134459134460134461134462134463134464134465134466134467134468134469134470134471134472134473134474134475134476134477134478134479134480134481134482134483134484134485134486134487134488134489134490134491134492134493134494134495134496134497134498134499134500134501134502134503134504134505134506134507134508134509134510134511134512134513134514134515134516134517134518134519134520134521134522134523134524134525134526134527134528134529134530134531134532134533134534134535134536134537134538134539134540134541134542134543134544134545134546134547134548134549134550134551134552134553134554134555134556134557134558134559134560134561134562134563134564134565134566134567134568134569134570134571134572134573134574134575134576134577134578134579134580134581134582134583134584134585134586134587134588134589134590134591134592134593134594134595134596134597134598134599134600134601134602134603134604134605134606134607134608134609134610134611134612134613134614134615134616134617134618134619134620134621134622134623134624134625134626134627134628134629134630134631134632134633134634134635134636134637134638134639134640134641134642134643134644134645134646134647134648134649134650134651134652134653134654134655134656134657134658134659134660134661134662134663134664134665134666134667134668134669134670134671134672134673134674134675134676134677134678134679134680134681134682134683134684134685134686134687134688134689134690134691134692134693134694134695134696134697134698134699134700134701134702134703134704134705134706134707134708134709134710134711134712134713134714134715134716134717134718134719134720134721134722134723134724134725134726134727134728134729134730134731134732134733134734134735134736134737134738134739134740134741134742134743134744134745134746134747134748134749134750134751134752134753134754134755134756134757134758134759134760134761134762134763134764134765134766134767134768134769134770134771134772134773134774134775134776134777134778134779134780134781134782134783134784134785134786134787134788134789134790134791134792134793134794134795134796134797134798134799134800134801134802134803134804134805134806134807134808134809134810134811134812134813134814134815134816134817134818134819134820134821134822134823134824134825134826134827134828134829134830134831134832134833134834134835134836134837134838134839134840134841134842134843134844134845134846134847134848134849134850134851134852134853134854134855134856134857134858134859134860134861134862134863134864134865134866134867134868134869134870134871134872134873134874134875134876134877134878134879134880134881134882134883134884134885134886134887134888134889134890134891134892134893134894134895134896134897134898134899134900134901134902134903134904134905134906134907134908134909134910134911134912134913134914134915134916134917134918134919134920134921134922134923134924134925134926134927134928134929134930134931134932134933134934134935134936134937134938134939134940134941134942134943134944134945134946134947134948134949134950134951134952134953134954134955134956134957134958134959134960134961134962134963134964134965134966134967134968134969134970134971134972134973134974134975134976134977134978134979134980134981134982134983134984134985134986134987134988134989134990134991134992134993134994134995134996134997134998134999135000135001135002135003135004135005135006135007135008135009135010135011135012135013135014135015135016135017135018135019135020135021135022135023135024135025135026135027135028135029135030135031135032135033135034135035135036135037135038135039135040135041135042135043135044135045135046135047135048135049135050135051135052135053135054135055135056135057135058135059135060135061135062135063135064135065135066135067135068135069135070135071135072135073135074135075135076135077135078135079135080135081135082135083135084135085135086135087135088135089135090135091135092135093135094135095135096135097135098135099135100135101135102135103135104135105135106135107135108135109135110135111135112135113135114135115135116135117135118135119135120135121135122135123135124135125135126135127135128135129135130135131135132135133135134135135135136135137135138135139135140135141135142135143135144135145135146135147135148135149135150135151135152135153135154135155135156135157135158135159135160135161135162135163135164135165135166135167135168135169135170135171135172135173135174135175135176135177135178135179135180135181135182135183135184135185135186135187135188135189135190135191135192135193135194135195135196135197135198135199135200135201135202135203135204135205135206135207135208135209135210135211135212135213135214135215135216135217135218135219135220135221135222135223135224135225135226135227135228135229135230135231135232135233135234135235135236135237135238135239135240135241135242135243135244135245135246135247135248135249135250135251135252135253135254135255135256135257135258135259135260135261135262135263135264135265135266135267135268135269135270135271135272135273135274135275135276135277135278135279135280135281135282135283135284135285135286135287135288135289135290135291135292135293135294135295135296135297135298135299135300135301135302135303135304135305135306135307135308135309135310135311135312135313135314135315135316135317135318135319135320135321135322135323135324135325135326135327135328135329135330135331135332135333135334135335135336135337135338135339135340135341135342135343135344135345135346135347135348135349135350135351135352135353135354135355135356135357135358135359135360135361135362135363135364135365135366135367135368135369135370135371135372135373135374135375135376135377135378135379135380135381135382135383135384135385135386135387135388135389135390135391135392135393135394135395135396135397135398135399135400135401135402135403135404135405135406135407135408135409135410135411135412135413135414135415135416135417135418135419135420135421135422135423135424135425135426135427135428135429135430135431135432135433135434135435135436135437135438135439135440135441135442135443135444135445135446135447135448135449135450135451135452135453135454135455135456135457135458135459135460135461135462135463135464135465135466135467135468135469135470135471135472135473135474135475135476135477135478135479135480135481135482135483135484135485135486135487135488135489135490135491135492135493135494135495135496135497135498135499135500135501135502135503135504135505135506135507135508135509135510135511135512135513135514135515135516135517135518135519135520135521135522135523135524135525135526135527135528135529135530135531135532135533135534135535135536135537135538135539135540135541135542135543135544135545135546135547135548135549135550135551135552135553135554135555135556135557135558135559135560135561135562135563135564135565135566135567135568135569135570135571135572135573135574135575135576135577135578135579135580135581135582135583135584135585135586135587135588135589135590135591135592135593135594135595135596135597135598135599135600135601135602135603135604135605135606135607135608135609135610135611135612135613135614135615135616135617135618135619135620135621135622135623135624135625135626135627135628135629135630135631135632135633135634135635135636135637135638135639135640135641135642135643135644135645135646135647135648135649135650135651135652135653135654135655135656135657135658135659135660135661135662135663135664135665135666135667135668135669135670135671135672135673135674135675135676135677135678135679135680135681135682135683135684135685135686135687135688135689135690135691135692135693135694135695135696135697135698135699135700135701135702135703135704135705135706135707135708135709135710135711135712135713135714135715135716135717135718135719135720135721135722135723135724135725135726135727135728135729135730135731135732135733135734135735135736135737135738135739135740135741135742135743135744135745135746135747135748135749135750135751135752135753135754135755135756135757135758135759135760135761135762135763135764135765135766135767135768135769135770135771135772135773135774135775135776135777135778135779135780135781135782135783135784135785135786135787135788135789135790135791135792135793135794135795135796135797135798135799135800135801135802135803135804135805135806135807135808135809135810135811135812135813135814135815135816135817135818135819135820135821135822135823135824135825135826135827135828135829135830135831135832135833135834135835135836135837135838135839135840135841135842135843135844135845135846135847135848135849135850135851135852135853135854135855135856135857135858135859135860135861135862135863135864135865135866135867135868135869135870135871135872135873135874135875135876135877135878135879135880135881135882135883135884135885135886135887135888135889135890135891135892135893135894135895135896135897135898135899135900135901135902135903135904135905135906135907135908135909135910135911135912135913135914135915135916135917135918135919135920135921135922135923135924135925135926135927135928135929135930135931135932135933135934135935135936135937135938135939135940135941135942135943135944135945135946135947135948135949135950135951135952135953135954135955135956135957135958135959135960135961135962135963135964135965135966135967135968135969135970135971135972135973135974135975135976135977135978135979135980135981135982135983135984135985135986135987135988135989135990135991135992135993135994135995135996135997135998135999136000136001136002136003136004136005136006136007136008136009136010136011136012136013136014136015136016136017136018136019136020136021136022136023136024136025136026136027136028136029136030136031136032136033136034136035136036136037136038136039136040136041136042136043136044136045136046136047136048136049136050136051136052136053136054136055136056136057136058136059136060136061136062136063136064136065136066136067136068136069136070136071136072136073136074136075136076136077136078136079136080136081136082136083136084136085136086136087136088136089136090136091136092136093136094136095136096136097136098136099136100136101136102136103136104136105136106136107136108136109136110136111136112136113136114136115136116136117136118136119136120136121136122136123136124136125136126136127136128136129136130136131136132136133136134136135136136136137136138136139136140136141136142136143136144136145136146136147136148136149136150136151136152136153136154136155136156136157136158136159136160136161136162136163136164136165136166136167136168136169136170136171136172136173136174136175136176136177136178136179136180136181136182136183136184136185136186136187136188136189136190136191136192136193136194136195136196136197136198136199136200136201136202136203136204136205136206136207136208136209136210136211136212136213136214136215136216136217136218136219136220136221136222136223136224136225136226136227136228136229136230136231136232136233136234136235136236136237136238136239136240136241136242136243136244136245136246136247136248136249136250136251136252136253136254136255136256136257136258136259136260136261136262136263136264136265136266136267136268136269136270136271136272136273136274136275136276136277136278136279136280136281136282136283136284136285136286136287136288136289136290136291136292136293136294136295136296136297136298136299136300136301136302136303136304136305136306136307136308136309136310136311136312136313136314136315136316136317136318136319136320136321136322136323136324136325136326136327136328136329136330136331136332136333136334136335136336136337136338136339136340136341136342136343136344136345136346136347136348136349136350136351136352136353136354136355136356136357136358136359136360136361136362136363136364136365136366136367136368136369136370136371136372136373136374136375136376136377136378136379136380136381136382136383136384136385136386136387136388136389136390136391136392136393136394136395136396136397136398136399136400136401136402136403136404136405136406136407136408136409136410136411136412136413136414136415136416136417136418136419136420136421136422136423136424136425136426136427136428136429136430136431136432136433136434136435136436136437136438136439136440136441136442136443136444136445136446136447136448136449136450136451136452136453136454136455136456136457136458136459136460136461136462136463136464136465136466136467136468136469136470136471136472136473136474136475136476136477136478136479136480136481136482136483136484136485136486136487136488136489136490136491136492136493136494136495136496136497136498136499136500136501136502136503136504136505136506136507136508136509136510136511136512136513136514136515136516136517136518136519136520136521136522136523136524136525136526136527136528136529136530136531136532136533136534136535136536136537136538136539136540136541136542136543136544136545136546136547136548136549136550136551136552136553136554136555136556136557136558136559136560136561136562136563136564136565136566136567136568136569136570136571136572136573136574136575136576136577136578136579136580136581136582136583136584136585136586136587136588136589136590136591136592136593136594136595136596136597136598136599136600136601136602136603136604136605136606136607136608136609136610136611136612136613136614136615136616136617136618136619136620136621136622136623136624136625136626136627136628136629136630136631136632136633136634136635136636136637136638136639136640136641136642136643136644136645136646136647136648136649136650136651136652136653136654136655136656136657136658136659136660136661136662136663136664136665136666136667136668136669136670136671136672136673136674136675136676136677136678136679136680136681136682136683136684136685136686136687136688136689136690136691136692136693136694136695136696136697136698136699136700136701136702136703136704136705136706136707136708136709136710136711136712136713136714136715136716136717136718136719136720136721136722136723136724136725136726136727136728136729136730136731136732136733136734136735136736136737136738136739136740136741136742136743136744136745136746136747136748136749136750136751136752136753136754136755136756136757136758136759136760136761136762136763136764136765136766136767136768136769136770136771136772136773136774136775136776136777136778136779136780136781136782136783136784136785136786136787136788136789136790136791136792136793136794136795136796136797136798136799136800136801136802136803136804136805136806136807136808136809136810136811136812136813136814136815136816136817136818136819136820136821136822136823136824136825136826136827136828136829136830136831136832136833136834136835136836136837136838136839136840136841136842136843136844136845136846136847136848136849136850136851136852136853136854136855136856136857136858136859136860136861136862136863136864136865136866136867136868136869136870136871136872136873136874136875136876136877136878136879136880136881136882136883136884136885136886136887136888136889136890136891136892136893136894136895136896136897136898136899136900136901136902136903136904136905136906136907136908136909136910136911136912136913136914136915136916136917136918136919136920136921136922136923136924136925136926136927136928136929136930136931136932136933136934136935136936136937136938136939136940136941136942136943136944136945136946136947136948136949136950136951136952136953136954136955136956136957136958136959136960136961136962136963136964136965136966136967136968136969136970136971136972136973136974136975136976136977136978136979136980136981136982136983136984136985136986136987136988136989136990136991136992136993136994136995136996136997136998136999137000137001137002137003137004137005137006137007137008137009137010137011137012137013137014137015137016137017137018137019137020137021137022137023137024137025137026137027137028137029137030137031137032137033137034137035137036137037137038137039137040137041137042137043137044137045137046137047137048137049137050137051137052137053137054137055137056137057137058137059137060137061137062137063137064137065137066137067137068137069137070137071137072137073137074137075137076137077137078137079137080137081137082137083137084137085137086137087137088137089137090137091137092137093137094137095137096137097137098137099137100137101137102137103137104137105137106137107137108137109137110137111137112137113137114137115137116137117137118137119137120137121137122137123137124137125137126137127137128137129137130137131137132137133137134137135137136137137137138137139137140137141137142137143137144137145137146137147137148137149137150137151137152137153137154137155137156137157137158137159137160137161137162137163137164137165137166137167137168137169137170137171137172137173137174137175137176137177137178137179137180137181137182137183137184137185137186137187137188137189137190137191137192137193137194137195137196137197137198137199137200137201137202137203137204137205137206137207137208137209137210137211137212137213137214137215137216137217137218137219137220137221137222137223137224137225137226137227137228137229137230137231137232137233137234137235137236137237137238137239137240137241137242137243137244137245137246137247137248137249137250137251137252137253137254137255137256137257137258137259137260137261137262137263137264137265137266137267137268137269137270137271137272137273137274137275137276137277137278137279137280137281137282137283137284137285137286137287137288137289137290137291137292137293137294137295137296137297137298137299137300137301137302137303137304137305137306137307137308137309137310137311137312137313137314137315137316137317137318137319137320137321137322137323137324137325137326137327137328137329137330137331137332137333137334137335137336137337137338137339137340137341137342137343137344137345137346137347137348137349137350137351137352137353137354137355137356137357137358137359137360137361137362137363137364137365137366137367137368137369137370137371137372137373137374137375137376137377137378137379137380137381137382137383137384137385137386137387137388137389137390137391137392137393137394137395137396137397137398137399137400137401137402137403137404137405137406137407137408137409137410137411137412137413137414137415137416137417137418137419137420137421137422137423137424137425137426137427137428137429137430137431137432137433137434137435137436137437137438137439137440137441137442137443137444137445137446137447137448137449137450137451137452137453137454137455137456137457137458137459137460137461137462137463137464137465137466137467137468137469137470137471137472137473137474137475137476137477137478137479137480137481137482137483137484137485137486137487137488137489137490137491137492137493137494137495137496137497137498137499137500137501137502137503137504137505137506137507137508137509137510137511137512137513137514137515137516137517137518137519137520137521137522137523137524137525137526137527137528137529137530137531137532137533137534137535137536137537137538137539137540137541137542137543137544137545137546137547137548137549137550137551137552137553137554137555137556137557137558137559137560137561137562137563137564137565137566137567137568137569137570137571137572137573137574137575137576137577137578137579137580137581137582137583137584137585137586137587137588137589137590137591137592137593137594137595137596137597137598137599137600137601137602137603137604137605137606137607137608137609137610137611137612137613137614137615137616137617137618137619137620137621137622137623137624137625137626137627137628137629137630137631137632137633137634137635137636137637137638137639137640137641137642137643137644137645137646137647137648137649137650137651137652137653137654137655137656137657137658137659137660137661137662137663137664137665137666137667137668137669137670137671137672137673137674137675137676137677137678137679137680137681137682137683137684137685137686137687137688137689137690137691137692137693137694137695137696137697137698137699137700137701137702137703137704137705137706137707137708137709137710137711137712137713137714137715137716137717137718137719137720137721137722137723137724137725137726137727137728137729137730137731137732137733137734137735137736137737137738137739137740137741137742137743137744137745137746137747137748137749137750137751137752137753137754137755137756137757137758137759137760137761137762137763137764137765137766137767137768137769137770137771137772137773137774137775137776137777137778137779137780137781137782137783137784137785137786137787137788137789137790137791137792137793137794137795137796137797137798137799137800137801137802137803137804137805137806137807137808137809137810137811137812137813137814137815137816137817137818137819137820137821137822137823137824137825137826137827137828137829137830137831137832137833137834137835137836137837137838137839137840137841137842137843137844137845137846137847137848137849137850137851137852137853137854137855137856137857137858137859137860137861137862137863137864137865137866137867137868137869137870137871137872137873137874137875137876137877137878137879137880137881137882137883137884137885137886137887137888137889137890137891137892137893137894137895137896137897137898137899137900137901137902137903137904137905137906137907137908137909137910137911137912137913137914137915137916137917137918137919137920137921137922137923137924137925137926137927137928137929137930137931137932137933137934137935137936137937137938137939137940137941137942137943137944137945137946137947137948137949137950137951137952137953137954137955137956137957137958137959137960137961137962137963137964137965137966137967137968137969137970137971137972137973137974137975137976137977137978137979137980137981137982137983137984137985137986137987137988137989137990137991137992137993137994137995137996137997137998137999138000138001138002138003138004138005138006138007138008138009138010138011138012138013138014138015138016138017138018138019138020138021138022138023138024138025138026138027138028138029138030138031138032138033138034138035138036138037138038138039138040138041138042138043138044138045138046138047138048138049138050138051138052138053138054138055138056138057138058138059138060138061138062138063138064138065138066138067138068138069138070138071138072138073138074138075138076138077138078138079138080138081138082138083138084138085138086138087138088138089138090138091138092138093138094138095138096138097138098138099138100138101138102138103138104138105138106138107138108138109138110138111138112138113138114138115138116138117138118138119138120138121138122138123138124138125138126138127138128138129138130138131138132138133138134138135138136138137138138138139138140138141138142138143138144138145138146138147138148138149138150138151138152138153138154138155138156138157138158138159138160138161138162138163138164138165138166138167138168138169138170138171138172138173138174138175138176138177138178138179138180138181138182138183138184138185138186138187138188138189138190138191138192138193138194138195138196138197138198138199138200138201138202138203138204138205138206138207138208138209138210138211138212138213138214138215138216138217138218138219138220138221138222138223138224138225138226138227138228138229138230138231138232138233138234138235138236138237138238138239138240138241138242138243138244138245138246138247138248138249138250138251138252138253138254138255138256138257138258138259138260138261138262138263138264138265138266138267138268138269138270138271138272138273138274138275138276138277138278138279138280138281138282138283138284138285138286138287138288138289138290138291138292138293138294138295138296138297138298138299138300138301138302138303138304138305138306138307138308138309138310138311138312138313138314138315138316138317138318138319138320138321138322138323138324138325138326138327138328138329138330138331138332138333138334138335138336138337138338138339138340138341138342138343138344138345138346138347138348138349138350138351138352138353138354138355138356138357138358138359138360138361138362138363138364138365138366138367138368138369138370138371138372138373138374138375138376138377138378138379138380138381138382138383138384138385138386138387138388138389138390138391138392138393138394138395138396138397138398138399138400138401138402138403138404138405138406138407138408138409138410138411138412138413138414138415138416138417138418138419138420138421138422138423138424138425138426138427138428138429138430138431138432138433138434138435138436138437138438138439138440138441138442138443138444138445138446138447138448138449138450138451138452138453138454138455138456138457138458138459138460138461138462138463138464138465138466138467138468138469138470138471138472138473138474138475138476138477138478138479138480138481138482138483138484138485138486138487138488138489138490138491138492138493138494138495138496138497138498138499138500138501138502138503138504138505138506138507138508138509138510138511138512138513138514138515138516138517138518138519138520138521138522138523138524138525138526138527138528138529138530138531138532138533138534138535138536138537138538138539138540138541138542138543138544138545138546138547138548138549138550138551138552138553138554138555138556138557138558138559138560138561138562138563138564138565138566138567138568138569138570138571138572138573138574138575138576138577138578138579138580138581138582138583138584138585138586138587138588138589138590138591138592138593138594138595138596138597138598138599138600138601138602138603138604138605138606138607138608138609138610138611138612138613138614138615138616138617138618138619138620138621138622138623138624138625138626138627138628138629138630138631138632138633138634138635138636138637138638138639138640138641138642138643138644138645138646138647138648138649138650138651138652138653138654138655138656138657138658138659138660138661138662138663138664138665138666138667138668138669138670138671138672138673138674138675138676138677138678138679138680138681138682138683138684138685138686138687138688138689138690138691138692138693138694138695138696138697138698138699138700138701138702138703138704138705138706138707138708138709138710138711138712138713138714138715138716138717138718138719138720138721138722138723138724138725138726138727138728138729138730138731138732138733138734138735138736138737138738138739138740138741138742138743138744138745138746138747138748138749138750138751138752138753138754138755138756138757138758138759138760138761138762138763138764138765138766138767138768138769138770138771138772138773138774138775138776138777138778138779138780138781138782138783138784138785138786138787138788138789138790138791138792138793138794138795138796138797138798138799138800138801138802138803138804138805138806138807138808138809138810138811138812138813138814138815138816138817138818138819138820138821138822138823138824138825138826138827138828138829138830138831138832138833138834138835138836138837138838138839138840138841138842138843138844138845138846138847138848138849138850138851138852138853138854138855138856138857138858138859138860138861138862138863138864138865138866138867138868138869138870138871138872138873138874138875138876138877138878138879138880138881138882138883138884138885138886138887138888138889138890138891138892138893138894138895138896138897138898138899138900138901138902138903138904138905138906138907138908138909138910138911138912138913138914138915138916138917138918138919138920138921138922138923138924138925138926138927138928138929138930138931138932138933138934138935138936138937138938138939138940138941138942138943138944138945138946138947138948138949138950138951138952138953138954138955138956138957138958138959138960138961138962138963138964138965138966138967138968138969138970138971138972138973138974138975138976138977138978138979138980138981138982138983138984138985138986138987138988138989138990138991138992138993138994138995138996138997138998138999139000139001139002139003139004139005139006139007139008139009139010139011139012139013139014139015139016139017139018139019139020139021139022139023139024139025139026139027139028139029139030139031139032139033139034139035139036139037139038139039139040139041139042139043139044139045139046139047139048139049139050139051139052139053139054139055139056139057139058139059139060139061139062139063139064139065139066139067139068139069139070139071139072139073139074139075139076139077139078139079139080139081139082139083139084139085139086139087139088139089139090139091139092139093139094139095139096139097139098139099139100139101139102139103139104139105139106139107139108139109139110139111139112139113139114139115139116139117139118139119139120139121139122139123139124139125139126139127139128139129139130139131139132139133139134139135139136139137139138139139139140139141139142139143139144139145139146139147139148139149139150139151139152139153139154139155139156139157139158139159139160139161139162139163139164139165139166139167139168139169139170139171139172139173139174139175139176139177139178139179139180139181139182139183139184139185139186139187139188139189139190139191139192139193139194139195139196139197139198139199139200139201139202139203139204139205139206139207139208139209139210139211139212139213139214139215139216139217139218139219139220139221139222139223139224139225139226139227139228139229139230139231139232139233139234139235139236139237139238139239139240139241139242139243139244139245139246139247139248139249139250139251139252139253139254139255139256139257139258139259139260139261139262139263139264139265139266139267139268139269139270139271139272139273139274139275139276139277139278139279139280139281139282139283139284139285139286139287139288139289139290139291139292139293139294139295139296139297139298139299139300139301139302139303139304139305139306139307139308139309139310139311139312139313139314139315139316139317139318139319139320139321139322139323139324139325139326139327139328139329139330139331139332139333139334139335139336139337139338139339139340139341139342139343139344139345139346139347139348139349139350139351139352139353139354139355139356139357139358139359139360139361139362139363139364139365139366139367139368139369139370139371139372139373139374139375139376139377139378139379139380139381139382139383139384139385139386139387139388139389139390139391139392139393139394139395139396139397139398139399139400139401139402139403139404139405139406139407139408139409139410139411139412139413139414139415139416139417139418139419139420139421139422139423139424139425139426139427139428139429139430139431139432139433139434139435139436139437139438139439139440139441139442139443139444139445139446139447139448139449139450139451139452139453139454139455139456139457139458139459139460139461139462139463139464139465139466139467139468139469139470139471139472139473139474139475139476139477139478139479139480139481139482139483139484139485139486139487139488139489139490139491139492139493139494139495139496139497139498139499139500139501139502139503139504139505139506139507139508139509139510139511139512139513139514139515139516139517139518139519139520139521139522139523139524139525139526139527139528139529139530139531139532139533139534139535139536139537139538139539139540139541139542139543139544139545139546139547139548139549139550139551139552139553139554139555139556139557139558139559139560139561139562139563139564139565139566139567139568139569139570139571139572139573139574139575139576139577139578139579139580139581139582139583139584139585139586139587139588139589139590139591139592139593139594139595139596139597139598139599139600139601139602139603139604139605139606139607139608139609139610139611139612139613139614139615139616139617139618139619139620139621139622139623139624139625139626139627139628139629139630139631139632139633139634139635139636139637139638139639139640139641139642139643139644139645139646139647139648139649139650139651139652139653139654139655139656139657139658139659139660139661139662139663139664139665139666139667139668139669139670139671139672139673139674139675139676139677139678139679139680139681139682139683139684139685139686139687139688139689139690139691139692139693139694139695139696139697139698139699139700139701139702139703139704139705139706139707139708139709139710139711139712139713139714139715139716139717139718139719139720139721139722139723139724139725139726139727139728139729139730139731139732139733139734139735139736139737139738139739139740139741139742139743139744139745139746139747139748139749139750139751139752139753139754139755139756139757139758139759139760139761139762139763139764139765139766139767139768139769139770139771139772139773139774139775139776139777139778139779139780139781139782139783139784139785139786139787139788139789139790139791139792139793139794139795139796139797139798139799139800139801139802139803139804139805139806139807139808139809139810139811139812139813139814139815139816139817139818139819139820139821139822139823139824139825139826139827139828139829139830139831139832139833139834139835139836139837139838139839139840139841139842139843139844139845139846139847139848139849139850139851139852139853139854139855139856139857139858139859139860139861139862139863139864139865139866139867139868139869139870139871139872139873139874139875139876139877139878139879139880139881139882139883139884139885139886139887139888139889139890139891139892139893139894139895139896139897139898139899139900139901139902139903139904139905139906139907139908139909139910139911139912139913139914139915139916139917139918139919139920139921139922139923139924139925139926139927139928139929139930139931139932139933139934139935139936139937139938139939139940139941139942139943139944139945139946139947139948139949139950139951139952139953139954139955139956139957139958139959139960139961139962139963139964139965139966139967139968139969139970139971139972139973139974139975139976139977139978139979139980139981139982139983139984139985139986139987139988139989139990139991139992139993139994139995139996139997139998139999140000140001140002140003140004140005140006140007140008140009140010140011140012140013140014140015140016140017140018140019140020140021140022140023140024140025140026140027140028140029140030140031140032140033140034140035140036140037140038140039140040140041140042140043140044140045140046140047140048140049140050140051140052140053140054140055140056140057140058140059140060140061140062140063140064140065140066140067140068140069140070140071140072140073140074140075140076140077140078140079140080140081140082140083140084140085140086140087140088140089140090140091140092140093140094140095140096140097140098140099140100140101140102140103140104140105140106140107140108140109140110140111140112140113140114140115140116140117140118140119140120140121140122140123140124140125140126140127140128140129140130140131140132140133140134140135140136140137140138140139140140140141140142140143140144140145140146140147140148140149140150140151140152140153140154140155140156140157140158140159140160140161140162140163140164140165140166140167140168140169140170140171140172140173140174140175140176140177140178140179140180140181140182140183140184140185140186140187140188140189140190140191140192140193140194140195140196140197140198140199140200140201140202140203140204140205140206140207140208140209140210140211140212140213140214140215140216140217140218140219140220140221140222140223140224140225140226140227140228140229140230140231140232140233140234140235140236140237140238140239140240140241140242140243140244140245140246140247140248140249140250140251140252140253140254140255140256140257140258140259140260140261140262140263140264140265140266140267140268140269140270140271140272140273140274140275140276140277140278140279140280140281140282140283140284140285140286140287140288140289140290140291140292140293140294140295140296140297140298140299140300140301140302140303140304140305140306140307140308140309140310140311140312140313140314140315140316140317140318140319140320140321140322140323140324140325140326140327140328140329140330140331140332140333140334140335140336140337140338140339140340140341140342140343140344140345140346140347140348140349140350140351140352140353140354140355140356140357140358140359140360140361140362140363140364140365140366140367140368140369140370140371140372140373140374140375140376140377140378140379140380140381140382140383140384140385140386140387140388140389140390140391140392140393140394140395140396140397140398140399140400140401140402140403140404140405140406140407140408140409140410140411140412140413140414140415140416140417140418140419140420140421140422140423140424140425140426140427140428140429140430140431140432140433140434140435140436140437140438140439140440140441140442140443140444140445140446140447140448140449140450140451140452140453140454140455140456140457140458140459140460140461140462140463140464140465140466140467140468140469140470140471140472140473140474140475140476140477140478140479140480140481140482140483140484140485140486140487140488140489140490140491140492140493140494140495140496140497140498140499140500140501140502140503140504140505140506140507140508140509140510140511140512140513140514140515140516140517140518140519140520140521140522140523140524140525140526140527140528140529140530140531140532140533140534140535140536140537140538140539140540140541140542140543140544140545140546140547140548140549140550140551140552140553140554140555140556140557140558140559140560140561140562140563140564140565140566140567140568140569140570140571140572140573140574140575140576140577140578140579140580140581140582140583140584140585140586140587140588140589140590140591140592140593140594140595140596140597140598140599140600140601140602140603140604140605140606140607140608140609140610140611140612140613140614140615140616140617140618140619140620140621140622140623140624140625140626140627140628140629140630140631140632140633140634140635140636140637140638140639140640140641140642140643140644140645140646140647140648140649140650140651140652140653140654140655140656140657140658140659140660140661140662140663140664140665140666140667140668140669140670140671140672140673140674140675140676140677140678140679140680140681140682140683140684140685140686140687140688140689140690140691140692140693140694140695140696140697140698140699140700140701140702140703140704140705140706140707140708140709140710140711140712140713140714140715140716140717140718140719140720140721140722140723140724140725140726140727140728140729140730140731140732140733140734140735140736140737140738140739140740140741140742140743140744140745140746140747140748140749140750140751140752140753140754140755140756140757140758140759140760140761140762140763140764140765140766140767140768140769140770140771140772140773140774140775140776140777140778140779140780140781140782140783140784140785140786140787140788140789140790140791140792140793140794140795140796140797140798140799140800140801140802140803140804140805140806140807140808140809140810140811140812140813140814140815140816140817140818140819140820140821140822140823140824140825140826140827140828140829140830140831140832140833140834140835140836140837140838140839140840140841140842140843140844140845140846140847140848140849140850140851140852140853140854140855140856140857140858140859140860140861140862140863140864140865140866140867140868140869140870140871140872140873140874140875140876140877140878140879140880140881140882140883140884140885140886140887140888140889140890140891140892140893140894140895140896140897140898140899140900140901140902140903140904140905140906140907140908140909140910140911140912140913140914140915140916140917140918140919140920140921140922140923140924140925140926140927140928140929140930140931140932140933140934140935140936140937140938140939140940140941140942140943140944140945140946140947140948140949140950140951140952140953140954140955140956140957140958140959140960140961140962140963140964140965140966140967140968140969140970140971140972140973140974140975140976140977140978140979140980140981140982140983140984140985140986140987140988140989140990140991140992140993140994140995140996140997140998140999141000141001141002141003141004141005141006141007141008141009141010141011141012141013141014141015141016141017141018141019141020141021141022141023141024141025141026141027141028141029141030141031141032141033141034141035141036141037141038141039141040141041141042141043141044141045141046141047141048141049141050141051141052141053141054141055141056141057141058141059141060141061141062141063141064141065141066141067141068141069141070141071141072141073141074141075141076141077141078141079141080141081141082141083141084141085141086141087141088141089141090141091141092141093141094141095141096141097141098141099141100141101141102141103141104141105141106141107141108141109141110141111141112141113141114141115141116141117141118141119141120141121141122141123141124141125141126141127141128141129141130141131141132141133141134141135141136141137141138141139141140141141141142141143141144141145141146141147141148141149141150141151141152141153141154141155141156141157141158141159141160141161141162141163141164141165141166141167141168141169141170141171141172141173141174141175141176141177141178141179141180141181141182141183141184141185141186141187141188141189141190141191141192141193141194141195141196141197141198141199141200141201141202141203141204141205141206141207141208141209141210141211141212141213141214141215141216141217141218141219141220141221141222141223141224141225141226141227141228141229141230141231141232141233141234141235141236141237141238141239141240141241141242141243141244141245141246141247141248141249141250141251141252141253141254141255141256141257141258141259141260141261141262141263141264141265141266141267141268141269141270141271141272141273141274141275141276141277141278141279141280141281141282141283141284141285141286141287141288141289141290141291141292141293141294141295141296141297141298141299141300141301141302141303141304141305141306141307141308141309141310141311141312141313141314141315141316141317141318141319141320141321141322141323141324141325141326141327141328141329141330141331141332141333141334141335141336141337141338141339141340141341141342141343141344141345141346141347141348141349141350141351141352141353141354141355141356141357141358141359141360141361141362141363141364141365141366141367141368141369141370141371141372141373141374141375141376141377141378141379141380141381141382141383141384141385141386141387141388141389141390141391141392141393141394141395141396141397141398141399141400141401141402141403141404141405141406141407141408141409141410141411141412141413141414141415141416141417141418141419141420141421141422141423141424141425141426141427141428141429141430141431141432141433141434141435141436141437141438141439141440141441141442141443141444141445141446141447141448141449141450141451141452141453141454141455141456141457141458141459141460141461141462141463141464141465141466141467141468141469141470141471141472141473141474141475141476141477141478141479141480141481141482141483141484141485141486141487141488141489141490141491141492141493141494141495141496141497141498141499141500141501141502141503141504141505141506141507141508141509141510141511141512141513141514141515141516141517141518141519141520141521141522141523141524141525141526141527141528141529141530141531141532141533141534141535141536141537141538141539141540141541141542141543141544141545141546141547141548141549141550141551141552141553141554141555141556141557141558141559141560141561141562141563141564141565141566141567141568141569141570141571141572141573141574141575141576141577141578141579141580141581141582141583141584141585141586141587141588141589141590141591141592141593141594141595141596141597141598141599141600141601141602141603141604141605141606141607141608141609141610141611141612141613141614141615141616141617141618141619141620141621141622141623141624141625141626141627141628141629141630141631141632141633141634141635141636141637141638141639141640141641141642141643141644141645141646141647141648141649141650141651141652141653141654141655141656141657141658141659141660141661141662141663141664141665141666141667141668141669141670141671141672141673141674141675141676141677141678141679141680141681141682141683141684141685141686141687141688141689141690141691141692141693141694141695141696141697141698141699141700141701141702141703141704141705141706141707141708141709141710141711141712141713141714141715141716141717141718141719141720141721141722141723141724141725141726141727141728141729141730141731141732141733141734141735141736141737141738141739141740141741141742141743141744141745141746141747141748141749141750141751141752141753141754141755141756141757141758141759141760141761141762141763141764141765141766141767141768141769141770141771141772141773141774141775141776141777141778141779141780141781141782141783141784141785141786141787141788141789141790141791141792141793141794141795141796141797141798141799141800141801141802141803141804141805141806141807141808141809141810141811141812141813141814141815141816141817141818141819141820141821141822141823141824141825141826141827141828141829141830141831141832141833141834141835141836141837141838141839141840141841141842141843141844141845141846141847141848141849141850141851141852141853141854141855141856141857141858141859141860141861141862141863141864141865141866141867141868141869141870141871141872141873141874141875141876141877141878141879141880141881141882141883141884141885141886141887141888141889141890141891141892141893141894141895141896141897141898141899141900141901141902141903141904141905141906141907141908141909141910141911141912141913141914141915141916141917141918141919141920141921141922141923141924141925141926141927141928141929141930141931141932141933141934141935141936141937141938141939141940141941141942141943141944141945141946141947141948141949141950141951141952141953141954141955141956141957141958141959141960141961141962141963141964141965141966141967141968141969141970141971141972141973141974141975141976141977141978141979141980141981141982141983141984141985141986141987141988141989141990141991141992141993141994141995141996141997141998141999142000142001142002142003142004142005142006142007142008142009142010142011142012142013142014142015142016142017142018142019142020142021142022142023142024142025142026142027142028142029142030142031142032142033142034142035142036142037142038142039142040142041142042142043142044142045142046142047142048142049142050142051142052142053142054142055142056142057142058142059142060142061142062142063142064142065142066142067142068142069142070142071142072142073142074142075142076142077
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (global = global || self, factory(global.Potree = {}));
  5. }(this, (function (exports) { 'use strict';
  6. // threejs.org/license
  7. const REVISION = '124';
  8. const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
  9. const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
  10. const CullFaceNone = 0;
  11. const CullFaceBack = 1;
  12. const CullFaceFront = 2;
  13. const CullFaceFrontBack = 3;
  14. const BasicShadowMap = 0;
  15. const PCFShadowMap = 1;
  16. const PCFSoftShadowMap = 2;
  17. const VSMShadowMap = 3;
  18. const FrontSide = 0;
  19. const BackSide = 1;
  20. const DoubleSide = 2;
  21. const FlatShading$1 = 1;
  22. const SmoothShading = 2;
  23. const NoBlending = 0;
  24. const NormalBlending = 1;
  25. const AdditiveBlending = 2;
  26. const SubtractiveBlending = 3;
  27. const MultiplyBlending = 4;
  28. const CustomBlending = 5;
  29. const AddEquation = 100;
  30. const SubtractEquation = 101;
  31. const ReverseSubtractEquation = 102;
  32. const MinEquation = 103;
  33. const MaxEquation = 104;
  34. const ZeroFactor = 200;
  35. const OneFactor = 201;
  36. const SrcColorFactor = 202;
  37. const OneMinusSrcColorFactor = 203;
  38. const SrcAlphaFactor = 204;
  39. const OneMinusSrcAlphaFactor = 205;
  40. const DstAlphaFactor = 206;
  41. const OneMinusDstAlphaFactor = 207;
  42. const DstColorFactor = 208;
  43. const OneMinusDstColorFactor = 209;
  44. const SrcAlphaSaturateFactor = 210;
  45. const NeverDepth = 0;
  46. const AlwaysDepth = 1;
  47. const LessDepth = 2;
  48. const LessEqualDepth = 3;
  49. const EqualDepth = 4;
  50. const GreaterEqualDepth = 5;
  51. const GreaterDepth = 6;
  52. const NotEqualDepth = 7;
  53. const MultiplyOperation = 0;
  54. const MixOperation = 1;
  55. const AddOperation = 2;
  56. const NoToneMapping = 0;
  57. const LinearToneMapping = 1;
  58. const ReinhardToneMapping = 2;
  59. const CineonToneMapping = 3;
  60. const ACESFilmicToneMapping = 4;
  61. const CustomToneMapping = 5;
  62. const UVMapping = 300;
  63. const CubeReflectionMapping = 301;
  64. const CubeRefractionMapping = 302;
  65. const EquirectangularReflectionMapping = 303;
  66. const EquirectangularRefractionMapping = 304;
  67. const CubeUVReflectionMapping = 306;
  68. const CubeUVRefractionMapping = 307;
  69. const RepeatWrapping = 1000;
  70. const ClampToEdgeWrapping = 1001;
  71. const MirroredRepeatWrapping = 1002;
  72. const NearestFilter = 1003;
  73. const NearestMipmapNearestFilter = 1004;
  74. const NearestMipMapNearestFilter = 1004;
  75. const NearestMipmapLinearFilter = 1005;
  76. const NearestMipMapLinearFilter = 1005;
  77. const LinearFilter = 1006;
  78. const LinearMipmapNearestFilter = 1007;
  79. const LinearMipMapNearestFilter = 1007;
  80. const LinearMipmapLinearFilter = 1008;
  81. const LinearMipMapLinearFilter = 1008;
  82. const UnsignedByteType = 1009;
  83. const ByteType = 1010;
  84. const ShortType = 1011;
  85. const UnsignedShortType = 1012;
  86. const IntType = 1013;
  87. const UnsignedIntType = 1014;
  88. const FloatType = 1015;
  89. const HalfFloatType = 1016;
  90. const UnsignedShort4444Type = 1017;
  91. const UnsignedShort5551Type = 1018;
  92. const UnsignedShort565Type = 1019;
  93. const UnsignedInt248Type$1 = 1020;
  94. const AlphaFormat = 1021;
  95. const RGBFormat = 1022;
  96. const RGBAFormat = 1023;
  97. const LuminanceFormat = 1024;
  98. const LuminanceAlphaFormat = 1025;
  99. const RGBEFormat = RGBAFormat;
  100. const DepthFormat = 1026;
  101. const DepthStencilFormat = 1027;
  102. const RedFormat = 1028;
  103. const RedIntegerFormat = 1029;
  104. const RGFormat = 1030;
  105. const RGIntegerFormat = 1031;
  106. const RGBIntegerFormat = 1032;
  107. const RGBAIntegerFormat = 1033;
  108. const RGB_S3TC_DXT1_Format = 33776;
  109. const RGBA_S3TC_DXT1_Format$1 = 33777;
  110. const RGBA_S3TC_DXT3_Format = 33778;
  111. const RGBA_S3TC_DXT5_Format$1 = 33779;
  112. const RGB_PVRTC_4BPPV1_Format = 35840;
  113. const RGB_PVRTC_2BPPV1_Format = 35841;
  114. const RGBA_PVRTC_4BPPV1_Format = 35842;
  115. const RGBA_PVRTC_2BPPV1_Format = 35843;
  116. const RGB_ETC1_Format = 36196;
  117. const RGB_ETC2_Format = 37492;
  118. const RGBA_ETC2_EAC_Format = 37496;
  119. const RGBA_ASTC_4x4_Format = 37808;
  120. const RGBA_ASTC_5x4_Format = 37809;
  121. const RGBA_ASTC_5x5_Format = 37810;
  122. const RGBA_ASTC_6x5_Format = 37811;
  123. const RGBA_ASTC_6x6_Format = 37812;
  124. const RGBA_ASTC_8x5_Format = 37813;
  125. const RGBA_ASTC_8x6_Format = 37814;
  126. const RGBA_ASTC_8x8_Format = 37815;
  127. const RGBA_ASTC_10x5_Format = 37816;
  128. const RGBA_ASTC_10x6_Format = 37817;
  129. const RGBA_ASTC_10x8_Format = 37818;
  130. const RGBA_ASTC_10x10_Format = 37819;
  131. const RGBA_ASTC_12x10_Format = 37820;
  132. const RGBA_ASTC_12x12_Format = 37821;
  133. const RGBA_BPTC_Format = 36492;
  134. const SRGB8_ALPHA8_ASTC_4x4_Format = 37840;
  135. const SRGB8_ALPHA8_ASTC_5x4_Format = 37841;
  136. const SRGB8_ALPHA8_ASTC_5x5_Format = 37842;
  137. const SRGB8_ALPHA8_ASTC_6x5_Format = 37843;
  138. const SRGB8_ALPHA8_ASTC_6x6_Format = 37844;
  139. const SRGB8_ALPHA8_ASTC_8x5_Format = 37845;
  140. const SRGB8_ALPHA8_ASTC_8x6_Format = 37846;
  141. const SRGB8_ALPHA8_ASTC_8x8_Format = 37847;
  142. const SRGB8_ALPHA8_ASTC_10x5_Format = 37848;
  143. const SRGB8_ALPHA8_ASTC_10x6_Format = 37849;
  144. const SRGB8_ALPHA8_ASTC_10x8_Format = 37850;
  145. const SRGB8_ALPHA8_ASTC_10x10_Format = 37851;
  146. const SRGB8_ALPHA8_ASTC_12x10_Format = 37852;
  147. const SRGB8_ALPHA8_ASTC_12x12_Format = 37853;
  148. const LoopOnce = 2200;
  149. const LoopRepeat = 2201;
  150. const LoopPingPong = 2202;
  151. const InterpolateDiscrete = 2300;
  152. const InterpolateLinear = 2301;
  153. const InterpolateSmooth = 2302;
  154. const ZeroCurvatureEnding = 2400;
  155. const ZeroSlopeEnding = 2401;
  156. const WrapAroundEnding = 2402;
  157. const NormalAnimationBlendMode = 2500;
  158. const AdditiveAnimationBlendMode = 2501;
  159. const TrianglesDrawMode = 0;
  160. const TriangleStripDrawMode = 1;
  161. const TriangleFanDrawMode = 2;
  162. const LinearEncoding = 3000;
  163. const sRGBEncoding = 3001;
  164. const GammaEncoding = 3007;
  165. const RGBEEncoding = 3002;
  166. const LogLuvEncoding = 3003;
  167. const RGBM7Encoding = 3004;
  168. const RGBM16Encoding = 3005;
  169. const RGBDEncoding = 3006;
  170. const BasicDepthPacking = 3200;
  171. const RGBADepthPacking = 3201;
  172. const TangentSpaceNormalMap = 0;
  173. const ObjectSpaceNormalMap = 1;
  174. const ZeroStencilOp = 0;
  175. const KeepStencilOp = 7680;
  176. const ReplaceStencilOp = 7681;
  177. const IncrementStencilOp = 7682;
  178. const DecrementStencilOp = 7683;
  179. const IncrementWrapStencilOp = 34055;
  180. const DecrementWrapStencilOp = 34056;
  181. const InvertStencilOp = 5386;
  182. const NeverStencilFunc = 512;
  183. const LessStencilFunc = 513;
  184. const EqualStencilFunc = 514;
  185. const LessEqualStencilFunc = 515;
  186. const GreaterStencilFunc = 516;
  187. const NotEqualStencilFunc = 517;
  188. const GreaterEqualStencilFunc = 518;
  189. const AlwaysStencilFunc = 519;
  190. const StaticDrawUsage = 35044;
  191. const DynamicDrawUsage = 35048;
  192. const StreamDrawUsage = 35040;
  193. const StaticReadUsage = 35045;
  194. const DynamicReadUsage = 35049;
  195. const StreamReadUsage = 35041;
  196. const StaticCopyUsage = 35046;
  197. const DynamicCopyUsage = 35050;
  198. const StreamCopyUsage = 35042;
  199. const GLSL1 = '100';
  200. const GLSL3 = '300 es';
  201. /**
  202. * https://github.com/mrdoob/eventdispatcher.js/
  203. */
  204. function EventDispatcher() {}
  205. Object.assign( EventDispatcher.prototype, {
  206. addEventListener: function ( type, listener ) {
  207. if ( this._listeners === undefined ) this._listeners = {};
  208. const listeners = this._listeners;
  209. if ( listeners[ type ] === undefined ) {
  210. listeners[ type ] = [];
  211. }
  212. if ( listeners[ type ].indexOf( listener ) === - 1 ) {
  213. listeners[ type ].push( listener );
  214. }
  215. },
  216. hasEventListener: function ( type, listener ) {
  217. if ( this._listeners === undefined ) return false;
  218. const listeners = this._listeners;
  219. return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
  220. },
  221. dispatchEvent: function ( event ) {
  222. if ( this._listeners === undefined ) return;
  223. const listeners = this._listeners;
  224. const listenerArray = listeners[ event.type ];
  225. if ( listenerArray !== undefined ) {
  226. event.target = this;
  227. // Make a copy, in case listeners are removed while iterating.
  228. const array = listenerArray.slice( 0 );
  229. for ( let i = 0, l = array.length; i < l; i ++ ) {
  230. array[ i ].call( this, event );
  231. }
  232. }
  233. }
  234. } );
  235. const _lut = [];
  236. for ( let i = 0; i < 256; i ++ ) {
  237. _lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
  238. }
  239. let _seed = 1234567;
  240. const MathUtils$1 = {
  241. DEG2RAD: Math.PI / 180,
  242. RAD2DEG: 180 / Math.PI,
  243. generateUUID: function () {
  244. // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
  245. const d0 = Math.random() * 0xffffffff | 0;
  246. const d1 = Math.random() * 0xffffffff | 0;
  247. const d2 = Math.random() * 0xffffffff | 0;
  248. const d3 = Math.random() * 0xffffffff | 0;
  249. const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
  250. _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
  251. _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
  252. _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
  253. // .toUpperCase() here flattens concatenated strings to save heap memory space.
  254. return uuid.toUpperCase();
  255. },
  256. clamp: function ( value, min, max ) {
  257. return Math.max( min, Math.min( max, value ) );
  258. },
  259. // compute euclidian modulo of m % n
  260. // https://en.wikipedia.org/wiki/Modulo_operation
  261. euclideanModulo: function ( n, m ) {
  262. return ( ( n % m ) + m ) % m;
  263. },
  264. // Linear mapping from range <a1, a2> to range <b1, b2>
  265. mapLinear: function ( x, a1, a2, b1, b2 ) {
  266. return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
  267. },
  268. // https://en.wikipedia.org/wiki/Linear_interpolation
  269. lerp: function ( x, y, t ) {
  270. return ( 1 - t ) * x + t * y;
  271. },
  272. // http://en.wikipedia.org/wiki/Smoothstep
  273. smoothstep: function ( x, min, max ) {
  274. if ( x <= min ) return 0;
  275. if ( x >= max ) return 1;
  276. x = ( x - min ) / ( max - min );
  277. return x * x * ( 3 - 2 * x );
  278. },
  279. smootherstep: function ( x, min, max ) {
  280. if ( x <= min ) return 0;
  281. if ( x >= max ) return 1;
  282. x = ( x - min ) / ( max - min );
  283. return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
  284. },
  285. // Random integer from <low, high> interval
  286. randInt: function ( low, high ) {
  287. return low + Math.floor( Math.random() * ( high - low + 1 ) );
  288. },
  289. // Random float from <low, high> interval
  290. randFloat: function ( low, high ) {
  291. return low + Math.random() * ( high - low );
  292. },
  293. // Random float from <-range/2, range/2> interval
  294. randFloatSpread: function ( range ) {
  295. return range * ( 0.5 - Math.random() );
  296. },
  297. // Deterministic pseudo-random float in the interval [ 0, 1 ]
  298. seededRandom: function ( s ) {
  299. if ( s !== undefined ) _seed = s % 2147483647;
  300. // Park-Miller algorithm
  301. _seed = _seed * 16807 % 2147483647;
  302. return ( _seed - 1 ) / 2147483646;
  303. },
  304. degToRad: function ( degrees ) {
  305. return degrees * MathUtils$1.DEG2RAD;
  306. },
  307. radToDeg: function ( radians ) {
  308. return radians * MathUtils$1.RAD2DEG;
  309. },
  310. isPowerOfTwo: function ( value ) {
  311. return ( value & ( value - 1 ) ) === 0 && value !== 0;
  312. },
  313. ceilPowerOfTwo: function ( value ) {
  314. return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
  315. },
  316. floorPowerOfTwo: function ( value ) {
  317. return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
  318. },
  319. setQuaternionFromProperEuler: function ( q, a, b, c, order ) {
  320. // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
  321. // rotations are applied to the axes in the order specified by 'order'
  322. // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
  323. // angles are in radians
  324. const cos = Math.cos;
  325. const sin = Math.sin;
  326. const c2 = cos( b / 2 );
  327. const s2 = sin( b / 2 );
  328. const c13 = cos( ( a + c ) / 2 );
  329. const s13 = sin( ( a + c ) / 2 );
  330. const c1_3 = cos( ( a - c ) / 2 );
  331. const s1_3 = sin( ( a - c ) / 2 );
  332. const c3_1 = cos( ( c - a ) / 2 );
  333. const s3_1 = sin( ( c - a ) / 2 );
  334. switch ( order ) {
  335. case 'XYX':
  336. q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
  337. break;
  338. case 'YZY':
  339. q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
  340. break;
  341. case 'ZXZ':
  342. q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
  343. break;
  344. case 'XZX':
  345. q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
  346. break;
  347. case 'YXY':
  348. q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
  349. break;
  350. case 'ZYZ':
  351. q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
  352. break;
  353. default:
  354. console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
  355. }
  356. }
  357. };
  358. class Vector2 {
  359. constructor( x = 0, y = 0 ) {
  360. Object.defineProperty( this, 'isVector2', { value: true } );
  361. this.x = x;
  362. this.y = y;
  363. }
  364. get width() {
  365. return this.x;
  366. }
  367. set width( value ) {
  368. this.x = value;
  369. }
  370. get height() {
  371. return this.y;
  372. }
  373. set height( value ) {
  374. this.y = value;
  375. }
  376. set( x, y ) {
  377. this.x = x;
  378. this.y = y;
  379. return this;
  380. }
  381. setScalar( scalar ) {
  382. this.x = scalar;
  383. this.y = scalar;
  384. return this;
  385. }
  386. setX( x ) {
  387. this.x = x;
  388. return this;
  389. }
  390. setY( y ) {
  391. this.y = y;
  392. return this;
  393. }
  394. setComponent( index, value ) {
  395. switch ( index ) {
  396. case 0: this.x = value; break;
  397. case 1: this.y = value; break;
  398. default: throw new Error( 'index is out of range: ' + index );
  399. }
  400. return this;
  401. }
  402. getComponent( index ) {
  403. switch ( index ) {
  404. case 0: return this.x;
  405. case 1: return this.y;
  406. default: throw new Error( 'index is out of range: ' + index );
  407. }
  408. }
  409. clone() {
  410. return new this.constructor( this.x, this.y );
  411. }
  412. copy( v ) {
  413. this.x = v.x;
  414. this.y = v.y;
  415. return this;
  416. }
  417. add( v, w ) {
  418. if ( w !== undefined ) {
  419. console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
  420. return this.addVectors( v, w );
  421. }
  422. this.x += v.x;
  423. this.y += v.y;
  424. return this;
  425. }
  426. addScalar( s ) {
  427. this.x += s;
  428. this.y += s;
  429. return this;
  430. }
  431. addVectors( a, b ) {
  432. this.x = a.x + b.x;
  433. this.y = a.y + b.y;
  434. return this;
  435. }
  436. addScaledVector( v, s ) {
  437. this.x += v.x * s;
  438. this.y += v.y * s;
  439. return this;
  440. }
  441. sub( v, w ) {
  442. if ( w !== undefined ) {
  443. console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
  444. return this.subVectors( v, w );
  445. }
  446. this.x -= v.x;
  447. this.y -= v.y;
  448. return this;
  449. }
  450. subScalar( s ) {
  451. this.x -= s;
  452. this.y -= s;
  453. return this;
  454. }
  455. subVectors( a, b ) {
  456. this.x = a.x - b.x;
  457. this.y = a.y - b.y;
  458. return this;
  459. }
  460. multiply( v ) {
  461. this.x *= v.x;
  462. this.y *= v.y;
  463. return this;
  464. }
  465. multiplyScalar( scalar ) {
  466. this.x *= scalar;
  467. this.y *= scalar;
  468. return this;
  469. }
  470. divide( v ) {
  471. this.x /= v.x;
  472. this.y /= v.y;
  473. return this;
  474. }
  475. divideScalar( scalar ) {
  476. return this.multiplyScalar( 1 / scalar );
  477. }
  478. applyMatrix3( m ) {
  479. const x = this.x, y = this.y;
  480. const e = m.elements;
  481. this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
  482. this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
  483. return this;
  484. }
  485. min( v ) {
  486. this.x = Math.min( this.x, v.x );
  487. this.y = Math.min( this.y, v.y );
  488. return this;
  489. }
  490. max( v ) {
  491. this.x = Math.max( this.x, v.x );
  492. this.y = Math.max( this.y, v.y );
  493. return this;
  494. }
  495. clamp( min, max ) {
  496. // assumes min < max, componentwise
  497. this.x = Math.max( min.x, Math.min( max.x, this.x ) );
  498. this.y = Math.max( min.y, Math.min( max.y, this.y ) );
  499. return this;
  500. }
  501. clampScalar( minVal, maxVal ) {
  502. this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
  503. this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
  504. return this;
  505. }
  506. clampLength( min, max ) {
  507. const length = this.length();
  508. return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
  509. }
  510. floor() {
  511. this.x = Math.floor( this.x );
  512. this.y = Math.floor( this.y );
  513. return this;
  514. }
  515. ceil() {
  516. this.x = Math.ceil( this.x );
  517. this.y = Math.ceil( this.y );
  518. return this;
  519. }
  520. round() {
  521. this.x = Math.round( this.x );
  522. this.y = Math.round( this.y );
  523. return this;
  524. }
  525. roundToZero() {
  526. this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
  527. this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
  528. return this;
  529. }
  530. negate() {
  531. this.x = - this.x;
  532. this.y = - this.y;
  533. return this;
  534. }
  535. dot( v ) {
  536. return this.x * v.x + this.y * v.y;
  537. }
  538. cross( v ) {
  539. return this.x * v.y - this.y * v.x;
  540. }
  541. lengthSq() {
  542. return this.x * this.x + this.y * this.y;
  543. }
  544. length() {
  545. return Math.sqrt( this.x * this.x + this.y * this.y );
  546. }
  547. manhattanLength() {
  548. return Math.abs( this.x ) + Math.abs( this.y );
  549. }
  550. normalize() {
  551. return this.divideScalar( this.length() || 1 );
  552. }
  553. angle() {
  554. // computes the angle in radians with respect to the positive x-axis
  555. const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
  556. return angle;
  557. }
  558. distanceTo( v ) {
  559. return Math.sqrt( this.distanceToSquared( v ) );
  560. }
  561. distanceToSquared( v ) {
  562. const dx = this.x - v.x, dy = this.y - v.y;
  563. return dx * dx + dy * dy;
  564. }
  565. manhattanDistanceTo( v ) {
  566. return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
  567. }
  568. setLength( length ) {
  569. return this.normalize().multiplyScalar( length );
  570. }
  571. lerp( v, alpha ) {
  572. this.x += ( v.x - this.x ) * alpha;
  573. this.y += ( v.y - this.y ) * alpha;
  574. return this;
  575. }
  576. lerpVectors( v1, v2, alpha ) {
  577. this.x = v1.x + ( v2.x - v1.x ) * alpha;
  578. this.y = v1.y + ( v2.y - v1.y ) * alpha;
  579. return this;
  580. }
  581. equals( v ) {
  582. return ( ( v.x === this.x ) && ( v.y === this.y ) );
  583. }
  584. fromArray( array, offset = 0 ) {
  585. this.x = array[ offset ];
  586. this.y = array[ offset + 1 ];
  587. return this;
  588. }
  589. toArray( array = [], offset = 0 ) {
  590. array[ offset ] = this.x;
  591. array[ offset + 1 ] = this.y;
  592. return array;
  593. }
  594. fromBufferAttribute( attribute, index, offset ) {
  595. if ( offset !== undefined ) {
  596. console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
  597. }
  598. this.x = attribute.getX( index );
  599. this.y = attribute.getY( index );
  600. return this;
  601. }
  602. rotateAround( center, angle ) {
  603. const c = Math.cos( angle ), s = Math.sin( angle );
  604. const x = this.x - center.x;
  605. const y = this.y - center.y;
  606. this.x = x * c - y * s + center.x;
  607. this.y = x * s + y * c + center.y;
  608. return this;
  609. }
  610. random() {
  611. this.x = Math.random();
  612. this.y = Math.random();
  613. return this;
  614. }
  615. }
  616. class Matrix3 {
  617. constructor() {
  618. Object.defineProperty( this, 'isMatrix3', { value: true } );
  619. this.elements = [
  620. 1, 0, 0,
  621. 0, 1, 0,
  622. 0, 0, 1
  623. ];
  624. if ( arguments.length > 0 ) {
  625. console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
  626. }
  627. }
  628. set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
  629. const te = this.elements;
  630. te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
  631. te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
  632. te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
  633. return this;
  634. }
  635. identity() {
  636. this.set(
  637. 1, 0, 0,
  638. 0, 1, 0,
  639. 0, 0, 1
  640. );
  641. return this;
  642. }
  643. clone() {
  644. return new this.constructor().fromArray( this.elements );
  645. }
  646. copy( m ) {
  647. const te = this.elements;
  648. const me = m.elements;
  649. te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
  650. te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
  651. te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
  652. return this;
  653. }
  654. extractBasis( xAxis, yAxis, zAxis ) {
  655. xAxis.setFromMatrix3Column( this, 0 );
  656. yAxis.setFromMatrix3Column( this, 1 );
  657. zAxis.setFromMatrix3Column( this, 2 );
  658. return this;
  659. }
  660. setFromMatrix4( m ) {
  661. const me = m.elements;
  662. this.set(
  663. me[ 0 ], me[ 4 ], me[ 8 ],
  664. me[ 1 ], me[ 5 ], me[ 9 ],
  665. me[ 2 ], me[ 6 ], me[ 10 ]
  666. );
  667. return this;
  668. }
  669. multiply( m ) {
  670. return this.multiplyMatrices( this, m );
  671. }
  672. premultiply( m ) {
  673. return this.multiplyMatrices( m, this );
  674. }
  675. multiplyMatrices( a, b ) {
  676. const ae = a.elements;
  677. const be = b.elements;
  678. const te = this.elements;
  679. const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
  680. const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
  681. const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
  682. const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
  683. const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
  684. const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
  685. te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
  686. te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
  687. te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
  688. te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
  689. te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
  690. te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
  691. te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
  692. te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
  693. te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
  694. return this;
  695. }
  696. multiplyScalar( s ) {
  697. const te = this.elements;
  698. te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
  699. te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
  700. te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
  701. return this;
  702. }
  703. determinant() {
  704. const te = this.elements;
  705. const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
  706. d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
  707. g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
  708. return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
  709. }
  710. invert() {
  711. const te = this.elements,
  712. n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
  713. n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
  714. n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
  715. t11 = n33 * n22 - n32 * n23,
  716. t12 = n32 * n13 - n33 * n12,
  717. t13 = n23 * n12 - n22 * n13,
  718. det = n11 * t11 + n21 * t12 + n31 * t13;
  719. if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
  720. const detInv = 1 / det;
  721. te[ 0 ] = t11 * detInv;
  722. te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
  723. te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
  724. te[ 3 ] = t12 * detInv;
  725. te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
  726. te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
  727. te[ 6 ] = t13 * detInv;
  728. te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
  729. te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
  730. return this;
  731. }
  732. transpose() {
  733. let tmp;
  734. const m = this.elements;
  735. tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
  736. tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
  737. tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
  738. return this;
  739. }
  740. getNormalMatrix( matrix4 ) {
  741. return this.setFromMatrix4( matrix4 ).copy( this ).invert().transpose();
  742. }
  743. transposeIntoArray( r ) {
  744. const m = this.elements;
  745. r[ 0 ] = m[ 0 ];
  746. r[ 1 ] = m[ 3 ];
  747. r[ 2 ] = m[ 6 ];
  748. r[ 3 ] = m[ 1 ];
  749. r[ 4 ] = m[ 4 ];
  750. r[ 5 ] = m[ 7 ];
  751. r[ 6 ] = m[ 2 ];
  752. r[ 7 ] = m[ 5 ];
  753. r[ 8 ] = m[ 8 ];
  754. return this;
  755. }
  756. setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
  757. const c = Math.cos( rotation );
  758. const s = Math.sin( rotation );
  759. this.set(
  760. sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
  761. - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
  762. 0, 0, 1
  763. );
  764. return this;
  765. }
  766. scale( sx, sy ) {
  767. const te = this.elements;
  768. te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
  769. te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
  770. return this;
  771. }
  772. rotate( theta ) {
  773. const c = Math.cos( theta );
  774. const s = Math.sin( theta );
  775. const te = this.elements;
  776. const a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
  777. const a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
  778. te[ 0 ] = c * a11 + s * a21;
  779. te[ 3 ] = c * a12 + s * a22;
  780. te[ 6 ] = c * a13 + s * a23;
  781. te[ 1 ] = - s * a11 + c * a21;
  782. te[ 4 ] = - s * a12 + c * a22;
  783. te[ 7 ] = - s * a13 + c * a23;
  784. return this;
  785. }
  786. translate( tx, ty ) {
  787. const te = this.elements;
  788. te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
  789. te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
  790. return this;
  791. }
  792. equals( matrix ) {
  793. const te = this.elements;
  794. const me = matrix.elements;
  795. for ( let i = 0; i < 9; i ++ ) {
  796. if ( te[ i ] !== me[ i ] ) return false;
  797. }
  798. return true;
  799. }
  800. fromArray( array, offset = 0 ) {
  801. for ( let i = 0; i < 9; i ++ ) {
  802. this.elements[ i ] = array[ i + offset ];
  803. }
  804. return this;
  805. }
  806. toArray( array = [], offset = 0 ) {
  807. const te = this.elements;
  808. array[ offset ] = te[ 0 ];
  809. array[ offset + 1 ] = te[ 1 ];
  810. array[ offset + 2 ] = te[ 2 ];
  811. array[ offset + 3 ] = te[ 3 ];
  812. array[ offset + 4 ] = te[ 4 ];
  813. array[ offset + 5 ] = te[ 5 ];
  814. array[ offset + 6 ] = te[ 6 ];
  815. array[ offset + 7 ] = te[ 7 ];
  816. array[ offset + 8 ] = te[ 8 ];
  817. return array;
  818. }
  819. }
  820. let _canvas;
  821. const ImageUtils = {
  822. getDataURL: function ( image ) {
  823. if ( /^data:/i.test( image.src ) ) {
  824. return image.src;
  825. }
  826. if ( typeof HTMLCanvasElement == 'undefined' ) {
  827. return image.src;
  828. }
  829. let canvas;
  830. if ( image instanceof HTMLCanvasElement ) {
  831. canvas = image;
  832. } else {
  833. if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
  834. _canvas.width = image.width;
  835. _canvas.height = image.height;
  836. const context = _canvas.getContext( '2d' );
  837. if ( image instanceof ImageData ) {
  838. context.putImageData( image, 0, 0 );
  839. } else {
  840. context.drawImage( image, 0, 0, image.width, image.height );
  841. }
  842. canvas = _canvas;
  843. }
  844. if ( canvas.width > 2048 || canvas.height > 2048 ) {
  845. return canvas.toDataURL( 'image/jpeg', 0.6 );
  846. } else {
  847. return canvas.toDataURL( 'image/png' );
  848. }
  849. }
  850. };
  851. let textureId = 0;
  852. function Texture( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding ) {
  853. Object.defineProperty( this, 'id', { value: textureId ++ } );
  854. this.uuid = MathUtils$1.generateUUID();
  855. this.name = '';
  856. this.image = image;
  857. this.mipmaps = [];
  858. this.mapping = mapping;
  859. this.wrapS = wrapS;
  860. this.wrapT = wrapT;
  861. this.magFilter = magFilter;
  862. this.minFilter = minFilter;
  863. this.anisotropy = anisotropy;
  864. this.format = format;
  865. this.internalFormat = null;
  866. this.type = type;
  867. this.offset = new Vector2( 0, 0 );
  868. this.repeat = new Vector2( 1, 1 );
  869. this.center = new Vector2( 0, 0 );
  870. this.rotation = 0;
  871. this.matrixAutoUpdate = true;
  872. this.matrix = new Matrix3();
  873. this.generateMipmaps = true;
  874. this.premultiplyAlpha = false;
  875. this.flipY = true;
  876. this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
  877. // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
  878. //
  879. // Also changing the encoding after already used by a Material will not automatically make the Material
  880. // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
  881. this.encoding = encoding;
  882. this.version = 0;
  883. this.onUpdate = null;
  884. }
  885. Texture.DEFAULT_IMAGE = undefined;
  886. Texture.DEFAULT_MAPPING = UVMapping;
  887. Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
  888. constructor: Texture,
  889. isTexture: true,
  890. updateMatrix: function () {
  891. this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
  892. },
  893. clone: function () {
  894. return new this.constructor().copy( this );
  895. },
  896. copy: function ( source ) {
  897. this.name = source.name;
  898. this.image = source.image;
  899. this.mipmaps = source.mipmaps.slice( 0 );
  900. this.mapping = source.mapping;
  901. this.wrapS = source.wrapS;
  902. this.wrapT = source.wrapT;
  903. this.magFilter = source.magFilter;
  904. this.minFilter = source.minFilter;
  905. this.anisotropy = source.anisotropy;
  906. this.format = source.format;
  907. this.internalFormat = source.internalFormat;
  908. this.type = source.type;
  909. this.offset.copy( source.offset );
  910. this.repeat.copy( source.repeat );
  911. this.center.copy( source.center );
  912. this.rotation = source.rotation;
  913. this.matrixAutoUpdate = source.matrixAutoUpdate;
  914. this.matrix.copy( source.matrix );
  915. this.generateMipmaps = source.generateMipmaps;
  916. this.premultiplyAlpha = source.premultiplyAlpha;
  917. this.flipY = source.flipY;
  918. this.unpackAlignment = source.unpackAlignment;
  919. this.encoding = source.encoding;
  920. return this;
  921. },
  922. toJSON: function ( meta ) {
  923. const isRootObject = ( meta === undefined || typeof meta === 'string' );
  924. if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
  925. return meta.textures[ this.uuid ];
  926. }
  927. const output = {
  928. metadata: {
  929. version: 4.5,
  930. type: 'Texture',
  931. generator: 'Texture.toJSON'
  932. },
  933. uuid: this.uuid,
  934. name: this.name,
  935. mapping: this.mapping,
  936. repeat: [ this.repeat.x, this.repeat.y ],
  937. offset: [ this.offset.x, this.offset.y ],
  938. center: [ this.center.x, this.center.y ],
  939. rotation: this.rotation,
  940. wrap: [ this.wrapS, this.wrapT ],
  941. format: this.format,
  942. type: this.type,
  943. encoding: this.encoding,
  944. minFilter: this.minFilter,
  945. magFilter: this.magFilter,
  946. anisotropy: this.anisotropy,
  947. flipY: this.flipY,
  948. premultiplyAlpha: this.premultiplyAlpha,
  949. unpackAlignment: this.unpackAlignment
  950. };
  951. if ( this.image !== undefined ) {
  952. // TODO: Move to THREE.Image
  953. const image = this.image;
  954. if ( image.uuid === undefined ) {
  955. image.uuid = MathUtils$1.generateUUID(); // UGH
  956. }
  957. if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
  958. let url;
  959. if ( Array.isArray( image ) ) {
  960. // process array of images e.g. CubeTexture
  961. url = [];
  962. for ( let i = 0, l = image.length; i < l; i ++ ) {
  963. // check cube texture with data textures
  964. if ( image[ i ].isDataTexture ) {
  965. url.push( serializeImage( image[ i ].image ) );
  966. } else {
  967. url.push( serializeImage( image[ i ] ) );
  968. }
  969. }
  970. } else {
  971. // process single image
  972. url = serializeImage( image );
  973. }
  974. meta.images[ image.uuid ] = {
  975. uuid: image.uuid,
  976. url: url
  977. };
  978. }
  979. output.image = image.uuid;
  980. }
  981. if ( ! isRootObject ) {
  982. meta.textures[ this.uuid ] = output;
  983. }
  984. return output;
  985. },
  986. dispose: function () {
  987. this.dispatchEvent( { type: 'dispose' } );
  988. },
  989. transformUv: function ( uv ) {
  990. if ( this.mapping !== UVMapping ) return uv;
  991. uv.applyMatrix3( this.matrix );
  992. if ( uv.x < 0 || uv.x > 1 ) {
  993. switch ( this.wrapS ) {
  994. case RepeatWrapping:
  995. uv.x = uv.x - Math.floor( uv.x );
  996. break;
  997. case ClampToEdgeWrapping:
  998. uv.x = uv.x < 0 ? 0 : 1;
  999. break;
  1000. case MirroredRepeatWrapping:
  1001. if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
  1002. uv.x = Math.ceil( uv.x ) - uv.x;
  1003. } else {
  1004. uv.x = uv.x - Math.floor( uv.x );
  1005. }
  1006. break;
  1007. }
  1008. }
  1009. if ( uv.y < 0 || uv.y > 1 ) {
  1010. switch ( this.wrapT ) {
  1011. case RepeatWrapping:
  1012. uv.y = uv.y - Math.floor( uv.y );
  1013. break;
  1014. case ClampToEdgeWrapping:
  1015. uv.y = uv.y < 0 ? 0 : 1;
  1016. break;
  1017. case MirroredRepeatWrapping:
  1018. if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
  1019. uv.y = Math.ceil( uv.y ) - uv.y;
  1020. } else {
  1021. uv.y = uv.y - Math.floor( uv.y );
  1022. }
  1023. break;
  1024. }
  1025. }
  1026. if ( this.flipY ) {
  1027. uv.y = 1 - uv.y;
  1028. }
  1029. return uv;
  1030. }
  1031. } );
  1032. Object.defineProperty( Texture.prototype, 'needsUpdate', {
  1033. set: function ( value ) {
  1034. if ( value === true ) this.version ++;
  1035. }
  1036. } );
  1037. function serializeImage( image ) {
  1038. if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
  1039. ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
  1040. ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
  1041. // default images
  1042. return ImageUtils.getDataURL( image );
  1043. } else {
  1044. if ( image.data ) {
  1045. // images of DataTexture
  1046. return {
  1047. data: Array.prototype.slice.call( image.data ),
  1048. width: image.width,
  1049. height: image.height,
  1050. type: image.data.constructor.name
  1051. };
  1052. } else {
  1053. console.warn( 'THREE.Texture: Unable to serialize Texture.' );
  1054. return {};
  1055. }
  1056. }
  1057. }
  1058. class Vector4 {
  1059. constructor( x = 0, y = 0, z = 0, w = 1 ) {
  1060. Object.defineProperty( this, 'isVector4', { value: true } );
  1061. this.x = x;
  1062. this.y = y;
  1063. this.z = z;
  1064. this.w = w;
  1065. }
  1066. get width() {
  1067. return this.z;
  1068. }
  1069. set width( value ) {
  1070. this.z = value;
  1071. }
  1072. get height() {
  1073. return this.w;
  1074. }
  1075. set height( value ) {
  1076. this.w = value;
  1077. }
  1078. set( x, y, z, w ) {
  1079. this.x = x;
  1080. this.y = y;
  1081. this.z = z;
  1082. this.w = w;
  1083. return this;
  1084. }
  1085. setScalar( scalar ) {
  1086. this.x = scalar;
  1087. this.y = scalar;
  1088. this.z = scalar;
  1089. this.w = scalar;
  1090. return this;
  1091. }
  1092. setX( x ) {
  1093. this.x = x;
  1094. return this;
  1095. }
  1096. setY( y ) {
  1097. this.y = y;
  1098. return this;
  1099. }
  1100. setZ( z ) {
  1101. this.z = z;
  1102. return this;
  1103. }
  1104. setW( w ) {
  1105. this.w = w;
  1106. return this;
  1107. }
  1108. setComponent( index, value ) {
  1109. switch ( index ) {
  1110. case 0: this.x = value; break;
  1111. case 1: this.y = value; break;
  1112. case 2: this.z = value; break;
  1113. case 3: this.w = value; break;
  1114. default: throw new Error( 'index is out of range: ' + index );
  1115. }
  1116. return this;
  1117. }
  1118. getComponent( index ) {
  1119. switch ( index ) {
  1120. case 0: return this.x;
  1121. case 1: return this.y;
  1122. case 2: return this.z;
  1123. case 3: return this.w;
  1124. default: throw new Error( 'index is out of range: ' + index );
  1125. }
  1126. }
  1127. clone() {
  1128. return new this.constructor( this.x, this.y, this.z, this.w );
  1129. }
  1130. copy( v ) {
  1131. this.x = v.x;
  1132. this.y = v.y;
  1133. this.z = v.z;
  1134. this.w = ( v.w !== undefined ) ? v.w : 1;
  1135. return this;
  1136. }
  1137. add( v, w ) {
  1138. if ( w !== undefined ) {
  1139. console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
  1140. return this.addVectors( v, w );
  1141. }
  1142. this.x += v.x;
  1143. this.y += v.y;
  1144. this.z += v.z;
  1145. this.w += v.w;
  1146. return this;
  1147. }
  1148. addScalar( s ) {
  1149. this.x += s;
  1150. this.y += s;
  1151. this.z += s;
  1152. this.w += s;
  1153. return this;
  1154. }
  1155. addVectors( a, b ) {
  1156. this.x = a.x + b.x;
  1157. this.y = a.y + b.y;
  1158. this.z = a.z + b.z;
  1159. this.w = a.w + b.w;
  1160. return this;
  1161. }
  1162. addScaledVector( v, s ) {
  1163. this.x += v.x * s;
  1164. this.y += v.y * s;
  1165. this.z += v.z * s;
  1166. this.w += v.w * s;
  1167. return this;
  1168. }
  1169. sub( v, w ) {
  1170. if ( w !== undefined ) {
  1171. console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
  1172. return this.subVectors( v, w );
  1173. }
  1174. this.x -= v.x;
  1175. this.y -= v.y;
  1176. this.z -= v.z;
  1177. this.w -= v.w;
  1178. return this;
  1179. }
  1180. subScalar( s ) {
  1181. this.x -= s;
  1182. this.y -= s;
  1183. this.z -= s;
  1184. this.w -= s;
  1185. return this;
  1186. }
  1187. subVectors( a, b ) {
  1188. this.x = a.x - b.x;
  1189. this.y = a.y - b.y;
  1190. this.z = a.z - b.z;
  1191. this.w = a.w - b.w;
  1192. return this;
  1193. }
  1194. multiplyScalar( scalar ) {
  1195. this.x *= scalar;
  1196. this.y *= scalar;
  1197. this.z *= scalar;
  1198. this.w *= scalar;
  1199. return this;
  1200. }
  1201. applyMatrix4( m ) {
  1202. const x = this.x, y = this.y, z = this.z, w = this.w;
  1203. const e = m.elements;
  1204. this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
  1205. this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
  1206. this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
  1207. this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
  1208. return this;
  1209. }
  1210. divideScalar( scalar ) {
  1211. return this.multiplyScalar( 1 / scalar );
  1212. }
  1213. setAxisAngleFromQuaternion( q ) {
  1214. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
  1215. // q is assumed to be normalized
  1216. this.w = 2 * Math.acos( q.w );
  1217. const s = Math.sqrt( 1 - q.w * q.w );
  1218. if ( s < 0.0001 ) {
  1219. this.x = 1;
  1220. this.y = 0;
  1221. this.z = 0;
  1222. } else {
  1223. this.x = q.x / s;
  1224. this.y = q.y / s;
  1225. this.z = q.z / s;
  1226. }
  1227. return this;
  1228. }
  1229. setAxisAngleFromRotationMatrix( m ) {
  1230. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
  1231. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  1232. let angle, x, y, z; // variables for result
  1233. const epsilon = 0.01, // margin to allow for rounding errors
  1234. epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
  1235. te = m.elements,
  1236. m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
  1237. m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
  1238. m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
  1239. if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
  1240. ( Math.abs( m13 - m31 ) < epsilon ) &&
  1241. ( Math.abs( m23 - m32 ) < epsilon ) ) {
  1242. // singularity found
  1243. // first check for identity matrix which must have +1 for all terms
  1244. // in leading diagonal and zero in other terms
  1245. if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
  1246. ( Math.abs( m13 + m31 ) < epsilon2 ) &&
  1247. ( Math.abs( m23 + m32 ) < epsilon2 ) &&
  1248. ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
  1249. // this singularity is identity matrix so angle = 0
  1250. this.set( 1, 0, 0, 0 );
  1251. return this; // zero angle, arbitrary axis
  1252. }
  1253. // otherwise this singularity is angle = 180
  1254. angle = Math.PI;
  1255. const xx = ( m11 + 1 ) / 2;
  1256. const yy = ( m22 + 1 ) / 2;
  1257. const zz = ( m33 + 1 ) / 2;
  1258. const xy = ( m12 + m21 ) / 4;
  1259. const xz = ( m13 + m31 ) / 4;
  1260. const yz = ( m23 + m32 ) / 4;
  1261. if ( ( xx > yy ) && ( xx > zz ) ) {
  1262. // m11 is the largest diagonal term
  1263. if ( xx < epsilon ) {
  1264. x = 0;
  1265. y = 0.707106781;
  1266. z = 0.707106781;
  1267. } else {
  1268. x = Math.sqrt( xx );
  1269. y = xy / x;
  1270. z = xz / x;
  1271. }
  1272. } else if ( yy > zz ) {
  1273. // m22 is the largest diagonal term
  1274. if ( yy < epsilon ) {
  1275. x = 0.707106781;
  1276. y = 0;
  1277. z = 0.707106781;
  1278. } else {
  1279. y = Math.sqrt( yy );
  1280. x = xy / y;
  1281. z = yz / y;
  1282. }
  1283. } else {
  1284. // m33 is the largest diagonal term so base result on this
  1285. if ( zz < epsilon ) {
  1286. x = 0.707106781;
  1287. y = 0.707106781;
  1288. z = 0;
  1289. } else {
  1290. z = Math.sqrt( zz );
  1291. x = xz / z;
  1292. y = yz / z;
  1293. }
  1294. }
  1295. this.set( x, y, z, angle );
  1296. return this; // return 180 deg rotation
  1297. }
  1298. // as we have reached here there are no singularities so we can handle normally
  1299. let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
  1300. ( m13 - m31 ) * ( m13 - m31 ) +
  1301. ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
  1302. if ( Math.abs( s ) < 0.001 ) s = 1;
  1303. // prevent divide by zero, should not happen if matrix is orthogonal and should be
  1304. // caught by singularity test above, but I've left it in just in case
  1305. this.x = ( m32 - m23 ) / s;
  1306. this.y = ( m13 - m31 ) / s;
  1307. this.z = ( m21 - m12 ) / s;
  1308. this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
  1309. return this;
  1310. }
  1311. min( v ) {
  1312. this.x = Math.min( this.x, v.x );
  1313. this.y = Math.min( this.y, v.y );
  1314. this.z = Math.min( this.z, v.z );
  1315. this.w = Math.min( this.w, v.w );
  1316. return this;
  1317. }
  1318. max( v ) {
  1319. this.x = Math.max( this.x, v.x );
  1320. this.y = Math.max( this.y, v.y );
  1321. this.z = Math.max( this.z, v.z );
  1322. this.w = Math.max( this.w, v.w );
  1323. return this;
  1324. }
  1325. clamp( min, max ) {
  1326. // assumes min < max, componentwise
  1327. this.x = Math.max( min.x, Math.min( max.x, this.x ) );
  1328. this.y = Math.max( min.y, Math.min( max.y, this.y ) );
  1329. this.z = Math.max( min.z, Math.min( max.z, this.z ) );
  1330. this.w = Math.max( min.w, Math.min( max.w, this.w ) );
  1331. return this;
  1332. }
  1333. clampScalar( minVal, maxVal ) {
  1334. this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
  1335. this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
  1336. this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
  1337. this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
  1338. return this;
  1339. }
  1340. clampLength( min, max ) {
  1341. const length = this.length();
  1342. return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
  1343. }
  1344. floor() {
  1345. this.x = Math.floor( this.x );
  1346. this.y = Math.floor( this.y );
  1347. this.z = Math.floor( this.z );
  1348. this.w = Math.floor( this.w );
  1349. return this;
  1350. }
  1351. ceil() {
  1352. this.x = Math.ceil( this.x );
  1353. this.y = Math.ceil( this.y );
  1354. this.z = Math.ceil( this.z );
  1355. this.w = Math.ceil( this.w );
  1356. return this;
  1357. }
  1358. round() {
  1359. this.x = Math.round( this.x );
  1360. this.y = Math.round( this.y );
  1361. this.z = Math.round( this.z );
  1362. this.w = Math.round( this.w );
  1363. return this;
  1364. }
  1365. roundToZero() {
  1366. this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
  1367. this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
  1368. this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
  1369. this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
  1370. return this;
  1371. }
  1372. negate() {
  1373. this.x = - this.x;
  1374. this.y = - this.y;
  1375. this.z = - this.z;
  1376. this.w = - this.w;
  1377. return this;
  1378. }
  1379. dot( v ) {
  1380. return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
  1381. }
  1382. lengthSq() {
  1383. return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
  1384. }
  1385. length() {
  1386. return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
  1387. }
  1388. manhattanLength() {
  1389. return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
  1390. }
  1391. normalize() {
  1392. return this.divideScalar( this.length() || 1 );
  1393. }
  1394. setLength( length ) {
  1395. return this.normalize().multiplyScalar( length );
  1396. }
  1397. lerp( v, alpha ) {
  1398. this.x += ( v.x - this.x ) * alpha;
  1399. this.y += ( v.y - this.y ) * alpha;
  1400. this.z += ( v.z - this.z ) * alpha;
  1401. this.w += ( v.w - this.w ) * alpha;
  1402. return this;
  1403. }
  1404. lerpVectors( v1, v2, alpha ) {
  1405. this.x = v1.x + ( v2.x - v1.x ) * alpha;
  1406. this.y = v1.y + ( v2.y - v1.y ) * alpha;
  1407. this.z = v1.z + ( v2.z - v1.z ) * alpha;
  1408. this.w = v1.w + ( v2.w - v1.w ) * alpha;
  1409. return this;
  1410. }
  1411. equals( v ) {
  1412. return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
  1413. }
  1414. fromArray( array, offset = 0 ) {
  1415. this.x = array[ offset ];
  1416. this.y = array[ offset + 1 ];
  1417. this.z = array[ offset + 2 ];
  1418. this.w = array[ offset + 3 ];
  1419. return this;
  1420. }
  1421. toArray( array = [], offset = 0 ) {
  1422. array[ offset ] = this.x;
  1423. array[ offset + 1 ] = this.y;
  1424. array[ offset + 2 ] = this.z;
  1425. array[ offset + 3 ] = this.w;
  1426. return array;
  1427. }
  1428. fromBufferAttribute( attribute, index, offset ) {
  1429. if ( offset !== undefined ) {
  1430. console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
  1431. }
  1432. this.x = attribute.getX( index );
  1433. this.y = attribute.getY( index );
  1434. this.z = attribute.getZ( index );
  1435. this.w = attribute.getW( index );
  1436. return this;
  1437. }
  1438. random() {
  1439. this.x = Math.random();
  1440. this.y = Math.random();
  1441. this.z = Math.random();
  1442. this.w = Math.random();
  1443. return this;
  1444. }
  1445. }
  1446. /*
  1447. In options, we can specify:
  1448. * Texture parameters for an auto-generated target texture
  1449. * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
  1450. */
  1451. function WebGLRenderTarget( width, height, options ) {
  1452. this.width = width;
  1453. this.height = height;
  1454. this.scissor = new Vector4( 0, 0, width, height );
  1455. this.scissorTest = false;
  1456. this.viewport = new Vector4( 0, 0, width, height );
  1457. options = options || {};
  1458. this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
  1459. this.texture.image = {};
  1460. this.texture.image.width = width;
  1461. this.texture.image.height = height;
  1462. this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
  1463. this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
  1464. this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
  1465. this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
  1466. this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
  1467. }
  1468. WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
  1469. constructor: WebGLRenderTarget,
  1470. isWebGLRenderTarget: true,
  1471. setSize: function ( width, height ) {
  1472. if ( this.width !== width || this.height !== height ) {
  1473. this.width = width;
  1474. this.height = height;
  1475. this.texture.image.width = width;
  1476. this.texture.image.height = height;
  1477. this.dispose();
  1478. }
  1479. this.viewport.set( 0, 0, width, height );
  1480. this.scissor.set( 0, 0, width, height );
  1481. },
  1482. clone: function () {
  1483. return new this.constructor().copy( this );
  1484. },
  1485. copy: function ( source ) {
  1486. this.width = source.width;
  1487. this.height = source.height;
  1488. this.viewport.copy( source.viewport );
  1489. this.texture = source.texture.clone();
  1490. this.depthBuffer = source.depthBuffer;
  1491. this.stencilBuffer = source.stencilBuffer;
  1492. this.depthTexture = source.depthTexture;
  1493. return this;
  1494. },
  1495. dispose: function () {
  1496. this.dispatchEvent( { type: 'dispose' } );
  1497. }
  1498. } );
  1499. function WebGLMultisampleRenderTarget( width, height, options ) {
  1500. WebGLRenderTarget.call( this, width, height, options );
  1501. this.samples = 4;
  1502. }
  1503. WebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {
  1504. constructor: WebGLMultisampleRenderTarget,
  1505. isWebGLMultisampleRenderTarget: true,
  1506. copy: function ( source ) {
  1507. WebGLRenderTarget.prototype.copy.call( this, source );
  1508. this.samples = source.samples;
  1509. return this;
  1510. }
  1511. } );
  1512. class Quaternion {
  1513. constructor( x = 0, y = 0, z = 0, w = 1 ) {
  1514. Object.defineProperty( this, 'isQuaternion', { value: true } );
  1515. this._x = x;
  1516. this._y = y;
  1517. this._z = z;
  1518. this._w = w;
  1519. }
  1520. static slerp( qa, qb, qm, t ) {
  1521. return qm.copy( qa ).slerp( qb, t );
  1522. }
  1523. static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
  1524. // fuzz-free, array-based Quaternion SLERP operation
  1525. let x0 = src0[ srcOffset0 + 0 ],
  1526. y0 = src0[ srcOffset0 + 1 ],
  1527. z0 = src0[ srcOffset0 + 2 ],
  1528. w0 = src0[ srcOffset0 + 3 ];
  1529. const x1 = src1[ srcOffset1 + 0 ],
  1530. y1 = src1[ srcOffset1 + 1 ],
  1531. z1 = src1[ srcOffset1 + 2 ],
  1532. w1 = src1[ srcOffset1 + 3 ];
  1533. if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
  1534. let s = 1 - t;
  1535. const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
  1536. dir = ( cos >= 0 ? 1 : - 1 ),
  1537. sqrSin = 1 - cos * cos;
  1538. // Skip the Slerp for tiny steps to avoid numeric problems:
  1539. if ( sqrSin > Number.EPSILON ) {
  1540. const sin = Math.sqrt( sqrSin ),
  1541. len = Math.atan2( sin, cos * dir );
  1542. s = Math.sin( s * len ) / sin;
  1543. t = Math.sin( t * len ) / sin;
  1544. }
  1545. const tDir = t * dir;
  1546. x0 = x0 * s + x1 * tDir;
  1547. y0 = y0 * s + y1 * tDir;
  1548. z0 = z0 * s + z1 * tDir;
  1549. w0 = w0 * s + w1 * tDir;
  1550. // Normalize in case we just did a lerp:
  1551. if ( s === 1 - t ) {
  1552. const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
  1553. x0 *= f;
  1554. y0 *= f;
  1555. z0 *= f;
  1556. w0 *= f;
  1557. }
  1558. }
  1559. dst[ dstOffset ] = x0;
  1560. dst[ dstOffset + 1 ] = y0;
  1561. dst[ dstOffset + 2 ] = z0;
  1562. dst[ dstOffset + 3 ] = w0;
  1563. }
  1564. static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
  1565. const x0 = src0[ srcOffset0 ];
  1566. const y0 = src0[ srcOffset0 + 1 ];
  1567. const z0 = src0[ srcOffset0 + 2 ];
  1568. const w0 = src0[ srcOffset0 + 3 ];
  1569. const x1 = src1[ srcOffset1 ];
  1570. const y1 = src1[ srcOffset1 + 1 ];
  1571. const z1 = src1[ srcOffset1 + 2 ];
  1572. const w1 = src1[ srcOffset1 + 3 ];
  1573. dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
  1574. dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
  1575. dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
  1576. dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
  1577. return dst;
  1578. }
  1579. get x() {
  1580. return this._x;
  1581. }
  1582. set x( value ) {
  1583. this._x = value;
  1584. this._onChangeCallback();
  1585. }
  1586. get y() {
  1587. return this._y;
  1588. }
  1589. set y( value ) {
  1590. this._y = value;
  1591. this._onChangeCallback();
  1592. }
  1593. get z() {
  1594. return this._z;
  1595. }
  1596. set z( value ) {
  1597. this._z = value;
  1598. this._onChangeCallback();
  1599. }
  1600. get w() {
  1601. return this._w;
  1602. }
  1603. set w( value ) {
  1604. this._w = value;
  1605. this._onChangeCallback();
  1606. }
  1607. set( x, y, z, w ) {
  1608. this._x = x;
  1609. this._y = y;
  1610. this._z = z;
  1611. this._w = w;
  1612. this._onChangeCallback();
  1613. return this;
  1614. }
  1615. clone() {
  1616. return new this.constructor( this._x, this._y, this._z, this._w );
  1617. }
  1618. copy( quaternion ) {
  1619. this._x = quaternion.x;
  1620. this._y = quaternion.y;
  1621. this._z = quaternion.z;
  1622. this._w = quaternion.w;
  1623. this._onChangeCallback();
  1624. return this;
  1625. }
  1626. setFromEuler( euler, update ) {
  1627. if ( ! ( euler && euler.isEuler ) ) {
  1628. throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
  1629. }
  1630. const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
  1631. // http://www.mathworks.com/matlabcentral/fileexchange/
  1632. // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
  1633. // content/SpinCalc.m
  1634. const cos = Math.cos;
  1635. const sin = Math.sin;
  1636. const c1 = cos( x / 2 );
  1637. const c2 = cos( y / 2 );
  1638. const c3 = cos( z / 2 );
  1639. const s1 = sin( x / 2 );
  1640. const s2 = sin( y / 2 );
  1641. const s3 = sin( z / 2 );
  1642. switch ( order ) {
  1643. case 'XYZ':
  1644. this._x = s1 * c2 * c3 + c1 * s2 * s3;
  1645. this._y = c1 * s2 * c3 - s1 * c2 * s3;
  1646. this._z = c1 * c2 * s3 + s1 * s2 * c3;
  1647. this._w = c1 * c2 * c3 - s1 * s2 * s3;
  1648. break;
  1649. case 'YXZ':
  1650. this._x = s1 * c2 * c3 + c1 * s2 * s3;
  1651. this._y = c1 * s2 * c3 - s1 * c2 * s3;
  1652. this._z = c1 * c2 * s3 - s1 * s2 * c3;
  1653. this._w = c1 * c2 * c3 + s1 * s2 * s3;
  1654. break;
  1655. case 'ZXY':
  1656. this._x = s1 * c2 * c3 - c1 * s2 * s3;
  1657. this._y = c1 * s2 * c3 + s1 * c2 * s3;
  1658. this._z = c1 * c2 * s3 + s1 * s2 * c3;
  1659. this._w = c1 * c2 * c3 - s1 * s2 * s3;
  1660. break;
  1661. case 'ZYX':
  1662. this._x = s1 * c2 * c3 - c1 * s2 * s3;
  1663. this._y = c1 * s2 * c3 + s1 * c2 * s3;
  1664. this._z = c1 * c2 * s3 - s1 * s2 * c3;
  1665. this._w = c1 * c2 * c3 + s1 * s2 * s3;
  1666. break;
  1667. case 'YZX':
  1668. this._x = s1 * c2 * c3 + c1 * s2 * s3;
  1669. this._y = c1 * s2 * c3 + s1 * c2 * s3;
  1670. this._z = c1 * c2 * s3 - s1 * s2 * c3;
  1671. this._w = c1 * c2 * c3 - s1 * s2 * s3;
  1672. break;
  1673. case 'XZY':
  1674. this._x = s1 * c2 * c3 - c1 * s2 * s3;
  1675. this._y = c1 * s2 * c3 - s1 * c2 * s3;
  1676. this._z = c1 * c2 * s3 + s1 * s2 * c3;
  1677. this._w = c1 * c2 * c3 + s1 * s2 * s3;
  1678. break;
  1679. default:
  1680. console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
  1681. }
  1682. if ( update !== false ) this._onChangeCallback();
  1683. return this;
  1684. }
  1685. setFromAxisAngle( axis, angle ) {
  1686. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
  1687. // assumes axis is normalized
  1688. const halfAngle = angle / 2, s = Math.sin( halfAngle );
  1689. this._x = axis.x * s;
  1690. this._y = axis.y * s;
  1691. this._z = axis.z * s;
  1692. this._w = Math.cos( halfAngle );
  1693. this._onChangeCallback();
  1694. return this;
  1695. }
  1696. setFromRotationMatrix( m ) {
  1697. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
  1698. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  1699. const te = m.elements,
  1700. m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
  1701. m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
  1702. m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
  1703. trace = m11 + m22 + m33;
  1704. if ( trace > 0 ) {
  1705. const s = 0.5 / Math.sqrt( trace + 1.0 );
  1706. this._w = 0.25 / s;
  1707. this._x = ( m32 - m23 ) * s;
  1708. this._y = ( m13 - m31 ) * s;
  1709. this._z = ( m21 - m12 ) * s;
  1710. } else if ( m11 > m22 && m11 > m33 ) {
  1711. const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
  1712. this._w = ( m32 - m23 ) / s;
  1713. this._x = 0.25 * s;
  1714. this._y = ( m12 + m21 ) / s;
  1715. this._z = ( m13 + m31 ) / s;
  1716. } else if ( m22 > m33 ) {
  1717. const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
  1718. this._w = ( m13 - m31 ) / s;
  1719. this._x = ( m12 + m21 ) / s;
  1720. this._y = 0.25 * s;
  1721. this._z = ( m23 + m32 ) / s;
  1722. } else {
  1723. const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
  1724. this._w = ( m21 - m12 ) / s;
  1725. this._x = ( m13 + m31 ) / s;
  1726. this._y = ( m23 + m32 ) / s;
  1727. this._z = 0.25 * s;
  1728. }
  1729. this._onChangeCallback();
  1730. return this;
  1731. }
  1732. setFromUnitVectors( vFrom, vTo ) {
  1733. // assumes direction vectors vFrom and vTo are normalized
  1734. const EPS = 0.000001;
  1735. let r = vFrom.dot( vTo ) + 1;
  1736. if ( r < EPS ) {
  1737. r = 0;
  1738. if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
  1739. this._x = - vFrom.y;
  1740. this._y = vFrom.x;
  1741. this._z = 0;
  1742. this._w = r;
  1743. } else {
  1744. this._x = 0;
  1745. this._y = - vFrom.z;
  1746. this._z = vFrom.y;
  1747. this._w = r;
  1748. }
  1749. } else {
  1750. // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
  1751. this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
  1752. this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
  1753. this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
  1754. this._w = r;
  1755. }
  1756. return this.normalize();
  1757. }
  1758. angleTo( q ) {
  1759. return 2 * Math.acos( Math.abs( MathUtils$1.clamp( this.dot( q ), - 1, 1 ) ) );
  1760. }
  1761. rotateTowards( q, step ) {
  1762. const angle = this.angleTo( q );
  1763. if ( angle === 0 ) return this;
  1764. const t = Math.min( 1, step / angle );
  1765. this.slerp( q, t );
  1766. return this;
  1767. }
  1768. identity() {
  1769. return this.set( 0, 0, 0, 1 );
  1770. }
  1771. invert() {
  1772. // quaternion is assumed to have unit length
  1773. return this.conjugate();
  1774. }
  1775. conjugate() {
  1776. this._x *= - 1;
  1777. this._y *= - 1;
  1778. this._z *= - 1;
  1779. this._onChangeCallback();
  1780. return this;
  1781. }
  1782. dot( v ) {
  1783. return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
  1784. }
  1785. lengthSq() {
  1786. return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
  1787. }
  1788. length() {
  1789. return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
  1790. }
  1791. normalize() {
  1792. let l = this.length();
  1793. if ( l === 0 ) {
  1794. this._x = 0;
  1795. this._y = 0;
  1796. this._z = 0;
  1797. this._w = 1;
  1798. } else {
  1799. l = 1 / l;
  1800. this._x = this._x * l;
  1801. this._y = this._y * l;
  1802. this._z = this._z * l;
  1803. this._w = this._w * l;
  1804. }
  1805. this._onChangeCallback();
  1806. return this;
  1807. }
  1808. multiply( q, p ) {
  1809. if ( p !== undefined ) {
  1810. console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
  1811. return this.multiplyQuaternions( q, p );
  1812. }
  1813. return this.multiplyQuaternions( this, q );
  1814. }
  1815. premultiply( q ) {
  1816. return this.multiplyQuaternions( q, this );
  1817. }
  1818. multiplyQuaternions( a, b ) {
  1819. // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
  1820. const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
  1821. const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
  1822. this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
  1823. this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
  1824. this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
  1825. this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
  1826. this._onChangeCallback();
  1827. return this;
  1828. }
  1829. slerp( qb, t ) {
  1830. if ( t === 0 ) return this;
  1831. if ( t === 1 ) return this.copy( qb );
  1832. const x = this._x, y = this._y, z = this._z, w = this._w;
  1833. // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
  1834. let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
  1835. if ( cosHalfTheta < 0 ) {
  1836. this._w = - qb._w;
  1837. this._x = - qb._x;
  1838. this._y = - qb._y;
  1839. this._z = - qb._z;
  1840. cosHalfTheta = - cosHalfTheta;
  1841. } else {
  1842. this.copy( qb );
  1843. }
  1844. if ( cosHalfTheta >= 1.0 ) {
  1845. this._w = w;
  1846. this._x = x;
  1847. this._y = y;
  1848. this._z = z;
  1849. return this;
  1850. }
  1851. const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
  1852. if ( sqrSinHalfTheta <= Number.EPSILON ) {
  1853. const s = 1 - t;
  1854. this._w = s * w + t * this._w;
  1855. this._x = s * x + t * this._x;
  1856. this._y = s * y + t * this._y;
  1857. this._z = s * z + t * this._z;
  1858. this.normalize();
  1859. this._onChangeCallback();
  1860. return this;
  1861. }
  1862. const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
  1863. const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
  1864. const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
  1865. ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
  1866. this._w = ( w * ratioA + this._w * ratioB );
  1867. this._x = ( x * ratioA + this._x * ratioB );
  1868. this._y = ( y * ratioA + this._y * ratioB );
  1869. this._z = ( z * ratioA + this._z * ratioB );
  1870. this._onChangeCallback();
  1871. return this;
  1872. }
  1873. equals( quaternion ) {
  1874. return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
  1875. }
  1876. fromArray( array, offset = 0 ) {
  1877. this._x = array[ offset ];
  1878. this._y = array[ offset + 1 ];
  1879. this._z = array[ offset + 2 ];
  1880. this._w = array[ offset + 3 ];
  1881. this._onChangeCallback();
  1882. return this;
  1883. }
  1884. toArray( array = [], offset = 0 ) {
  1885. array[ offset ] = this._x;
  1886. array[ offset + 1 ] = this._y;
  1887. array[ offset + 2 ] = this._z;
  1888. array[ offset + 3 ] = this._w;
  1889. return array;
  1890. }
  1891. fromBufferAttribute( attribute, index ) {
  1892. this._x = attribute.getX( index );
  1893. this._y = attribute.getY( index );
  1894. this._z = attribute.getZ( index );
  1895. this._w = attribute.getW( index );
  1896. return this;
  1897. }
  1898. _onChange( callback ) {
  1899. this._onChangeCallback = callback;
  1900. return this;
  1901. }
  1902. _onChangeCallback() {}
  1903. }
  1904. class Vector3 {
  1905. constructor( x = 0, y = 0, z = 0 ) {
  1906. Object.defineProperty( this, 'isVector3', { value: true } );
  1907. this.x = x;
  1908. this.y = y;
  1909. this.z = z;
  1910. }
  1911. set( x, y, z ) {
  1912. if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
  1913. this.x = x;
  1914. this.y = y;
  1915. this.z = z;
  1916. return this;
  1917. }
  1918. setScalar( scalar ) {
  1919. this.x = scalar;
  1920. this.y = scalar;
  1921. this.z = scalar;
  1922. return this;
  1923. }
  1924. setX( x ) {
  1925. this.x = x;
  1926. return this;
  1927. }
  1928. setY( y ) {
  1929. this.y = y;
  1930. return this;
  1931. }
  1932. setZ( z ) {
  1933. this.z = z;
  1934. return this;
  1935. }
  1936. setComponent( index, value ) {
  1937. switch ( index ) {
  1938. case 0: this.x = value; break;
  1939. case 1: this.y = value; break;
  1940. case 2: this.z = value; break;
  1941. default: throw new Error( 'index is out of range: ' + index );
  1942. }
  1943. return this;
  1944. }
  1945. getComponent( index ) {
  1946. switch ( index ) {
  1947. case 0: return this.x;
  1948. case 1: return this.y;
  1949. case 2: return this.z;
  1950. default: throw new Error( 'index is out of range: ' + index );
  1951. }
  1952. }
  1953. clone() {
  1954. return new this.constructor( this.x, this.y, this.z );
  1955. }
  1956. copy( v ) {
  1957. this.x = v.x;
  1958. this.y = v.y;
  1959. this.z = v.z;
  1960. return this;
  1961. }
  1962. add( v, w ) {
  1963. if ( w !== undefined ) {
  1964. console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
  1965. return this.addVectors( v, w );
  1966. }
  1967. this.x += v.x;
  1968. this.y += v.y;
  1969. this.z += v.z;
  1970. return this;
  1971. }
  1972. addScalar( s ) {
  1973. this.x += s;
  1974. this.y += s;
  1975. this.z += s;
  1976. return this;
  1977. }
  1978. addVectors( a, b ) {
  1979. this.x = a.x + b.x;
  1980. this.y = a.y + b.y;
  1981. this.z = a.z + b.z;
  1982. return this;
  1983. }
  1984. addScaledVector( v, s ) {
  1985. this.x += v.x * s;
  1986. this.y += v.y * s;
  1987. this.z += v.z * s;
  1988. return this;
  1989. }
  1990. sub( v, w ) {
  1991. if ( w !== undefined ) {
  1992. console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
  1993. return this.subVectors( v, w );
  1994. }
  1995. this.x -= v.x;
  1996. this.y -= v.y;
  1997. this.z -= v.z;
  1998. return this;
  1999. }
  2000. subScalar( s ) {
  2001. this.x -= s;
  2002. this.y -= s;
  2003. this.z -= s;
  2004. return this;
  2005. }
  2006. subVectors( a, b ) {
  2007. this.x = a.x - b.x;
  2008. this.y = a.y - b.y;
  2009. this.z = a.z - b.z;
  2010. return this;
  2011. }
  2012. multiply( v, w ) {
  2013. if ( w !== undefined ) {
  2014. console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
  2015. return this.multiplyVectors( v, w );
  2016. }
  2017. this.x *= v.x;
  2018. this.y *= v.y;
  2019. this.z *= v.z;
  2020. return this;
  2021. }
  2022. multiplyScalar( scalar ) {
  2023. this.x *= scalar;
  2024. this.y *= scalar;
  2025. this.z *= scalar;
  2026. return this;
  2027. }
  2028. multiplyVectors( a, b ) {
  2029. this.x = a.x * b.x;
  2030. this.y = a.y * b.y;
  2031. this.z = a.z * b.z;
  2032. return this;
  2033. }
  2034. applyEuler( euler ) {
  2035. if ( ! ( euler && euler.isEuler ) ) {
  2036. console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
  2037. }
  2038. return this.applyQuaternion( _quaternion.setFromEuler( euler ) );
  2039. }
  2040. applyAxisAngle( axis, angle ) {
  2041. return this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );
  2042. }
  2043. applyMatrix3( m ) {
  2044. const x = this.x, y = this.y, z = this.z;
  2045. const e = m.elements;
  2046. this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
  2047. this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
  2048. this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
  2049. return this;
  2050. }
  2051. applyNormalMatrix( m ) {
  2052. return this.applyMatrix3( m ).normalize();
  2053. }
  2054. applyMatrix4( m ) {
  2055. const x = this.x, y = this.y, z = this.z;
  2056. const e = m.elements;
  2057. const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
  2058. this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
  2059. this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
  2060. this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
  2061. return this;
  2062. }
  2063. applyQuaternion( q ) {
  2064. const x = this.x, y = this.y, z = this.z;
  2065. const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
  2066. // calculate quat * vector
  2067. const ix = qw * x + qy * z - qz * y;
  2068. const iy = qw * y + qz * x - qx * z;
  2069. const iz = qw * z + qx * y - qy * x;
  2070. const iw = - qx * x - qy * y - qz * z;
  2071. // calculate result * inverse quat
  2072. this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
  2073. this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
  2074. this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
  2075. return this;
  2076. }
  2077. project( camera ) {
  2078. return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
  2079. }
  2080. unproject( camera ) {
  2081. return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
  2082. }
  2083. transformDirection( m ) {
  2084. // input: THREE.Matrix4 affine matrix
  2085. // vector interpreted as a direction
  2086. const x = this.x, y = this.y, z = this.z;
  2087. const e = m.elements;
  2088. this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
  2089. this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
  2090. this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
  2091. return this.normalize();
  2092. }
  2093. divide( v ) {
  2094. this.x /= v.x;
  2095. this.y /= v.y;
  2096. this.z /= v.z;
  2097. return this;
  2098. }
  2099. divideScalar( scalar ) {
  2100. return this.multiplyScalar( 1 / scalar );
  2101. }
  2102. min( v ) {
  2103. this.x = Math.min( this.x, v.x );
  2104. this.y = Math.min( this.y, v.y );
  2105. this.z = Math.min( this.z, v.z );
  2106. return this;
  2107. }
  2108. max( v ) {
  2109. this.x = Math.max( this.x, v.x );
  2110. this.y = Math.max( this.y, v.y );
  2111. this.z = Math.max( this.z, v.z );
  2112. return this;
  2113. }
  2114. clamp( min, max ) {
  2115. // assumes min < max, componentwise
  2116. this.x = Math.max( min.x, Math.min( max.x, this.x ) );
  2117. this.y = Math.max( min.y, Math.min( max.y, this.y ) );
  2118. this.z = Math.max( min.z, Math.min( max.z, this.z ) );
  2119. return this;
  2120. }
  2121. clampScalar( minVal, maxVal ) {
  2122. this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
  2123. this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
  2124. this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
  2125. return this;
  2126. }
  2127. clampLength( min, max ) {
  2128. const length = this.length();
  2129. return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
  2130. }
  2131. floor() {
  2132. this.x = Math.floor( this.x );
  2133. this.y = Math.floor( this.y );
  2134. this.z = Math.floor( this.z );
  2135. return this;
  2136. }
  2137. ceil() {
  2138. this.x = Math.ceil( this.x );
  2139. this.y = Math.ceil( this.y );
  2140. this.z = Math.ceil( this.z );
  2141. return this;
  2142. }
  2143. round() {
  2144. this.x = Math.round( this.x );
  2145. this.y = Math.round( this.y );
  2146. this.z = Math.round( this.z );
  2147. return this;
  2148. }
  2149. roundToZero() {
  2150. this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
  2151. this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
  2152. this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
  2153. return this;
  2154. }
  2155. negate() {
  2156. this.x = - this.x;
  2157. this.y = - this.y;
  2158. this.z = - this.z;
  2159. return this;
  2160. }
  2161. dot( v ) {
  2162. return this.x * v.x + this.y * v.y + this.z * v.z;
  2163. }
  2164. // TODO lengthSquared?
  2165. lengthSq() {
  2166. return this.x * this.x + this.y * this.y + this.z * this.z;
  2167. }
  2168. length() {
  2169. return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
  2170. }
  2171. manhattanLength() {
  2172. return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
  2173. }
  2174. normalize() {
  2175. return this.divideScalar( this.length() || 1 );
  2176. }
  2177. setLength( length ) {
  2178. return this.normalize().multiplyScalar( length );
  2179. }
  2180. lerp( v, alpha ) {
  2181. this.x += ( v.x - this.x ) * alpha;
  2182. this.y += ( v.y - this.y ) * alpha;
  2183. this.z += ( v.z - this.z ) * alpha;
  2184. return this;
  2185. }
  2186. lerpVectors( v1, v2, alpha ) {
  2187. this.x = v1.x + ( v2.x - v1.x ) * alpha;
  2188. this.y = v1.y + ( v2.y - v1.y ) * alpha;
  2189. this.z = v1.z + ( v2.z - v1.z ) * alpha;
  2190. return this;
  2191. }
  2192. cross( v, w ) {
  2193. if ( w !== undefined ) {
  2194. console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
  2195. return this.crossVectors( v, w );
  2196. }
  2197. return this.crossVectors( this, v );
  2198. }
  2199. crossVectors( a, b ) {
  2200. const ax = a.x, ay = a.y, az = a.z;
  2201. const bx = b.x, by = b.y, bz = b.z;
  2202. this.x = ay * bz - az * by;
  2203. this.y = az * bx - ax * bz;
  2204. this.z = ax * by - ay * bx;
  2205. return this;
  2206. }
  2207. projectOnVector( v ) {
  2208. const denominator = v.lengthSq();
  2209. if ( denominator === 0 ) return this.set( 0, 0, 0 );
  2210. const scalar = v.dot( this ) / denominator;
  2211. return this.copy( v ).multiplyScalar( scalar );
  2212. }
  2213. projectOnPlane( planeNormal ) {
  2214. _vector.copy( this ).projectOnVector( planeNormal );
  2215. return this.sub( _vector );
  2216. }
  2217. reflect( normal ) {
  2218. // reflect incident vector off plane orthogonal to normal
  2219. // normal is assumed to have unit length
  2220. return this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
  2221. }
  2222. angleTo( v ) {
  2223. const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
  2224. if ( denominator === 0 ) return Math.PI / 2;
  2225. const theta = this.dot( v ) / denominator;
  2226. // clamp, to handle numerical problems
  2227. return Math.acos( MathUtils$1.clamp( theta, - 1, 1 ) );
  2228. }
  2229. distanceTo( v ) {
  2230. return Math.sqrt( this.distanceToSquared( v ) );
  2231. }
  2232. distanceToSquared( v ) {
  2233. const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
  2234. return dx * dx + dy * dy + dz * dz;
  2235. }
  2236. manhattanDistanceTo( v ) {
  2237. return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
  2238. }
  2239. setFromSpherical( s ) {
  2240. return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
  2241. }
  2242. setFromSphericalCoords( radius, phi, theta ) {
  2243. const sinPhiRadius = Math.sin( phi ) * radius;
  2244. this.x = sinPhiRadius * Math.sin( theta );
  2245. this.y = Math.cos( phi ) * radius;
  2246. this.z = sinPhiRadius * Math.cos( theta );
  2247. return this;
  2248. }
  2249. setFromCylindrical( c ) {
  2250. return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
  2251. }
  2252. setFromCylindricalCoords( radius, theta, y ) {
  2253. this.x = radius * Math.sin( theta );
  2254. this.y = y;
  2255. this.z = radius * Math.cos( theta );
  2256. return this;
  2257. }
  2258. setFromMatrixPosition( m ) {
  2259. const e = m.elements;
  2260. this.x = e[ 12 ];
  2261. this.y = e[ 13 ];
  2262. this.z = e[ 14 ];
  2263. return this;
  2264. }
  2265. setFromMatrixScale( m ) {
  2266. const sx = this.setFromMatrixColumn( m, 0 ).length();
  2267. const sy = this.setFromMatrixColumn( m, 1 ).length();
  2268. const sz = this.setFromMatrixColumn( m, 2 ).length();
  2269. this.x = sx;
  2270. this.y = sy;
  2271. this.z = sz;
  2272. return this;
  2273. }
  2274. setFromMatrixColumn( m, index ) {
  2275. return this.fromArray( m.elements, index * 4 );
  2276. }
  2277. setFromMatrix3Column( m, index ) {
  2278. return this.fromArray( m.elements, index * 3 );
  2279. }
  2280. equals( v ) {
  2281. return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
  2282. }
  2283. fromArray( array, offset = 0 ) {
  2284. this.x = array[ offset ];
  2285. this.y = array[ offset + 1 ];
  2286. this.z = array[ offset + 2 ];
  2287. return this;
  2288. }
  2289. toArray( array = [], offset = 0 ) {
  2290. array[ offset ] = this.x;
  2291. array[ offset + 1 ] = this.y;
  2292. array[ offset + 2 ] = this.z;
  2293. return array;
  2294. }
  2295. fromBufferAttribute( attribute, index, offset ) {
  2296. if ( offset !== undefined ) {
  2297. console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
  2298. }
  2299. this.x = attribute.getX( index );
  2300. this.y = attribute.getY( index );
  2301. this.z = attribute.getZ( index );
  2302. return this;
  2303. }
  2304. random() {
  2305. this.x = Math.random();
  2306. this.y = Math.random();
  2307. this.z = Math.random();
  2308. return this;
  2309. }
  2310. }
  2311. const _vector = /*@__PURE__*/ new Vector3();
  2312. const _quaternion = /*@__PURE__*/ new Quaternion();
  2313. class Box3 {
  2314. constructor( min, max ) {
  2315. Object.defineProperty( this, 'isBox3', { value: true } );
  2316. this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
  2317. this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
  2318. }
  2319. set( min, max ) {
  2320. this.min.copy( min );
  2321. this.max.copy( max );
  2322. return this;
  2323. }
  2324. setFromArray( array ) {
  2325. let minX = + Infinity;
  2326. let minY = + Infinity;
  2327. let minZ = + Infinity;
  2328. let maxX = - Infinity;
  2329. let maxY = - Infinity;
  2330. let maxZ = - Infinity;
  2331. for ( let i = 0, l = array.length; i < l; i += 3 ) {
  2332. const x = array[ i ];
  2333. const y = array[ i + 1 ];
  2334. const z = array[ i + 2 ];
  2335. if ( x < minX ) minX = x;
  2336. if ( y < minY ) minY = y;
  2337. if ( z < minZ ) minZ = z;
  2338. if ( x > maxX ) maxX = x;
  2339. if ( y > maxY ) maxY = y;
  2340. if ( z > maxZ ) maxZ = z;
  2341. }
  2342. this.min.set( minX, minY, minZ );
  2343. this.max.set( maxX, maxY, maxZ );
  2344. return this;
  2345. }
  2346. setFromBufferAttribute( attribute ) {
  2347. let minX = + Infinity;
  2348. let minY = + Infinity;
  2349. let minZ = + Infinity;
  2350. let maxX = - Infinity;
  2351. let maxY = - Infinity;
  2352. let maxZ = - Infinity;
  2353. for ( let i = 0, l = attribute.count; i < l; i ++ ) {
  2354. const x = attribute.getX( i );
  2355. const y = attribute.getY( i );
  2356. const z = attribute.getZ( i );
  2357. if ( x < minX ) minX = x;
  2358. if ( y < minY ) minY = y;
  2359. if ( z < minZ ) minZ = z;
  2360. if ( x > maxX ) maxX = x;
  2361. if ( y > maxY ) maxY = y;
  2362. if ( z > maxZ ) maxZ = z;
  2363. }
  2364. this.min.set( minX, minY, minZ );
  2365. this.max.set( maxX, maxY, maxZ );
  2366. return this;
  2367. }
  2368. setFromPoints( points ) {
  2369. this.makeEmpty();
  2370. for ( let i = 0, il = points.length; i < il; i ++ ) {
  2371. this.expandByPoint( points[ i ] );
  2372. }
  2373. return this;
  2374. }
  2375. setFromCenterAndSize( center, size ) {
  2376. const halfSize = _vector$1.copy( size ).multiplyScalar( 0.5 );
  2377. this.min.copy( center ).sub( halfSize );
  2378. this.max.copy( center ).add( halfSize );
  2379. return this;
  2380. }
  2381. setFromObject( object ) {
  2382. this.makeEmpty();
  2383. return this.expandByObject( object );
  2384. }
  2385. clone() {
  2386. return new this.constructor().copy( this );
  2387. }
  2388. copy( box ) {
  2389. this.min.copy( box.min );
  2390. this.max.copy( box.max );
  2391. return this;
  2392. }
  2393. makeEmpty() {
  2394. this.min.x = this.min.y = this.min.z = + Infinity;
  2395. this.max.x = this.max.y = this.max.z = - Infinity;
  2396. return this;
  2397. }
  2398. isEmpty() {
  2399. // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
  2400. return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
  2401. }
  2402. getCenter( target ) {
  2403. if ( target === undefined ) {
  2404. console.warn( 'THREE.Box3: .getCenter() target is now required' );
  2405. target = new Vector3();
  2406. }
  2407. return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
  2408. }
  2409. getSize( target ) {
  2410. if ( target === undefined ) {
  2411. console.warn( 'THREE.Box3: .getSize() target is now required' );
  2412. target = new Vector3();
  2413. }
  2414. return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
  2415. }
  2416. expandByPoint( point ) {
  2417. this.min.min( point );
  2418. this.max.max( point );
  2419. return this;
  2420. }
  2421. expandByVector( vector ) {
  2422. this.min.sub( vector );
  2423. this.max.add( vector );
  2424. return this;
  2425. }
  2426. expandByScalar( scalar ) {
  2427. this.min.addScalar( - scalar );
  2428. this.max.addScalar( scalar );
  2429. return this;
  2430. }
  2431. expandByObject( object ) {
  2432. // Computes the world-axis-aligned bounding box of an object (including its children),
  2433. // accounting for both the object's, and children's, world transforms
  2434. object.updateWorldMatrix( false, false );
  2435. const geometry = object.geometry;
  2436. if ( geometry !== undefined ) {
  2437. if ( geometry.boundingBox === null ) {
  2438. geometry.computeBoundingBox();
  2439. }
  2440. _box.copy( geometry.boundingBox );
  2441. _box.applyMatrix4( object.matrixWorld );
  2442. this.union( _box );
  2443. }
  2444. const children = object.children;
  2445. for ( let i = 0, l = children.length; i < l; i ++ ) {
  2446. this.expandByObject( children[ i ] );
  2447. }
  2448. return this;
  2449. }
  2450. containsPoint( point ) {
  2451. return point.x < this.min.x || point.x > this.max.x ||
  2452. point.y < this.min.y || point.y > this.max.y ||
  2453. point.z < this.min.z || point.z > this.max.z ? false : true;
  2454. }
  2455. containsBox( box ) {
  2456. return this.min.x <= box.min.x && box.max.x <= this.max.x &&
  2457. this.min.y <= box.min.y && box.max.y <= this.max.y &&
  2458. this.min.z <= box.min.z && box.max.z <= this.max.z;
  2459. }
  2460. getParameter( point, target ) {
  2461. // This can potentially have a divide by zero if the box
  2462. // has a size dimension of 0.
  2463. if ( target === undefined ) {
  2464. console.warn( 'THREE.Box3: .getParameter() target is now required' );
  2465. target = new Vector3();
  2466. }
  2467. return target.set(
  2468. ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
  2469. ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
  2470. ( point.z - this.min.z ) / ( this.max.z - this.min.z )
  2471. );
  2472. }
  2473. intersectsBox( box ) {
  2474. // using 6 splitting planes to rule out intersections.
  2475. return box.max.x < this.min.x || box.min.x > this.max.x ||
  2476. box.max.y < this.min.y || box.min.y > this.max.y ||
  2477. box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
  2478. }
  2479. intersectsSphere( sphere ) {
  2480. // Find the point on the AABB closest to the sphere center.
  2481. this.clampPoint( sphere.center, _vector$1 );
  2482. // If that point is inside the sphere, the AABB and sphere intersect.
  2483. return _vector$1.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
  2484. }
  2485. intersectsPlane( plane ) {
  2486. // We compute the minimum and maximum dot product values. If those values
  2487. // are on the same side (back or front) of the plane, then there is no intersection.
  2488. let min, max;
  2489. if ( plane.normal.x > 0 ) {
  2490. min = plane.normal.x * this.min.x;
  2491. max = plane.normal.x * this.max.x;
  2492. } else {
  2493. min = plane.normal.x * this.max.x;
  2494. max = plane.normal.x * this.min.x;
  2495. }
  2496. if ( plane.normal.y > 0 ) {
  2497. min += plane.normal.y * this.min.y;
  2498. max += plane.normal.y * this.max.y;
  2499. } else {
  2500. min += plane.normal.y * this.max.y;
  2501. max += plane.normal.y * this.min.y;
  2502. }
  2503. if ( plane.normal.z > 0 ) {
  2504. min += plane.normal.z * this.min.z;
  2505. max += plane.normal.z * this.max.z;
  2506. } else {
  2507. min += plane.normal.z * this.max.z;
  2508. max += plane.normal.z * this.min.z;
  2509. }
  2510. return ( min <= - plane.constant && max >= - plane.constant );
  2511. }
  2512. intersectsTriangle( triangle ) {
  2513. if ( this.isEmpty() ) {
  2514. return false;
  2515. }
  2516. // compute box center and extents
  2517. this.getCenter( _center );
  2518. _extents.subVectors( this.max, _center );
  2519. // translate triangle to aabb origin
  2520. _v0.subVectors( triangle.a, _center );
  2521. _v1.subVectors( triangle.b, _center );
  2522. _v2.subVectors( triangle.c, _center );
  2523. // compute edge vectors for triangle
  2524. _f0.subVectors( _v1, _v0 );
  2525. _f1.subVectors( _v2, _v1 );
  2526. _f2.subVectors( _v0, _v2 );
  2527. // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
  2528. // 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
  2529. // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
  2530. let axes = [
  2531. 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
  2532. _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
  2533. - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
  2534. ];
  2535. if ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {
  2536. return false;
  2537. }
  2538. // test 3 face normals from the aabb
  2539. axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
  2540. if ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {
  2541. return false;
  2542. }
  2543. // finally testing the face normal of the triangle
  2544. // use already existing triangle edge vectors here
  2545. _triangleNormal.crossVectors( _f0, _f1 );
  2546. axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
  2547. return satForAxes( axes, _v0, _v1, _v2, _extents );
  2548. }
  2549. clampPoint( point, target ) {
  2550. if ( target === undefined ) {
  2551. console.warn( 'THREE.Box3: .clampPoint() target is now required' );
  2552. target = new Vector3();
  2553. }
  2554. return target.copy( point ).clamp( this.min, this.max );
  2555. }
  2556. distanceToPoint( point ) {
  2557. const clampedPoint = _vector$1.copy( point ).clamp( this.min, this.max );
  2558. return clampedPoint.sub( point ).length();
  2559. }
  2560. getBoundingSphere( target ) {
  2561. if ( target === undefined ) {
  2562. console.error( 'THREE.Box3: .getBoundingSphere() target is now required' );
  2563. //target = new Sphere(); // removed to avoid cyclic dependency
  2564. }
  2565. this.getCenter( target.center );
  2566. target.radius = this.getSize( _vector$1 ).length() * 0.5;
  2567. return target;
  2568. }
  2569. intersect( box ) {
  2570. this.min.max( box.min );
  2571. this.max.min( box.max );
  2572. // 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.
  2573. if ( this.isEmpty() ) this.makeEmpty();
  2574. return this;
  2575. }
  2576. union( box ) {
  2577. this.min.min( box.min );
  2578. this.max.max( box.max );
  2579. return this;
  2580. }
  2581. applyMatrix4( matrix ) {
  2582. // transform of empty box is an empty box.
  2583. if ( this.isEmpty() ) return this;
  2584. // NOTE: I am using a binary pattern to specify all 2^3 combinations below
  2585. _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
  2586. _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
  2587. _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
  2588. _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
  2589. _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
  2590. _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
  2591. _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
  2592. _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
  2593. this.setFromPoints( _points );
  2594. return this;
  2595. }
  2596. translate( offset ) {
  2597. this.min.add( offset );
  2598. this.max.add( offset );
  2599. return this;
  2600. }
  2601. equals( box ) {
  2602. return box.min.equals( this.min ) && box.max.equals( this.max );
  2603. }
  2604. }
  2605. function satForAxes( axes, v0, v1, v2, extents ) {
  2606. for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
  2607. _testAxis.fromArray( axes, i );
  2608. // project the aabb onto the seperating axis
  2609. const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
  2610. // project all 3 vertices of the triangle onto the seperating axis
  2611. const p0 = v0.dot( _testAxis );
  2612. const p1 = v1.dot( _testAxis );
  2613. const p2 = v2.dot( _testAxis );
  2614. // actual test, basically see if either of the most extreme of the triangle points intersects r
  2615. if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
  2616. // points of the projected triangle are outside the projected half-length of the aabb
  2617. // the axis is seperating and we can exit
  2618. return false;
  2619. }
  2620. }
  2621. return true;
  2622. }
  2623. const _points = [
  2624. /*@__PURE__*/ new Vector3(),
  2625. /*@__PURE__*/ new Vector3(),
  2626. /*@__PURE__*/ new Vector3(),
  2627. /*@__PURE__*/ new Vector3(),
  2628. /*@__PURE__*/ new Vector3(),
  2629. /*@__PURE__*/ new Vector3(),
  2630. /*@__PURE__*/ new Vector3(),
  2631. /*@__PURE__*/ new Vector3()
  2632. ];
  2633. const _vector$1 = /*@__PURE__*/ new Vector3();
  2634. const _box = /*@__PURE__*/ new Box3();
  2635. // triangle centered vertices
  2636. const _v0 = /*@__PURE__*/ new Vector3();
  2637. const _v1 = /*@__PURE__*/ new Vector3();
  2638. const _v2 = /*@__PURE__*/ new Vector3();
  2639. // triangle edge vectors
  2640. const _f0 = /*@__PURE__*/ new Vector3();
  2641. const _f1 = /*@__PURE__*/ new Vector3();
  2642. const _f2 = /*@__PURE__*/ new Vector3();
  2643. const _center = /*@__PURE__*/ new Vector3();
  2644. const _extents = /*@__PURE__*/ new Vector3();
  2645. const _triangleNormal = /*@__PURE__*/ new Vector3();
  2646. const _testAxis = /*@__PURE__*/ new Vector3();
  2647. const _box$1 = /*@__PURE__*/ new Box3();
  2648. class Sphere {
  2649. constructor( center, radius ) {
  2650. this.center = ( center !== undefined ) ? center : new Vector3();
  2651. this.radius = ( radius !== undefined ) ? radius : - 1;
  2652. }
  2653. set( center, radius ) {
  2654. this.center.copy( center );
  2655. this.radius = radius;
  2656. return this;
  2657. }
  2658. setFromPoints( points, optionalCenter ) {
  2659. const center = this.center;
  2660. if ( optionalCenter !== undefined ) {
  2661. center.copy( optionalCenter );
  2662. } else {
  2663. _box$1.setFromPoints( points ).getCenter( center );
  2664. }
  2665. let maxRadiusSq = 0;
  2666. for ( let i = 0, il = points.length; i < il; i ++ ) {
  2667. maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
  2668. }
  2669. this.radius = Math.sqrt( maxRadiusSq );
  2670. return this;
  2671. }
  2672. clone() {
  2673. return new this.constructor().copy( this );
  2674. }
  2675. copy( sphere ) {
  2676. this.center.copy( sphere.center );
  2677. this.radius = sphere.radius;
  2678. return this;
  2679. }
  2680. isEmpty() {
  2681. return ( this.radius < 0 );
  2682. }
  2683. makeEmpty() {
  2684. this.center.set( 0, 0, 0 );
  2685. this.radius = - 1;
  2686. return this;
  2687. }
  2688. containsPoint( point ) {
  2689. return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
  2690. }
  2691. distanceToPoint( point ) {
  2692. return ( point.distanceTo( this.center ) - this.radius );
  2693. }
  2694. intersectsSphere( sphere ) {
  2695. const radiusSum = this.radius + sphere.radius;
  2696. return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
  2697. }
  2698. intersectsBox( box ) {
  2699. return box.intersectsSphere( this );
  2700. }
  2701. intersectsPlane( plane ) {
  2702. return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
  2703. }
  2704. clampPoint( point, target ) {
  2705. const deltaLengthSq = this.center.distanceToSquared( point );
  2706. if ( target === undefined ) {
  2707. console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
  2708. target = new Vector3();
  2709. }
  2710. target.copy( point );
  2711. if ( deltaLengthSq > ( this.radius * this.radius ) ) {
  2712. target.sub( this.center ).normalize();
  2713. target.multiplyScalar( this.radius ).add( this.center );
  2714. }
  2715. return target;
  2716. }
  2717. getBoundingBox( target ) {
  2718. if ( target === undefined ) {
  2719. console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
  2720. target = new Box3();
  2721. }
  2722. if ( this.isEmpty() ) {
  2723. // Empty sphere produces empty bounding box
  2724. target.makeEmpty();
  2725. return target;
  2726. }
  2727. target.set( this.center, this.center );
  2728. target.expandByScalar( this.radius );
  2729. return target;
  2730. }
  2731. applyMatrix4( matrix ) {
  2732. this.center.applyMatrix4( matrix );
  2733. this.radius = this.radius * matrix.getMaxScaleOnAxis();
  2734. return this;
  2735. }
  2736. translate( offset ) {
  2737. this.center.add( offset );
  2738. return this;
  2739. }
  2740. equals( sphere ) {
  2741. return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
  2742. }
  2743. }
  2744. const _vector$2 = /*@__PURE__*/ new Vector3();
  2745. const _segCenter = /*@__PURE__*/ new Vector3();
  2746. const _segDir = /*@__PURE__*/ new Vector3();
  2747. const _diff = /*@__PURE__*/ new Vector3();
  2748. const _edge1 = /*@__PURE__*/ new Vector3();
  2749. const _edge2 = /*@__PURE__*/ new Vector3();
  2750. const _normal = /*@__PURE__*/ new Vector3();
  2751. class Ray {
  2752. constructor( origin, direction ) {
  2753. this.origin = ( origin !== undefined ) ? origin : new Vector3();
  2754. this.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );
  2755. }
  2756. set( origin, direction ) {
  2757. this.origin.copy( origin );
  2758. this.direction.copy( direction );
  2759. return this;
  2760. }
  2761. clone() {
  2762. return new this.constructor().copy( this );
  2763. }
  2764. copy( ray ) {
  2765. this.origin.copy( ray.origin );
  2766. this.direction.copy( ray.direction );
  2767. return this;
  2768. }
  2769. at( t, target ) {
  2770. if ( target === undefined ) {
  2771. console.warn( 'THREE.Ray: .at() target is now required' );
  2772. target = new Vector3();
  2773. }
  2774. return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
  2775. }
  2776. lookAt( v ) {
  2777. this.direction.copy( v ).sub( this.origin ).normalize();
  2778. return this;
  2779. }
  2780. recast( t ) {
  2781. this.origin.copy( this.at( t, _vector$2 ) );
  2782. return this;
  2783. }
  2784. closestPointToPoint( point, target ) {
  2785. if ( target === undefined ) {
  2786. console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
  2787. target = new Vector3();
  2788. }
  2789. target.subVectors( point, this.origin );
  2790. const directionDistance = target.dot( this.direction );
  2791. if ( directionDistance < 0 ) {
  2792. return target.copy( this.origin );
  2793. }
  2794. return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
  2795. }
  2796. distanceToPoint( point ) {
  2797. return Math.sqrt( this.distanceSqToPoint( point ) );
  2798. }
  2799. distanceSqToPoint( point ) {
  2800. const directionDistance = _vector$2.subVectors( point, this.origin ).dot( this.direction );
  2801. // point behind the ray
  2802. if ( directionDistance < 0 ) {
  2803. return this.origin.distanceToSquared( point );
  2804. }
  2805. _vector$2.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
  2806. return _vector$2.distanceToSquared( point );
  2807. }
  2808. distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
  2809. // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
  2810. // It returns the min distance between the ray and the segment
  2811. // defined by v0 and v1
  2812. // It can also set two optional targets :
  2813. // - The closest point on the ray
  2814. // - The closest point on the segment
  2815. _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
  2816. _segDir.copy( v1 ).sub( v0 ).normalize();
  2817. _diff.copy( this.origin ).sub( _segCenter );
  2818. const segExtent = v0.distanceTo( v1 ) * 0.5;
  2819. const a01 = - this.direction.dot( _segDir );
  2820. const b0 = _diff.dot( this.direction );
  2821. const b1 = - _diff.dot( _segDir );
  2822. const c = _diff.lengthSq();
  2823. const det = Math.abs( 1 - a01 * a01 );
  2824. let s0, s1, sqrDist, extDet;
  2825. if ( det > 0 ) {
  2826. // The ray and segment are not parallel.
  2827. s0 = a01 * b1 - b0;
  2828. s1 = a01 * b0 - b1;
  2829. extDet = segExtent * det;
  2830. if ( s0 >= 0 ) {
  2831. if ( s1 >= - extDet ) {
  2832. if ( s1 <= extDet ) {
  2833. // region 0
  2834. // Minimum at interior points of ray and segment.
  2835. const invDet = 1 / det;
  2836. s0 *= invDet;
  2837. s1 *= invDet;
  2838. sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
  2839. } else {
  2840. // region 1
  2841. s1 = segExtent;
  2842. s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
  2843. sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
  2844. }
  2845. } else {
  2846. // region 5
  2847. s1 = - segExtent;
  2848. s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
  2849. sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
  2850. }
  2851. } else {
  2852. if ( s1 <= - extDet ) {
  2853. // region 4
  2854. s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
  2855. s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
  2856. sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
  2857. } else if ( s1 <= extDet ) {
  2858. // region 3
  2859. s0 = 0;
  2860. s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
  2861. sqrDist = s1 * ( s1 + 2 * b1 ) + c;
  2862. } else {
  2863. // region 2
  2864. s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
  2865. s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
  2866. sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
  2867. }
  2868. }
  2869. } else {
  2870. // Ray and segment are parallel.
  2871. s1 = ( a01 > 0 ) ? - segExtent : segExtent;
  2872. s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
  2873. sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
  2874. }
  2875. if ( optionalPointOnRay ) {
  2876. optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
  2877. }
  2878. if ( optionalPointOnSegment ) {
  2879. optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );
  2880. }
  2881. return sqrDist;
  2882. }
  2883. intersectSphere( sphere, target ) {
  2884. _vector$2.subVectors( sphere.center, this.origin );
  2885. const tca = _vector$2.dot( this.direction );
  2886. const d2 = _vector$2.dot( _vector$2 ) - tca * tca;
  2887. const radius2 = sphere.radius * sphere.radius;
  2888. if ( d2 > radius2 ) return null;
  2889. const thc = Math.sqrt( radius2 - d2 );
  2890. // t0 = first intersect point - entrance on front of sphere
  2891. const t0 = tca - thc;
  2892. // t1 = second intersect point - exit point on back of sphere
  2893. const t1 = tca + thc;
  2894. // test to see if both t0 and t1 are behind the ray - if so, return null
  2895. if ( t0 < 0 && t1 < 0 ) return null;
  2896. // test to see if t0 is behind the ray:
  2897. // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
  2898. // in order to always return an intersect point that is in front of the ray.
  2899. if ( t0 < 0 ) return this.at( t1, target );
  2900. // else t0 is in front of the ray, so return the first collision point scaled by t0
  2901. return this.at( t0, target );
  2902. }
  2903. intersectsSphere( sphere ) {
  2904. return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
  2905. }
  2906. distanceToPlane( plane ) {
  2907. const denominator = plane.normal.dot( this.direction );
  2908. if ( denominator === 0 ) {
  2909. // line is coplanar, return origin
  2910. if ( plane.distanceToPoint( this.origin ) === 0 ) {
  2911. return 0;
  2912. }
  2913. // Null is preferable to undefined since undefined means.... it is undefined
  2914. return null;
  2915. }
  2916. const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
  2917. // Return if the ray never intersects the plane
  2918. return t >= 0 ? t : null;
  2919. }
  2920. intersectPlane( plane, target ) {
  2921. const t = this.distanceToPlane( plane );
  2922. if ( t === null ) {
  2923. return null;
  2924. }
  2925. return this.at( t, target );
  2926. }
  2927. intersectsPlane( plane ) {
  2928. // check if the ray lies on the plane first
  2929. const distToPoint = plane.distanceToPoint( this.origin );
  2930. if ( distToPoint === 0 ) {
  2931. return true;
  2932. }
  2933. const denominator = plane.normal.dot( this.direction );
  2934. if ( denominator * distToPoint < 0 ) {
  2935. return true;
  2936. }
  2937. // ray origin is behind the plane (and is pointing behind it)
  2938. return false;
  2939. }
  2940. intersectBox( box, target ) {
  2941. let tmin, tmax, tymin, tymax, tzmin, tzmax;
  2942. const invdirx = 1 / this.direction.x,
  2943. invdiry = 1 / this.direction.y,
  2944. invdirz = 1 / this.direction.z;
  2945. const origin = this.origin;
  2946. if ( invdirx >= 0 ) {
  2947. tmin = ( box.min.x - origin.x ) * invdirx;
  2948. tmax = ( box.max.x - origin.x ) * invdirx;
  2949. } else {
  2950. tmin = ( box.max.x - origin.x ) * invdirx;
  2951. tmax = ( box.min.x - origin.x ) * invdirx;
  2952. }
  2953. if ( invdiry >= 0 ) {
  2954. tymin = ( box.min.y - origin.y ) * invdiry;
  2955. tymax = ( box.max.y - origin.y ) * invdiry;
  2956. } else {
  2957. tymin = ( box.max.y - origin.y ) * invdiry;
  2958. tymax = ( box.min.y - origin.y ) * invdiry;
  2959. }
  2960. if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
  2961. // These lines also handle the case where tmin or tmax is NaN
  2962. // (result of 0 * Infinity). x !== x returns true if x is NaN
  2963. if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
  2964. if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
  2965. if ( invdirz >= 0 ) {
  2966. tzmin = ( box.min.z - origin.z ) * invdirz;
  2967. tzmax = ( box.max.z - origin.z ) * invdirz;
  2968. } else {
  2969. tzmin = ( box.max.z - origin.z ) * invdirz;
  2970. tzmax = ( box.min.z - origin.z ) * invdirz;
  2971. }
  2972. if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
  2973. if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
  2974. if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
  2975. //return point closest to the ray (positive side)
  2976. if ( tmax < 0 ) return null;
  2977. return this.at( tmin >= 0 ? tmin : tmax, target );
  2978. }
  2979. intersectsBox( box ) {
  2980. return this.intersectBox( box, _vector$2 ) !== null;
  2981. }
  2982. intersectTriangle( a, b, c, backfaceCulling, target ) {
  2983. // Compute the offset origin, edges, and normal.
  2984. // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
  2985. _edge1.subVectors( b, a );
  2986. _edge2.subVectors( c, a );
  2987. _normal.crossVectors( _edge1, _edge2 );
  2988. // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
  2989. // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
  2990. // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
  2991. // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
  2992. // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
  2993. let DdN = this.direction.dot( _normal );
  2994. let sign;
  2995. if ( DdN > 0 ) {
  2996. if ( backfaceCulling ) return null;
  2997. sign = 1;
  2998. } else if ( DdN < 0 ) {
  2999. sign = - 1;
  3000. DdN = - DdN;
  3001. } else {
  3002. return null;
  3003. }
  3004. _diff.subVectors( this.origin, a );
  3005. const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
  3006. // b1 < 0, no intersection
  3007. if ( DdQxE2 < 0 ) {
  3008. return null;
  3009. }
  3010. const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
  3011. // b2 < 0, no intersection
  3012. if ( DdE1xQ < 0 ) {
  3013. return null;
  3014. }
  3015. // b1+b2 > 1, no intersection
  3016. if ( DdQxE2 + DdE1xQ > DdN ) {
  3017. return null;
  3018. }
  3019. // Line intersects triangle, check if ray does.
  3020. const QdN = - sign * _diff.dot( _normal );
  3021. // t < 0, no intersection
  3022. if ( QdN < 0 ) {
  3023. return null;
  3024. }
  3025. // Ray intersects triangle.
  3026. return this.at( QdN / DdN, target );
  3027. }
  3028. applyMatrix4( matrix4 ) {
  3029. this.origin.applyMatrix4( matrix4 );
  3030. this.direction.transformDirection( matrix4 );
  3031. return this;
  3032. }
  3033. equals( ray ) {
  3034. return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
  3035. }
  3036. }
  3037. class Matrix4 {
  3038. constructor() {
  3039. Object.defineProperty( this, 'isMatrix4', { value: true } );
  3040. this.elements = [
  3041. 1, 0, 0, 0,
  3042. 0, 1, 0, 0,
  3043. 0, 0, 1, 0,
  3044. 0, 0, 0, 1
  3045. ];
  3046. if ( arguments.length > 0 ) {
  3047. console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
  3048. }
  3049. }
  3050. set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
  3051. const te = this.elements;
  3052. te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
  3053. te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
  3054. te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
  3055. te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
  3056. return this;
  3057. }
  3058. identity() {
  3059. this.set(
  3060. 1, 0, 0, 0,
  3061. 0, 1, 0, 0,
  3062. 0, 0, 1, 0,
  3063. 0, 0, 0, 1
  3064. );
  3065. return this;
  3066. }
  3067. clone() {
  3068. return new Matrix4().fromArray( this.elements );
  3069. }
  3070. copy( m ) {
  3071. const te = this.elements;
  3072. const me = m.elements;
  3073. te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
  3074. te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
  3075. te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
  3076. te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
  3077. return this;
  3078. }
  3079. copyPosition( m ) {
  3080. const te = this.elements, me = m.elements;
  3081. te[ 12 ] = me[ 12 ];
  3082. te[ 13 ] = me[ 13 ];
  3083. te[ 14 ] = me[ 14 ];
  3084. return this;
  3085. }
  3086. extractBasis( xAxis, yAxis, zAxis ) {
  3087. xAxis.setFromMatrixColumn( this, 0 );
  3088. yAxis.setFromMatrixColumn( this, 1 );
  3089. zAxis.setFromMatrixColumn( this, 2 );
  3090. return this;
  3091. }
  3092. makeBasis( xAxis, yAxis, zAxis ) {
  3093. this.set(
  3094. xAxis.x, yAxis.x, zAxis.x, 0,
  3095. xAxis.y, yAxis.y, zAxis.y, 0,
  3096. xAxis.z, yAxis.z, zAxis.z, 0,
  3097. 0, 0, 0, 1
  3098. );
  3099. return this;
  3100. }
  3101. extractRotation( m ) {
  3102. // this method does not support reflection matrices
  3103. const te = this.elements;
  3104. const me = m.elements;
  3105. const scaleX = 1 / _v1$1.setFromMatrixColumn( m, 0 ).length();
  3106. const scaleY = 1 / _v1$1.setFromMatrixColumn( m, 1 ).length();
  3107. const scaleZ = 1 / _v1$1.setFromMatrixColumn( m, 2 ).length();
  3108. te[ 0 ] = me[ 0 ] * scaleX;
  3109. te[ 1 ] = me[ 1 ] * scaleX;
  3110. te[ 2 ] = me[ 2 ] * scaleX;
  3111. te[ 3 ] = 0;
  3112. te[ 4 ] = me[ 4 ] * scaleY;
  3113. te[ 5 ] = me[ 5 ] * scaleY;
  3114. te[ 6 ] = me[ 6 ] * scaleY;
  3115. te[ 7 ] = 0;
  3116. te[ 8 ] = me[ 8 ] * scaleZ;
  3117. te[ 9 ] = me[ 9 ] * scaleZ;
  3118. te[ 10 ] = me[ 10 ] * scaleZ;
  3119. te[ 11 ] = 0;
  3120. te[ 12 ] = 0;
  3121. te[ 13 ] = 0;
  3122. te[ 14 ] = 0;
  3123. te[ 15 ] = 1;
  3124. return this;
  3125. }
  3126. makeRotationFromEuler( euler ) {
  3127. if ( ! ( euler && euler.isEuler ) ) {
  3128. console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
  3129. }
  3130. const te = this.elements;
  3131. const x = euler.x, y = euler.y, z = euler.z;
  3132. const a = Math.cos( x ), b = Math.sin( x );
  3133. const c = Math.cos( y ), d = Math.sin( y );
  3134. const e = Math.cos( z ), f = Math.sin( z );
  3135. if ( euler.order === 'XYZ' ) {
  3136. const ae = a * e, af = a * f, be = b * e, bf = b * f;
  3137. te[ 0 ] = c * e;
  3138. te[ 4 ] = - c * f;
  3139. te[ 8 ] = d;
  3140. te[ 1 ] = af + be * d;
  3141. te[ 5 ] = ae - bf * d;
  3142. te[ 9 ] = - b * c;
  3143. te[ 2 ] = bf - ae * d;
  3144. te[ 6 ] = be + af * d;
  3145. te[ 10 ] = a * c;
  3146. } else if ( euler.order === 'YXZ' ) {
  3147. const ce = c * e, cf = c * f, de = d * e, df = d * f;
  3148. te[ 0 ] = ce + df * b;
  3149. te[ 4 ] = de * b - cf;
  3150. te[ 8 ] = a * d;
  3151. te[ 1 ] = a * f;
  3152. te[ 5 ] = a * e;
  3153. te[ 9 ] = - b;
  3154. te[ 2 ] = cf * b - de;
  3155. te[ 6 ] = df + ce * b;
  3156. te[ 10 ] = a * c;
  3157. } else if ( euler.order === 'ZXY' ) {
  3158. const ce = c * e, cf = c * f, de = d * e, df = d * f;
  3159. te[ 0 ] = ce - df * b;
  3160. te[ 4 ] = - a * f;
  3161. te[ 8 ] = de + cf * b;
  3162. te[ 1 ] = cf + de * b;
  3163. te[ 5 ] = a * e;
  3164. te[ 9 ] = df - ce * b;
  3165. te[ 2 ] = - a * d;
  3166. te[ 6 ] = b;
  3167. te[ 10 ] = a * c;
  3168. } else if ( euler.order === 'ZYX' ) {
  3169. const ae = a * e, af = a * f, be = b * e, bf = b * f;
  3170. te[ 0 ] = c * e;
  3171. te[ 4 ] = be * d - af;
  3172. te[ 8 ] = ae * d + bf;
  3173. te[ 1 ] = c * f;
  3174. te[ 5 ] = bf * d + ae;
  3175. te[ 9 ] = af * d - be;
  3176. te[ 2 ] = - d;
  3177. te[ 6 ] = b * c;
  3178. te[ 10 ] = a * c;
  3179. } else if ( euler.order === 'YZX' ) {
  3180. const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
  3181. te[ 0 ] = c * e;
  3182. te[ 4 ] = bd - ac * f;
  3183. te[ 8 ] = bc * f + ad;
  3184. te[ 1 ] = f;
  3185. te[ 5 ] = a * e;
  3186. te[ 9 ] = - b * e;
  3187. te[ 2 ] = - d * e;
  3188. te[ 6 ] = ad * f + bc;
  3189. te[ 10 ] = ac - bd * f;
  3190. } else if ( euler.order === 'XZY' ) {
  3191. const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
  3192. te[ 0 ] = c * e;
  3193. te[ 4 ] = - f;
  3194. te[ 8 ] = d * e;
  3195. te[ 1 ] = ac * f + bd;
  3196. te[ 5 ] = a * e;
  3197. te[ 9 ] = ad * f - bc;
  3198. te[ 2 ] = bc * f - ad;
  3199. te[ 6 ] = b * e;
  3200. te[ 10 ] = bd * f + ac;
  3201. }
  3202. // bottom row
  3203. te[ 3 ] = 0;
  3204. te[ 7 ] = 0;
  3205. te[ 11 ] = 0;
  3206. // last column
  3207. te[ 12 ] = 0;
  3208. te[ 13 ] = 0;
  3209. te[ 14 ] = 0;
  3210. te[ 15 ] = 1;
  3211. return this;
  3212. }
  3213. makeRotationFromQuaternion( q ) {
  3214. return this.compose( _zero, q, _one );
  3215. }
  3216. lookAt( eye, target, up ) {
  3217. const te = this.elements;
  3218. _z.subVectors( eye, target );
  3219. if ( _z.lengthSq() === 0 ) {
  3220. // eye and target are in the same position
  3221. _z.z = 1;
  3222. }
  3223. _z.normalize();
  3224. _x.crossVectors( up, _z );
  3225. if ( _x.lengthSq() === 0 ) {
  3226. // up and z are parallel
  3227. if ( Math.abs( up.z ) === 1 ) {
  3228. _z.x += 0.0001;
  3229. } else {
  3230. _z.z += 0.0001;
  3231. }
  3232. _z.normalize();
  3233. _x.crossVectors( up, _z );
  3234. }
  3235. _x.normalize();
  3236. _y.crossVectors( _z, _x );
  3237. te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
  3238. te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
  3239. te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
  3240. return this;
  3241. }
  3242. multiply( m, n ) {
  3243. if ( n !== undefined ) {
  3244. console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
  3245. return this.multiplyMatrices( m, n );
  3246. }
  3247. return this.multiplyMatrices( this, m );
  3248. }
  3249. premultiply( m ) {
  3250. return this.multiplyMatrices( m, this );
  3251. }
  3252. multiplyMatrices( a, b ) {
  3253. const ae = a.elements;
  3254. const be = b.elements;
  3255. const te = this.elements;
  3256. const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
  3257. const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
  3258. const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
  3259. const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
  3260. const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
  3261. const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
  3262. const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
  3263. const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
  3264. te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
  3265. te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
  3266. te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
  3267. te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
  3268. te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
  3269. te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
  3270. te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
  3271. te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
  3272. te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
  3273. te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
  3274. te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
  3275. te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
  3276. te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
  3277. te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
  3278. te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
  3279. te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
  3280. return this;
  3281. }
  3282. multiplyScalar( s ) {
  3283. const te = this.elements;
  3284. te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
  3285. te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
  3286. te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
  3287. te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
  3288. return this;
  3289. }
  3290. determinant() {
  3291. const te = this.elements;
  3292. const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
  3293. const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
  3294. const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
  3295. const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
  3296. //TODO: make this more efficient
  3297. //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
  3298. return (
  3299. n41 * (
  3300. + n14 * n23 * n32
  3301. - n13 * n24 * n32
  3302. - n14 * n22 * n33
  3303. + n12 * n24 * n33
  3304. + n13 * n22 * n34
  3305. - n12 * n23 * n34
  3306. ) +
  3307. n42 * (
  3308. + n11 * n23 * n34
  3309. - n11 * n24 * n33
  3310. + n14 * n21 * n33
  3311. - n13 * n21 * n34
  3312. + n13 * n24 * n31
  3313. - n14 * n23 * n31
  3314. ) +
  3315. n43 * (
  3316. + n11 * n24 * n32
  3317. - n11 * n22 * n34
  3318. - n14 * n21 * n32
  3319. + n12 * n21 * n34
  3320. + n14 * n22 * n31
  3321. - n12 * n24 * n31
  3322. ) +
  3323. n44 * (
  3324. - n13 * n22 * n31
  3325. - n11 * n23 * n32
  3326. + n11 * n22 * n33
  3327. + n13 * n21 * n32
  3328. - n12 * n21 * n33
  3329. + n12 * n23 * n31
  3330. )
  3331. );
  3332. }
  3333. transpose() {
  3334. const te = this.elements;
  3335. let tmp;
  3336. tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
  3337. tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
  3338. tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
  3339. tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
  3340. tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
  3341. tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
  3342. return this;
  3343. }
  3344. setPosition( x, y, z ) {
  3345. const te = this.elements;
  3346. if ( x.isVector3 ) {
  3347. te[ 12 ] = x.x;
  3348. te[ 13 ] = x.y;
  3349. te[ 14 ] = x.z;
  3350. } else {
  3351. te[ 12 ] = x;
  3352. te[ 13 ] = y;
  3353. te[ 14 ] = z;
  3354. }
  3355. return this;
  3356. }
  3357. invert() {
  3358. // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
  3359. const te = this.elements,
  3360. n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
  3361. n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
  3362. n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
  3363. n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
  3364. t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
  3365. t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
  3366. t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
  3367. t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
  3368. const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
  3369. if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
  3370. const detInv = 1 / det;
  3371. te[ 0 ] = t11 * detInv;
  3372. te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
  3373. te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
  3374. te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
  3375. te[ 4 ] = t12 * detInv;
  3376. te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
  3377. te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
  3378. te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
  3379. te[ 8 ] = t13 * detInv;
  3380. te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
  3381. te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
  3382. te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
  3383. te[ 12 ] = t14 * detInv;
  3384. te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
  3385. te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
  3386. te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
  3387. return this;
  3388. }
  3389. scale( v ) {
  3390. const te = this.elements;
  3391. const x = v.x, y = v.y, z = v.z;
  3392. te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
  3393. te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
  3394. te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
  3395. te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
  3396. return this;
  3397. }
  3398. getMaxScaleOnAxis() {
  3399. const te = this.elements;
  3400. const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
  3401. const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
  3402. const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
  3403. return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
  3404. }
  3405. makeTranslation( x, y, z ) {
  3406. this.set(
  3407. 1, 0, 0, x,
  3408. 0, 1, 0, y,
  3409. 0, 0, 1, z,
  3410. 0, 0, 0, 1
  3411. );
  3412. return this;
  3413. }
  3414. makeRotationX( theta ) {
  3415. const c = Math.cos( theta ), s = Math.sin( theta );
  3416. this.set(
  3417. 1, 0, 0, 0,
  3418. 0, c, - s, 0,
  3419. 0, s, c, 0,
  3420. 0, 0, 0, 1
  3421. );
  3422. return this;
  3423. }
  3424. makeRotationY( theta ) {
  3425. const c = Math.cos( theta ), s = Math.sin( theta );
  3426. this.set(
  3427. c, 0, s, 0,
  3428. 0, 1, 0, 0,
  3429. - s, 0, c, 0,
  3430. 0, 0, 0, 1
  3431. );
  3432. return this;
  3433. }
  3434. makeRotationZ( theta ) {
  3435. const c = Math.cos( theta ), s = Math.sin( theta );
  3436. this.set(
  3437. c, - s, 0, 0,
  3438. s, c, 0, 0,
  3439. 0, 0, 1, 0,
  3440. 0, 0, 0, 1
  3441. );
  3442. return this;
  3443. }
  3444. makeRotationAxis( axis, angle ) {
  3445. // Based on http://www.gamedev.net/reference/articles/article1199.asp
  3446. const c = Math.cos( angle );
  3447. const s = Math.sin( angle );
  3448. const t = 1 - c;
  3449. const x = axis.x, y = axis.y, z = axis.z;
  3450. const tx = t * x, ty = t * y;
  3451. this.set(
  3452. tx * x + c, tx * y - s * z, tx * z + s * y, 0,
  3453. tx * y + s * z, ty * y + c, ty * z - s * x, 0,
  3454. tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
  3455. 0, 0, 0, 1
  3456. );
  3457. return this;
  3458. }
  3459. makeScale( x, y, z ) {
  3460. this.set(
  3461. x, 0, 0, 0,
  3462. 0, y, 0, 0,
  3463. 0, 0, z, 0,
  3464. 0, 0, 0, 1
  3465. );
  3466. return this;
  3467. }
  3468. makeShear( x, y, z ) {
  3469. this.set(
  3470. 1, y, z, 0,
  3471. x, 1, z, 0,
  3472. x, y, 1, 0,
  3473. 0, 0, 0, 1
  3474. );
  3475. return this;
  3476. }
  3477. compose( position, quaternion, scale ) {
  3478. const te = this.elements;
  3479. const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
  3480. const x2 = x + x, y2 = y + y, z2 = z + z;
  3481. const xx = x * x2, xy = x * y2, xz = x * z2;
  3482. const yy = y * y2, yz = y * z2, zz = z * z2;
  3483. const wx = w * x2, wy = w * y2, wz = w * z2;
  3484. const sx = scale.x, sy = scale.y, sz = scale.z;
  3485. te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
  3486. te[ 1 ] = ( xy + wz ) * sx;
  3487. te[ 2 ] = ( xz - wy ) * sx;
  3488. te[ 3 ] = 0;
  3489. te[ 4 ] = ( xy - wz ) * sy;
  3490. te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
  3491. te[ 6 ] = ( yz + wx ) * sy;
  3492. te[ 7 ] = 0;
  3493. te[ 8 ] = ( xz + wy ) * sz;
  3494. te[ 9 ] = ( yz - wx ) * sz;
  3495. te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
  3496. te[ 11 ] = 0;
  3497. te[ 12 ] = position.x;
  3498. te[ 13 ] = position.y;
  3499. te[ 14 ] = position.z;
  3500. te[ 15 ] = 1;
  3501. return this;
  3502. }
  3503. decompose( position, quaternion, scale ) {
  3504. const te = this.elements;
  3505. let sx = _v1$1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
  3506. const sy = _v1$1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
  3507. const sz = _v1$1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
  3508. // if determine is negative, we need to invert one scale
  3509. const det = this.determinant();
  3510. if ( det < 0 ) sx = - sx;
  3511. position.x = te[ 12 ];
  3512. position.y = te[ 13 ];
  3513. position.z = te[ 14 ];
  3514. // scale the rotation part
  3515. _m1.copy( this );
  3516. const invSX = 1 / sx;
  3517. const invSY = 1 / sy;
  3518. const invSZ = 1 / sz;
  3519. _m1.elements[ 0 ] *= invSX;
  3520. _m1.elements[ 1 ] *= invSX;
  3521. _m1.elements[ 2 ] *= invSX;
  3522. _m1.elements[ 4 ] *= invSY;
  3523. _m1.elements[ 5 ] *= invSY;
  3524. _m1.elements[ 6 ] *= invSY;
  3525. _m1.elements[ 8 ] *= invSZ;
  3526. _m1.elements[ 9 ] *= invSZ;
  3527. _m1.elements[ 10 ] *= invSZ;
  3528. quaternion.setFromRotationMatrix( _m1 );
  3529. scale.x = sx;
  3530. scale.y = sy;
  3531. scale.z = sz;
  3532. return this;
  3533. }
  3534. makePerspective( left, right, top, bottom, near, far ) {
  3535. if ( far === undefined ) {
  3536. console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
  3537. }
  3538. const te = this.elements;
  3539. const x = 2 * near / ( right - left );
  3540. const y = 2 * near / ( top - bottom );
  3541. const a = ( right + left ) / ( right - left );
  3542. const b = ( top + bottom ) / ( top - bottom );
  3543. const c = - ( far + near ) / ( far - near );
  3544. const d = - 2 * far * near / ( far - near );
  3545. te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
  3546. te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
  3547. te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
  3548. te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
  3549. return this;
  3550. }
  3551. makeOrthographic( left, right, top, bottom, near, far ) {
  3552. const te = this.elements;
  3553. const w = 1.0 / ( right - left );
  3554. const h = 1.0 / ( top - bottom );
  3555. const p = 1.0 / ( far - near );
  3556. const x = ( right + left ) * w;
  3557. const y = ( top + bottom ) * h;
  3558. const z = ( far + near ) * p;
  3559. te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
  3560. te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y;
  3561. te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z;
  3562. te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
  3563. return this;
  3564. }
  3565. equals( matrix ) {
  3566. const te = this.elements;
  3567. const me = matrix.elements;
  3568. for ( let i = 0; i < 16; i ++ ) {
  3569. if ( te[ i ] !== me[ i ] ) return false;
  3570. }
  3571. return true;
  3572. }
  3573. fromArray( array, offset = 0 ) {
  3574. for ( let i = 0; i < 16; i ++ ) {
  3575. this.elements[ i ] = array[ i + offset ];
  3576. }
  3577. return this;
  3578. }
  3579. toArray( array = [], offset = 0 ) {
  3580. const te = this.elements;
  3581. array[ offset ] = te[ 0 ];
  3582. array[ offset + 1 ] = te[ 1 ];
  3583. array[ offset + 2 ] = te[ 2 ];
  3584. array[ offset + 3 ] = te[ 3 ];
  3585. array[ offset + 4 ] = te[ 4 ];
  3586. array[ offset + 5 ] = te[ 5 ];
  3587. array[ offset + 6 ] = te[ 6 ];
  3588. array[ offset + 7 ] = te[ 7 ];
  3589. array[ offset + 8 ] = te[ 8 ];
  3590. array[ offset + 9 ] = te[ 9 ];
  3591. array[ offset + 10 ] = te[ 10 ];
  3592. array[ offset + 11 ] = te[ 11 ];
  3593. array[ offset + 12 ] = te[ 12 ];
  3594. array[ offset + 13 ] = te[ 13 ];
  3595. array[ offset + 14 ] = te[ 14 ];
  3596. array[ offset + 15 ] = te[ 15 ];
  3597. return array;
  3598. }
  3599. }
  3600. const _v1$1 = /*@__PURE__*/ new Vector3();
  3601. const _m1 = /*@__PURE__*/ new Matrix4();
  3602. const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
  3603. const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
  3604. const _x = /*@__PURE__*/ new Vector3();
  3605. const _y = /*@__PURE__*/ new Vector3();
  3606. const _z = /*@__PURE__*/ new Vector3();
  3607. class Euler {
  3608. constructor( x = 0, y = 0, z = 0, order = Euler.DefaultOrder ) {
  3609. Object.defineProperty( this, 'isEuler', { value: true } );
  3610. this._x = x;
  3611. this._y = y;
  3612. this._z = z;
  3613. this._order = order;
  3614. }
  3615. get x() {
  3616. return this._x;
  3617. }
  3618. set x( value ) {
  3619. this._x = value;
  3620. this._onChangeCallback();
  3621. }
  3622. get y() {
  3623. return this._y;
  3624. }
  3625. set y( value ) {
  3626. this._y = value;
  3627. this._onChangeCallback();
  3628. }
  3629. get z() {
  3630. return this._z;
  3631. }
  3632. set z( value ) {
  3633. this._z = value;
  3634. this._onChangeCallback();
  3635. }
  3636. get order() {
  3637. return this._order;
  3638. }
  3639. set order( value ) {
  3640. this._order = value;
  3641. this._onChangeCallback();
  3642. }
  3643. set( x, y, z, order ) {
  3644. this._x = x;
  3645. this._y = y;
  3646. this._z = z;
  3647. this._order = order || this._order;
  3648. this._onChangeCallback();
  3649. return this;
  3650. }
  3651. clone() {
  3652. return new this.constructor( this._x, this._y, this._z, this._order );
  3653. }
  3654. copy( euler ) {
  3655. this._x = euler._x;
  3656. this._y = euler._y;
  3657. this._z = euler._z;
  3658. this._order = euler._order;
  3659. this._onChangeCallback();
  3660. return this;
  3661. }
  3662. setFromRotationMatrix( m, order, update ) {
  3663. const clamp = MathUtils$1.clamp;
  3664. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  3665. const te = m.elements;
  3666. const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
  3667. const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
  3668. const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
  3669. order = order || this._order;
  3670. switch ( order ) {
  3671. case 'XYZ':
  3672. this._y = Math.asin( clamp( m13, - 1, 1 ) );
  3673. if ( Math.abs( m13 ) < 0.9999999 ) {
  3674. this._x = Math.atan2( - m23, m33 );
  3675. this._z = Math.atan2( - m12, m11 );
  3676. } else {
  3677. this._x = Math.atan2( m32, m22 );
  3678. this._z = 0;
  3679. }
  3680. break;
  3681. case 'YXZ':
  3682. this._x = Math.asin( - clamp( m23, - 1, 1 ) );
  3683. if ( Math.abs( m23 ) < 0.9999999 ) {
  3684. this._y = Math.atan2( m13, m33 );
  3685. this._z = Math.atan2( m21, m22 );
  3686. } else {
  3687. this._y = Math.atan2( - m31, m11 );
  3688. this._z = 0;
  3689. }
  3690. break;
  3691. case 'ZXY':
  3692. this._x = Math.asin( clamp( m32, - 1, 1 ) );
  3693. if ( Math.abs( m32 ) < 0.9999999 ) {
  3694. this._y = Math.atan2( - m31, m33 );
  3695. this._z = Math.atan2( - m12, m22 );
  3696. } else {
  3697. this._y = 0;
  3698. this._z = Math.atan2( m21, m11 );
  3699. }
  3700. break;
  3701. case 'ZYX':
  3702. this._y = Math.asin( - clamp( m31, - 1, 1 ) );
  3703. if ( Math.abs( m31 ) < 0.9999999 ) {
  3704. this._x = Math.atan2( m32, m33 );
  3705. this._z = Math.atan2( m21, m11 );
  3706. } else {
  3707. this._x = 0;
  3708. this._z = Math.atan2( - m12, m22 );
  3709. }
  3710. break;
  3711. case 'YZX':
  3712. this._z = Math.asin( clamp( m21, - 1, 1 ) );
  3713. if ( Math.abs( m21 ) < 0.9999999 ) {
  3714. this._x = Math.atan2( - m23, m22 );
  3715. this._y = Math.atan2( - m31, m11 );
  3716. } else {
  3717. this._x = 0;
  3718. this._y = Math.atan2( m13, m33 );
  3719. }
  3720. break;
  3721. case 'XZY':
  3722. this._z = Math.asin( - clamp( m12, - 1, 1 ) );
  3723. if ( Math.abs( m12 ) < 0.9999999 ) {
  3724. this._x = Math.atan2( m32, m22 );
  3725. this._y = Math.atan2( m13, m11 );
  3726. } else {
  3727. this._x = Math.atan2( - m23, m33 );
  3728. this._y = 0;
  3729. }
  3730. break;
  3731. default:
  3732. console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
  3733. }
  3734. this._order = order;
  3735. if ( update !== false ) this._onChangeCallback();
  3736. return this;
  3737. }
  3738. setFromQuaternion( q, order, update ) {
  3739. _matrix.makeRotationFromQuaternion( q );
  3740. return this.setFromRotationMatrix( _matrix, order, update );
  3741. }
  3742. setFromVector3( v, order ) {
  3743. return this.set( v.x, v.y, v.z, order || this._order );
  3744. }
  3745. reorder( newOrder ) {
  3746. // WARNING: this discards revolution information -bhouston
  3747. _quaternion$1.setFromEuler( this );
  3748. return this.setFromQuaternion( _quaternion$1, newOrder );
  3749. }
  3750. equals( euler ) {
  3751. return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
  3752. }
  3753. fromArray( array ) {
  3754. this._x = array[ 0 ];
  3755. this._y = array[ 1 ];
  3756. this._z = array[ 2 ];
  3757. if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
  3758. this._onChangeCallback();
  3759. return this;
  3760. }
  3761. toArray( array = [], offset = 0 ) {
  3762. array[ offset ] = this._x;
  3763. array[ offset + 1 ] = this._y;
  3764. array[ offset + 2 ] = this._z;
  3765. array[ offset + 3 ] = this._order;
  3766. return array;
  3767. }
  3768. toVector3( optionalResult ) {
  3769. if ( optionalResult ) {
  3770. return optionalResult.set( this._x, this._y, this._z );
  3771. } else {
  3772. return new Vector3( this._x, this._y, this._z );
  3773. }
  3774. }
  3775. _onChange( callback ) {
  3776. this._onChangeCallback = callback;
  3777. return this;
  3778. }
  3779. _onChangeCallback() {}
  3780. }
  3781. Euler.DefaultOrder = 'XYZ';
  3782. Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
  3783. const _matrix = /*@__PURE__*/ new Matrix4();
  3784. const _quaternion$1 = /*@__PURE__*/ new Quaternion();
  3785. class Layers {
  3786. constructor() {
  3787. this.mask = 1 | 0;
  3788. }
  3789. set( channel ) {
  3790. this.mask = 1 << channel | 0;
  3791. }
  3792. enable( channel ) {
  3793. this.mask |= 1 << channel | 0;
  3794. }
  3795. enableAll() {
  3796. this.mask = 0xffffffff | 0;
  3797. }
  3798. toggle( channel ) {
  3799. this.mask ^= 1 << channel | 0;
  3800. }
  3801. disable( channel ) {
  3802. this.mask &= ~ ( 1 << channel | 0 );
  3803. }
  3804. disableAll() {
  3805. this.mask = 0;
  3806. }
  3807. test( layers ) {
  3808. return ( this.mask & layers.mask ) !== 0;
  3809. }
  3810. }
  3811. let _object3DId = 0;
  3812. const _v1$2 = new Vector3();
  3813. const _q1 = new Quaternion();
  3814. const _m1$1 = new Matrix4();
  3815. const _target = new Vector3();
  3816. const _position = new Vector3();
  3817. const _scale = new Vector3();
  3818. const _quaternion$2 = new Quaternion();
  3819. const _xAxis = new Vector3( 1, 0, 0 );
  3820. const _yAxis = new Vector3( 0, 1, 0 );
  3821. const _zAxis = new Vector3( 0, 0, 1 );
  3822. const _addedEvent = { type: 'added' };
  3823. const _removedEvent = { type: 'removed' };
  3824. function Object3D() {
  3825. Object.defineProperty( this, 'id', { value: _object3DId ++ } );
  3826. this.uuid = MathUtils$1.generateUUID();
  3827. this.name = '';
  3828. this.type = 'Object3D';
  3829. this.parent = null;
  3830. this.children = [];
  3831. this.up = Object3D.DefaultUp.clone();
  3832. const position = new Vector3();
  3833. const rotation = new Euler();
  3834. const quaternion = new Quaternion();
  3835. const scale = new Vector3( 1, 1, 1 );
  3836. function onRotationChange() {
  3837. quaternion.setFromEuler( rotation, false );
  3838. }
  3839. function onQuaternionChange() {
  3840. rotation.setFromQuaternion( quaternion, undefined, false );
  3841. }
  3842. rotation._onChange( onRotationChange );
  3843. quaternion._onChange( onQuaternionChange );
  3844. Object.defineProperties( this, {
  3845. position: {
  3846. configurable: true,
  3847. enumerable: true,
  3848. value: position
  3849. },
  3850. rotation: {
  3851. configurable: true,
  3852. enumerable: true,
  3853. value: rotation
  3854. },
  3855. quaternion: {
  3856. configurable: true,
  3857. enumerable: true,
  3858. value: quaternion
  3859. },
  3860. scale: {
  3861. configurable: true,
  3862. enumerable: true,
  3863. value: scale
  3864. },
  3865. modelViewMatrix: {
  3866. value: new Matrix4()
  3867. },
  3868. normalMatrix: {
  3869. value: new Matrix3()
  3870. }
  3871. } );
  3872. this.matrix = new Matrix4();
  3873. this.matrixWorld = new Matrix4();
  3874. this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
  3875. this.matrixWorldNeedsUpdate = false;
  3876. this.layers = new Layers();
  3877. this.visible = true;
  3878. this.castShadow = false;
  3879. this.receiveShadow = false;
  3880. this.frustumCulled = true;
  3881. this.renderOrder = 0;
  3882. this.animations = [];
  3883. this.userData = {};
  3884. }
  3885. Object3D.DefaultUp = new Vector3( 0, 1, 0 );
  3886. Object3D.DefaultMatrixAutoUpdate = true;
  3887. Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
  3888. constructor: Object3D,
  3889. isObject3D: true,
  3890. onBeforeRender: function () {},
  3891. onAfterRender: function () {},
  3892. applyMatrix4: function ( matrix ) {
  3893. if ( this.matrixAutoUpdate ) this.updateMatrix();
  3894. this.matrix.premultiply( matrix );
  3895. this.matrix.decompose( this.position, this.quaternion, this.scale );
  3896. },
  3897. applyQuaternion: function ( q ) {
  3898. this.quaternion.premultiply( q );
  3899. return this;
  3900. },
  3901. setRotationFromAxisAngle: function ( axis, angle ) {
  3902. // assumes axis is normalized
  3903. this.quaternion.setFromAxisAngle( axis, angle );
  3904. },
  3905. setRotationFromEuler: function ( euler ) {
  3906. this.quaternion.setFromEuler( euler, true );
  3907. },
  3908. setRotationFromMatrix: function ( m ) {
  3909. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  3910. this.quaternion.setFromRotationMatrix( m );
  3911. },
  3912. setRotationFromQuaternion: function ( q ) {
  3913. // assumes q is normalized
  3914. this.quaternion.copy( q );
  3915. },
  3916. rotateOnAxis: function ( axis, angle ) {
  3917. // rotate object on axis in object space
  3918. // axis is assumed to be normalized
  3919. _q1.setFromAxisAngle( axis, angle );
  3920. this.quaternion.multiply( _q1 );
  3921. return this;
  3922. },
  3923. rotateOnWorldAxis: function ( axis, angle ) {
  3924. // rotate object on axis in world space
  3925. // axis is assumed to be normalized
  3926. // method assumes no rotated parent
  3927. _q1.setFromAxisAngle( axis, angle );
  3928. this.quaternion.premultiply( _q1 );
  3929. return this;
  3930. },
  3931. rotateX: function ( angle ) {
  3932. return this.rotateOnAxis( _xAxis, angle );
  3933. },
  3934. rotateY: function ( angle ) {
  3935. return this.rotateOnAxis( _yAxis, angle );
  3936. },
  3937. rotateZ: function ( angle ) {
  3938. return this.rotateOnAxis( _zAxis, angle );
  3939. },
  3940. translateOnAxis: function ( axis, distance ) {
  3941. // translate object by distance along axis in object space
  3942. // axis is assumed to be normalized
  3943. _v1$2.copy( axis ).applyQuaternion( this.quaternion );
  3944. this.position.add( _v1$2.multiplyScalar( distance ) );
  3945. return this;
  3946. },
  3947. translateX: function ( distance ) {
  3948. return this.translateOnAxis( _xAxis, distance );
  3949. },
  3950. translateY: function ( distance ) {
  3951. return this.translateOnAxis( _yAxis, distance );
  3952. },
  3953. translateZ: function ( distance ) {
  3954. return this.translateOnAxis( _zAxis, distance );
  3955. },
  3956. localToWorld: function ( vector ) {
  3957. return vector.applyMatrix4( this.matrixWorld );
  3958. },
  3959. worldToLocal: function ( vector ) {
  3960. return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
  3961. },
  3962. lookAt: function ( x, y, z ) {
  3963. // This method does not support objects having non-uniformly-scaled parent(s)
  3964. if ( x.isVector3 ) {
  3965. _target.copy( x );
  3966. } else {
  3967. _target.set( x, y, z );
  3968. }
  3969. const parent = this.parent;
  3970. this.updateWorldMatrix( true, false );
  3971. _position.setFromMatrixPosition( this.matrixWorld );
  3972. if ( this.isCamera || this.isLight ) {
  3973. _m1$1.lookAt( _position, _target, this.up );
  3974. } else {
  3975. _m1$1.lookAt( _target, _position, this.up );
  3976. }
  3977. this.quaternion.setFromRotationMatrix( _m1$1 );
  3978. if ( parent ) {
  3979. _m1$1.extractRotation( parent.matrixWorld );
  3980. _q1.setFromRotationMatrix( _m1$1 );
  3981. this.quaternion.premultiply( _q1.invert() );
  3982. }
  3983. },
  3984. add: function ( object ) {
  3985. if ( arguments.length > 1 ) {
  3986. for ( let i = 0; i < arguments.length; i ++ ) {
  3987. this.add( arguments[ i ] );
  3988. }
  3989. return this;
  3990. }
  3991. if ( object === this ) {
  3992. console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
  3993. return this;
  3994. }
  3995. if ( object && object.isObject3D ) {
  3996. if ( object.parent !== null ) {
  3997. object.parent.remove( object );
  3998. }
  3999. object.parent = this;
  4000. this.children.push( object );
  4001. object.dispatchEvent( _addedEvent );
  4002. } else {
  4003. console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
  4004. }
  4005. return this;
  4006. },
  4007. remove: function ( object ) {
  4008. if ( arguments.length > 1 ) {
  4009. for ( let i = 0; i < arguments.length; i ++ ) {
  4010. this.remove( arguments[ i ] );
  4011. }
  4012. return this;
  4013. }
  4014. const index = this.children.indexOf( object );
  4015. if ( index !== - 1 ) {
  4016. object.parent = null;
  4017. this.children.splice( index, 1 );
  4018. object.dispatchEvent( _removedEvent );
  4019. }
  4020. return this;
  4021. },
  4022. clear: function () {
  4023. for ( let i = 0; i < this.children.length; i ++ ) {
  4024. const object = this.children[ i ];
  4025. object.parent = null;
  4026. object.dispatchEvent( _removedEvent );
  4027. }
  4028. this.children.length = 0;
  4029. return this;
  4030. },
  4031. attach: function ( object ) {
  4032. // adds object as a child of this, while maintaining the object's world transform
  4033. this.updateWorldMatrix( true, false );
  4034. _m1$1.copy( this.matrixWorld ).invert();
  4035. if ( object.parent !== null ) {
  4036. object.parent.updateWorldMatrix( true, false );
  4037. _m1$1.multiply( object.parent.matrixWorld );
  4038. }
  4039. object.applyMatrix4( _m1$1 );
  4040. object.updateWorldMatrix( false, false );
  4041. this.add( object );
  4042. return this;
  4043. },
  4044. getObjectById: function ( id ) {
  4045. return this.getObjectByProperty( 'id', id );
  4046. },
  4047. getObjectByName: function ( name ) {
  4048. return this.getObjectByProperty( 'name', name );
  4049. },
  4050. getObjectByProperty: function ( name, value ) {
  4051. if ( this[ name ] === value ) return this;
  4052. for ( let i = 0, l = this.children.length; i < l; i ++ ) {
  4053. const child = this.children[ i ];
  4054. const object = child.getObjectByProperty( name, value );
  4055. if ( object !== undefined ) {
  4056. return object;
  4057. }
  4058. }
  4059. return undefined;
  4060. },
  4061. getWorldPosition: function ( target ) {
  4062. if ( target === undefined ) {
  4063. console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
  4064. target = new Vector3();
  4065. }
  4066. this.updateWorldMatrix( true, false );
  4067. return target.setFromMatrixPosition( this.matrixWorld );
  4068. },
  4069. getWorldQuaternion: function ( target ) {
  4070. if ( target === undefined ) {
  4071. console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
  4072. target = new Quaternion();
  4073. }
  4074. this.updateWorldMatrix( true, false );
  4075. this.matrixWorld.decompose( _position, target, _scale );
  4076. return target;
  4077. },
  4078. getWorldScale: function ( target ) {
  4079. if ( target === undefined ) {
  4080. console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
  4081. target = new Vector3();
  4082. }
  4083. this.updateWorldMatrix( true, false );
  4084. this.matrixWorld.decompose( _position, _quaternion$2, target );
  4085. return target;
  4086. },
  4087. getWorldDirection: function ( target ) {
  4088. if ( target === undefined ) {
  4089. console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
  4090. target = new Vector3();
  4091. }
  4092. this.updateWorldMatrix( true, false );
  4093. const e = this.matrixWorld.elements;
  4094. return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
  4095. },
  4096. raycast: function () {},
  4097. traverse: function ( callback ) {
  4098. callback( this );
  4099. const children = this.children;
  4100. for ( let i = 0, l = children.length; i < l; i ++ ) {
  4101. children[ i ].traverse( callback );
  4102. }
  4103. },
  4104. traverseVisible: function ( callback ) {
  4105. if ( this.visible === false ) return;
  4106. callback( this );
  4107. const children = this.children;
  4108. for ( let i = 0, l = children.length; i < l; i ++ ) {
  4109. children[ i ].traverseVisible( callback );
  4110. }
  4111. },
  4112. traverseAncestors: function ( callback ) {
  4113. const parent = this.parent;
  4114. if ( parent !== null ) {
  4115. callback( parent );
  4116. parent.traverseAncestors( callback );
  4117. }
  4118. },
  4119. updateMatrix: function () {
  4120. this.matrix.compose( this.position, this.quaternion, this.scale );
  4121. this.matrixWorldNeedsUpdate = true;
  4122. },
  4123. updateMatrixWorld: function ( force ) {
  4124. if ( this.matrixAutoUpdate ) this.updateMatrix();
  4125. if ( this.matrixWorldNeedsUpdate || force ) {
  4126. if ( this.parent === null ) {
  4127. this.matrixWorld.copy( this.matrix );
  4128. } else {
  4129. this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
  4130. }
  4131. this.matrixWorldNeedsUpdate = false;
  4132. force = true;
  4133. }
  4134. // update children
  4135. const children = this.children;
  4136. for ( let i = 0, l = children.length; i < l; i ++ ) {
  4137. children[ i ].updateMatrixWorld( force );
  4138. }
  4139. },
  4140. updateWorldMatrix: function ( updateParents, updateChildren ) {
  4141. const parent = this.parent;
  4142. if ( updateParents === true && parent !== null ) {
  4143. parent.updateWorldMatrix( true, false );
  4144. }
  4145. if ( this.matrixAutoUpdate ) this.updateMatrix();
  4146. if ( this.parent === null ) {
  4147. this.matrixWorld.copy( this.matrix );
  4148. } else {
  4149. this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
  4150. }
  4151. // update children
  4152. if ( updateChildren === true ) {
  4153. const children = this.children;
  4154. for ( let i = 0, l = children.length; i < l; i ++ ) {
  4155. children[ i ].updateWorldMatrix( false, true );
  4156. }
  4157. }
  4158. },
  4159. toJSON: function ( meta ) {
  4160. // meta is a string when called from JSON.stringify
  4161. const isRootObject = ( meta === undefined || typeof meta === 'string' );
  4162. const output = {};
  4163. // meta is a hash used to collect geometries, materials.
  4164. // not providing it implies that this is the root object
  4165. // being serialized.
  4166. if ( isRootObject ) {
  4167. // initialize meta obj
  4168. meta = {
  4169. geometries: {},
  4170. materials: {},
  4171. textures: {},
  4172. images: {},
  4173. shapes: {},
  4174. skeletons: {},
  4175. animations: {}
  4176. };
  4177. output.metadata = {
  4178. version: 4.5,
  4179. type: 'Object',
  4180. generator: 'Object3D.toJSON'
  4181. };
  4182. }
  4183. // standard Object3D serialization
  4184. const object = {};
  4185. object.uuid = this.uuid;
  4186. object.type = this.type;
  4187. if ( this.name !== '' ) object.name = this.name;
  4188. if ( this.castShadow === true ) object.castShadow = true;
  4189. if ( this.receiveShadow === true ) object.receiveShadow = true;
  4190. if ( this.visible === false ) object.visible = false;
  4191. if ( this.frustumCulled === false ) object.frustumCulled = false;
  4192. if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
  4193. if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
  4194. object.layers = this.layers.mask;
  4195. object.matrix = this.matrix.toArray();
  4196. if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
  4197. // object specific properties
  4198. if ( this.isInstancedMesh ) {
  4199. object.type = 'InstancedMesh';
  4200. object.count = this.count;
  4201. object.instanceMatrix = this.instanceMatrix.toJSON();
  4202. }
  4203. //
  4204. function serialize( library, element ) {
  4205. if ( library[ element.uuid ] === undefined ) {
  4206. library[ element.uuid ] = element.toJSON( meta );
  4207. }
  4208. return element.uuid;
  4209. }
  4210. if ( this.isMesh || this.isLine || this.isPoints ) {
  4211. object.geometry = serialize( meta.geometries, this.geometry );
  4212. const parameters = this.geometry.parameters;
  4213. if ( parameters !== undefined && parameters.shapes !== undefined ) {
  4214. const shapes = parameters.shapes;
  4215. if ( Array.isArray( shapes ) ) {
  4216. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  4217. const shape = shapes[ i ];
  4218. serialize( meta.shapes, shape );
  4219. }
  4220. } else {
  4221. serialize( meta.shapes, shapes );
  4222. }
  4223. }
  4224. }
  4225. if ( this.isSkinnedMesh ) {
  4226. object.bindMode = this.bindMode;
  4227. object.bindMatrix = this.bindMatrix.toArray();
  4228. if ( this.skeleton !== undefined ) {
  4229. serialize( meta.skeletons, this.skeleton );
  4230. object.skeleton = this.skeleton.uuid;
  4231. }
  4232. }
  4233. if ( this.material !== undefined ) {
  4234. if ( Array.isArray( this.material ) ) {
  4235. const uuids = [];
  4236. for ( let i = 0, l = this.material.length; i < l; i ++ ) {
  4237. uuids.push( serialize( meta.materials, this.material[ i ] ) );
  4238. }
  4239. object.material = uuids;
  4240. } else {
  4241. object.material = serialize( meta.materials, this.material );
  4242. }
  4243. }
  4244. //
  4245. if ( this.children.length > 0 ) {
  4246. object.children = [];
  4247. for ( let i = 0; i < this.children.length; i ++ ) {
  4248. object.children.push( this.children[ i ].toJSON( meta ).object );
  4249. }
  4250. }
  4251. //
  4252. if ( this.animations.length > 0 ) {
  4253. object.animations = [];
  4254. for ( let i = 0; i < this.animations.length; i ++ ) {
  4255. const animation = this.animations[ i ];
  4256. object.animations.push( serialize( meta.animations, animation ) );
  4257. }
  4258. }
  4259. if ( isRootObject ) {
  4260. const geometries = extractFromCache( meta.geometries );
  4261. const materials = extractFromCache( meta.materials );
  4262. const textures = extractFromCache( meta.textures );
  4263. const images = extractFromCache( meta.images );
  4264. const shapes = extractFromCache( meta.shapes );
  4265. const skeletons = extractFromCache( meta.skeletons );
  4266. const animations = extractFromCache( meta.animations );
  4267. if ( geometries.length > 0 ) output.geometries = geometries;
  4268. if ( materials.length > 0 ) output.materials = materials;
  4269. if ( textures.length > 0 ) output.textures = textures;
  4270. if ( images.length > 0 ) output.images = images;
  4271. if ( shapes.length > 0 ) output.shapes = shapes;
  4272. if ( skeletons.length > 0 ) output.skeletons = skeletons;
  4273. if ( animations.length > 0 ) output.animations = animations;
  4274. }
  4275. output.object = object;
  4276. return output;
  4277. // extract data from the cache hash
  4278. // remove metadata on each item
  4279. // and return as array
  4280. function extractFromCache( cache ) {
  4281. const values = [];
  4282. for ( const key in cache ) {
  4283. const data = cache[ key ];
  4284. delete data.metadata;
  4285. values.push( data );
  4286. }
  4287. return values;
  4288. }
  4289. },
  4290. clone: function ( recursive ) {
  4291. return new this.constructor().copy( this, recursive );
  4292. },
  4293. copy: function ( source, recursive = true ) {
  4294. this.name = source.name;
  4295. this.up.copy( source.up );
  4296. this.position.copy( source.position );
  4297. this.rotation.order = source.rotation.order;
  4298. this.quaternion.copy( source.quaternion );
  4299. this.scale.copy( source.scale );
  4300. this.matrix.copy( source.matrix );
  4301. this.matrixWorld.copy( source.matrixWorld );
  4302. this.matrixAutoUpdate = source.matrixAutoUpdate;
  4303. this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
  4304. this.layers.mask = source.layers.mask;
  4305. this.visible = source.visible;
  4306. this.castShadow = source.castShadow;
  4307. this.receiveShadow = source.receiveShadow;
  4308. this.frustumCulled = source.frustumCulled;
  4309. this.renderOrder = source.renderOrder;
  4310. this.userData = JSON.parse( JSON.stringify( source.userData ) );
  4311. if ( recursive === true ) {
  4312. for ( let i = 0; i < source.children.length; i ++ ) {
  4313. const child = source.children[ i ];
  4314. this.add( child.clone() );
  4315. }
  4316. }
  4317. return this;
  4318. }
  4319. } );
  4320. const _vector1 = /*@__PURE__*/ new Vector3();
  4321. const _vector2 = /*@__PURE__*/ new Vector3();
  4322. const _normalMatrix = /*@__PURE__*/ new Matrix3();
  4323. class Plane {
  4324. constructor( normal, constant ) {
  4325. Object.defineProperty( this, 'isPlane', { value: true } );
  4326. // normal is assumed to be normalized
  4327. this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
  4328. this.constant = ( constant !== undefined ) ? constant : 0;
  4329. }
  4330. set( normal, constant ) {
  4331. this.normal.copy( normal );
  4332. this.constant = constant;
  4333. return this;
  4334. }
  4335. setComponents( x, y, z, w ) {
  4336. this.normal.set( x, y, z );
  4337. this.constant = w;
  4338. return this;
  4339. }
  4340. setFromNormalAndCoplanarPoint( normal, point ) {
  4341. this.normal.copy( normal );
  4342. this.constant = - point.dot( this.normal );
  4343. return this;
  4344. }
  4345. setFromCoplanarPoints( a, b, c ) {
  4346. const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
  4347. // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
  4348. this.setFromNormalAndCoplanarPoint( normal, a );
  4349. return this;
  4350. }
  4351. clone() {
  4352. return new this.constructor().copy( this );
  4353. }
  4354. copy( plane ) {
  4355. this.normal.copy( plane.normal );
  4356. this.constant = plane.constant;
  4357. return this;
  4358. }
  4359. normalize() {
  4360. // Note: will lead to a divide by zero if the plane is invalid.
  4361. const inverseNormalLength = 1.0 / this.normal.length();
  4362. this.normal.multiplyScalar( inverseNormalLength );
  4363. this.constant *= inverseNormalLength;
  4364. return this;
  4365. }
  4366. negate() {
  4367. this.constant *= - 1;
  4368. this.normal.negate();
  4369. return this;
  4370. }
  4371. distanceToPoint( point ) {
  4372. return this.normal.dot( point ) + this.constant;
  4373. }
  4374. distanceToSphere( sphere ) {
  4375. return this.distanceToPoint( sphere.center ) - sphere.radius;
  4376. }
  4377. projectPoint( point, target ) {
  4378. if ( target === undefined ) {
  4379. console.warn( 'THREE.Plane: .projectPoint() target is now required' );
  4380. target = new Vector3();
  4381. }
  4382. return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
  4383. }
  4384. intersectLine( line, target ) {
  4385. if ( target === undefined ) {
  4386. console.warn( 'THREE.Plane: .intersectLine() target is now required' );
  4387. target = new Vector3();
  4388. }
  4389. const direction = line.delta( _vector1 );
  4390. const denominator = this.normal.dot( direction );
  4391. if ( denominator === 0 ) {
  4392. // line is coplanar, return origin
  4393. if ( this.distanceToPoint( line.start ) === 0 ) {
  4394. return target.copy( line.start );
  4395. }
  4396. // Unsure if this is the correct method to handle this case.
  4397. return undefined;
  4398. }
  4399. const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
  4400. if ( t < 0 || t > 1 ) {
  4401. return undefined;
  4402. }
  4403. return target.copy( direction ).multiplyScalar( t ).add( line.start );
  4404. }
  4405. intersectsLine( line ) {
  4406. // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
  4407. const startSign = this.distanceToPoint( line.start );
  4408. const endSign = this.distanceToPoint( line.end );
  4409. return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
  4410. }
  4411. intersectsBox( box ) {
  4412. return box.intersectsPlane( this );
  4413. }
  4414. intersectsSphere( sphere ) {
  4415. return sphere.intersectsPlane( this );
  4416. }
  4417. coplanarPoint( target ) {
  4418. if ( target === undefined ) {
  4419. console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
  4420. target = new Vector3();
  4421. }
  4422. return target.copy( this.normal ).multiplyScalar( - this.constant );
  4423. }
  4424. applyMatrix4( matrix, optionalNormalMatrix ) {
  4425. const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
  4426. const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
  4427. const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
  4428. this.constant = - referencePoint.dot( normal );
  4429. return this;
  4430. }
  4431. translate( offset ) {
  4432. this.constant -= offset.dot( this.normal );
  4433. return this;
  4434. }
  4435. equals( plane ) {
  4436. return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
  4437. }
  4438. }
  4439. const _v0$1 = /*@__PURE__*/ new Vector3();
  4440. const _v1$3 = /*@__PURE__*/ new Vector3();
  4441. const _v2$1 = /*@__PURE__*/ new Vector3();
  4442. const _v3 = /*@__PURE__*/ new Vector3();
  4443. const _vab = /*@__PURE__*/ new Vector3();
  4444. const _vac = /*@__PURE__*/ new Vector3();
  4445. const _vbc = /*@__PURE__*/ new Vector3();
  4446. const _vap = /*@__PURE__*/ new Vector3();
  4447. const _vbp = /*@__PURE__*/ new Vector3();
  4448. const _vcp = /*@__PURE__*/ new Vector3();
  4449. class Triangle {
  4450. constructor( a, b, c ) {
  4451. this.a = ( a !== undefined ) ? a : new Vector3();
  4452. this.b = ( b !== undefined ) ? b : new Vector3();
  4453. this.c = ( c !== undefined ) ? c : new Vector3();
  4454. }
  4455. static getNormal( a, b, c, target ) {
  4456. if ( target === undefined ) {
  4457. console.warn( 'THREE.Triangle: .getNormal() target is now required' );
  4458. target = new Vector3();
  4459. }
  4460. target.subVectors( c, b );
  4461. _v0$1.subVectors( a, b );
  4462. target.cross( _v0$1 );
  4463. const targetLengthSq = target.lengthSq();
  4464. if ( targetLengthSq > 0 ) {
  4465. return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
  4466. }
  4467. return target.set( 0, 0, 0 );
  4468. }
  4469. // static/instance method to calculate barycentric coordinates
  4470. // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
  4471. static getBarycoord( point, a, b, c, target ) {
  4472. _v0$1.subVectors( c, a );
  4473. _v1$3.subVectors( b, a );
  4474. _v2$1.subVectors( point, a );
  4475. const dot00 = _v0$1.dot( _v0$1 );
  4476. const dot01 = _v0$1.dot( _v1$3 );
  4477. const dot02 = _v0$1.dot( _v2$1 );
  4478. const dot11 = _v1$3.dot( _v1$3 );
  4479. const dot12 = _v1$3.dot( _v2$1 );
  4480. const denom = ( dot00 * dot11 - dot01 * dot01 );
  4481. if ( target === undefined ) {
  4482. console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
  4483. target = new Vector3();
  4484. }
  4485. // collinear or singular triangle
  4486. if ( denom === 0 ) {
  4487. // arbitrary location outside of triangle?
  4488. // not sure if this is the best idea, maybe should be returning undefined
  4489. return target.set( - 2, - 1, - 1 );
  4490. }
  4491. const invDenom = 1 / denom;
  4492. const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
  4493. const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
  4494. // barycentric coordinates must always sum to 1
  4495. return target.set( 1 - u - v, v, u );
  4496. }
  4497. static containsPoint( point, a, b, c ) {
  4498. this.getBarycoord( point, a, b, c, _v3 );
  4499. return ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );
  4500. }
  4501. static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
  4502. this.getBarycoord( point, p1, p2, p3, _v3 );
  4503. target.set( 0, 0 );
  4504. target.addScaledVector( uv1, _v3.x );
  4505. target.addScaledVector( uv2, _v3.y );
  4506. target.addScaledVector( uv3, _v3.z );
  4507. return target;
  4508. }
  4509. static isFrontFacing( a, b, c, direction ) {
  4510. _v0$1.subVectors( c, b );
  4511. _v1$3.subVectors( a, b );
  4512. // strictly front facing
  4513. return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
  4514. }
  4515. set( a, b, c ) {
  4516. this.a.copy( a );
  4517. this.b.copy( b );
  4518. this.c.copy( c );
  4519. return this;
  4520. }
  4521. setFromPointsAndIndices( points, i0, i1, i2 ) {
  4522. this.a.copy( points[ i0 ] );
  4523. this.b.copy( points[ i1 ] );
  4524. this.c.copy( points[ i2 ] );
  4525. return this;
  4526. }
  4527. clone() {
  4528. return new this.constructor().copy( this );
  4529. }
  4530. copy( triangle ) {
  4531. this.a.copy( triangle.a );
  4532. this.b.copy( triangle.b );
  4533. this.c.copy( triangle.c );
  4534. return this;
  4535. }
  4536. getArea() {
  4537. _v0$1.subVectors( this.c, this.b );
  4538. _v1$3.subVectors( this.a, this.b );
  4539. return _v0$1.cross( _v1$3 ).length() * 0.5;
  4540. }
  4541. getMidpoint( target ) {
  4542. if ( target === undefined ) {
  4543. console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
  4544. target = new Vector3();
  4545. }
  4546. return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
  4547. }
  4548. getNormal( target ) {
  4549. return Triangle.getNormal( this.a, this.b, this.c, target );
  4550. }
  4551. getPlane( target ) {
  4552. if ( target === undefined ) {
  4553. console.warn( 'THREE.Triangle: .getPlane() target is now required' );
  4554. target = new Plane();
  4555. }
  4556. return target.setFromCoplanarPoints( this.a, this.b, this.c );
  4557. }
  4558. getBarycoord( point, target ) {
  4559. return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
  4560. }
  4561. getUV( point, uv1, uv2, uv3, target ) {
  4562. return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
  4563. }
  4564. containsPoint( point ) {
  4565. return Triangle.containsPoint( point, this.a, this.b, this.c );
  4566. }
  4567. isFrontFacing( direction ) {
  4568. return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
  4569. }
  4570. intersectsBox( box ) {
  4571. return box.intersectsTriangle( this );
  4572. }
  4573. closestPointToPoint( p, target ) {
  4574. if ( target === undefined ) {
  4575. console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
  4576. target = new Vector3();
  4577. }
  4578. const a = this.a, b = this.b, c = this.c;
  4579. let v, w;
  4580. // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
  4581. // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
  4582. // under the accompanying license; see chapter 5.1.5 for detailed explanation.
  4583. // basically, we're distinguishing which of the voronoi regions of the triangle
  4584. // the point lies in with the minimum amount of redundant computation.
  4585. _vab.subVectors( b, a );
  4586. _vac.subVectors( c, a );
  4587. _vap.subVectors( p, a );
  4588. const d1 = _vab.dot( _vap );
  4589. const d2 = _vac.dot( _vap );
  4590. if ( d1 <= 0 && d2 <= 0 ) {
  4591. // vertex region of A; barycentric coords (1, 0, 0)
  4592. return target.copy( a );
  4593. }
  4594. _vbp.subVectors( p, b );
  4595. const d3 = _vab.dot( _vbp );
  4596. const d4 = _vac.dot( _vbp );
  4597. if ( d3 >= 0 && d4 <= d3 ) {
  4598. // vertex region of B; barycentric coords (0, 1, 0)
  4599. return target.copy( b );
  4600. }
  4601. const vc = d1 * d4 - d3 * d2;
  4602. if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
  4603. v = d1 / ( d1 - d3 );
  4604. // edge region of AB; barycentric coords (1-v, v, 0)
  4605. return target.copy( a ).addScaledVector( _vab, v );
  4606. }
  4607. _vcp.subVectors( p, c );
  4608. const d5 = _vab.dot( _vcp );
  4609. const d6 = _vac.dot( _vcp );
  4610. if ( d6 >= 0 && d5 <= d6 ) {
  4611. // vertex region of C; barycentric coords (0, 0, 1)
  4612. return target.copy( c );
  4613. }
  4614. const vb = d5 * d2 - d1 * d6;
  4615. if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
  4616. w = d2 / ( d2 - d6 );
  4617. // edge region of AC; barycentric coords (1-w, 0, w)
  4618. return target.copy( a ).addScaledVector( _vac, w );
  4619. }
  4620. const va = d3 * d6 - d5 * d4;
  4621. if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
  4622. _vbc.subVectors( c, b );
  4623. w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
  4624. // edge region of BC; barycentric coords (0, 1-w, w)
  4625. return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
  4626. }
  4627. // face region
  4628. const denom = 1 / ( va + vb + vc );
  4629. // u = va * denom
  4630. v = vb * denom;
  4631. w = vc * denom;
  4632. return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
  4633. }
  4634. equals( triangle ) {
  4635. return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
  4636. }
  4637. }
  4638. const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
  4639. 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
  4640. 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
  4641. 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
  4642. 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
  4643. 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
  4644. 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
  4645. 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
  4646. 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
  4647. 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
  4648. 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
  4649. 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
  4650. 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
  4651. 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
  4652. 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
  4653. 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
  4654. 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
  4655. 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
  4656. 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
  4657. 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
  4658. 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
  4659. 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
  4660. 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
  4661. 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
  4662. const _hslA = { h: 0, s: 0, l: 0 };
  4663. const _hslB = { h: 0, s: 0, l: 0 };
  4664. function hue2rgb( p, q, t ) {
  4665. if ( t < 0 ) t += 1;
  4666. if ( t > 1 ) t -= 1;
  4667. if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
  4668. if ( t < 1 / 2 ) return q;
  4669. if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
  4670. return p;
  4671. }
  4672. function SRGBToLinear( c ) {
  4673. return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
  4674. }
  4675. function LinearToSRGB( c ) {
  4676. return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
  4677. }
  4678. class Color {
  4679. constructor( r, g, b ) {
  4680. Object.defineProperty( this, 'isColor', { value: true } );
  4681. if ( g === undefined && b === undefined ) {
  4682. // r is THREE.Color, hex or string
  4683. return this.set( r );
  4684. }
  4685. return this.setRGB( r, g, b );
  4686. }
  4687. set( value ) {
  4688. if ( value && value.isColor ) {
  4689. this.copy( value );
  4690. } else if ( typeof value === 'number' ) {
  4691. this.setHex( value );
  4692. } else if ( typeof value === 'string' ) {
  4693. this.setStyle( value );
  4694. }
  4695. return this;
  4696. }
  4697. setScalar( scalar ) {
  4698. this.r = scalar;
  4699. this.g = scalar;
  4700. this.b = scalar;
  4701. return this;
  4702. }
  4703. setHex( hex ) {
  4704. hex = Math.floor( hex );
  4705. this.r = ( hex >> 16 & 255 ) / 255;
  4706. this.g = ( hex >> 8 & 255 ) / 255;
  4707. this.b = ( hex & 255 ) / 255;
  4708. return this;
  4709. }
  4710. setRGB( r, g, b ) {
  4711. this.r = r;
  4712. this.g = g;
  4713. this.b = b;
  4714. return this;
  4715. }
  4716. setHSL( h, s, l ) {
  4717. // h,s,l ranges are in 0.0 - 1.0
  4718. h = MathUtils$1.euclideanModulo( h, 1 );
  4719. s = MathUtils$1.clamp( s, 0, 1 );
  4720. l = MathUtils$1.clamp( l, 0, 1 );
  4721. if ( s === 0 ) {
  4722. this.r = this.g = this.b = l;
  4723. } else {
  4724. const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
  4725. const q = ( 2 * l ) - p;
  4726. this.r = hue2rgb( q, p, h + 1 / 3 );
  4727. this.g = hue2rgb( q, p, h );
  4728. this.b = hue2rgb( q, p, h - 1 / 3 );
  4729. }
  4730. return this;
  4731. }
  4732. setStyle( style ) {
  4733. function handleAlpha( string ) {
  4734. if ( string === undefined ) return;
  4735. if ( parseFloat( string ) < 1 ) {
  4736. console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
  4737. }
  4738. }
  4739. let m;
  4740. if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
  4741. // rgb / hsl
  4742. let color;
  4743. const name = m[ 1 ];
  4744. const components = m[ 2 ];
  4745. switch ( name ) {
  4746. case 'rgb':
  4747. case 'rgba':
  4748. if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
  4749. // rgb(255,0,0) rgba(255,0,0,0.5)
  4750. this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
  4751. this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
  4752. this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
  4753. handleAlpha( color[ 4 ] );
  4754. return this;
  4755. }
  4756. if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
  4757. // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
  4758. this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
  4759. this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
  4760. this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
  4761. handleAlpha( color[ 4 ] );
  4762. return this;
  4763. }
  4764. break;
  4765. case 'hsl':
  4766. case 'hsla':
  4767. if ( color = /^(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
  4768. // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
  4769. const h = parseFloat( color[ 1 ] ) / 360;
  4770. const s = parseInt( color[ 2 ], 10 ) / 100;
  4771. const l = parseInt( color[ 3 ], 10 ) / 100;
  4772. handleAlpha( color[ 4 ] );
  4773. return this.setHSL( h, s, l );
  4774. }
  4775. break;
  4776. }
  4777. } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
  4778. // hex color
  4779. const hex = m[ 1 ];
  4780. const size = hex.length;
  4781. if ( size === 3 ) {
  4782. // #ff0
  4783. this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
  4784. this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
  4785. this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
  4786. return this;
  4787. } else if ( size === 6 ) {
  4788. // #ff0000
  4789. this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
  4790. this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
  4791. this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
  4792. return this;
  4793. }
  4794. }
  4795. if ( style && style.length > 0 ) {
  4796. return this.setColorName( style );
  4797. }
  4798. return this;
  4799. }
  4800. setColorName( style ) {
  4801. // color keywords
  4802. const hex = _colorKeywords[ style ];
  4803. if ( hex !== undefined ) {
  4804. // red
  4805. this.setHex( hex );
  4806. } else {
  4807. // unknown color
  4808. console.warn( 'THREE.Color: Unknown color ' + style );
  4809. }
  4810. return this;
  4811. }
  4812. clone() {
  4813. return new this.constructor( this.r, this.g, this.b );
  4814. }
  4815. copy( color ) {
  4816. this.r = color.r;
  4817. this.g = color.g;
  4818. this.b = color.b;
  4819. return this;
  4820. }
  4821. copyGammaToLinear( color, gammaFactor = 2.0 ) {
  4822. this.r = Math.pow( color.r, gammaFactor );
  4823. this.g = Math.pow( color.g, gammaFactor );
  4824. this.b = Math.pow( color.b, gammaFactor );
  4825. return this;
  4826. }
  4827. copyLinearToGamma( color, gammaFactor = 2.0 ) {
  4828. const safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
  4829. this.r = Math.pow( color.r, safeInverse );
  4830. this.g = Math.pow( color.g, safeInverse );
  4831. this.b = Math.pow( color.b, safeInverse );
  4832. return this;
  4833. }
  4834. convertGammaToLinear( gammaFactor ) {
  4835. this.copyGammaToLinear( this, gammaFactor );
  4836. return this;
  4837. }
  4838. convertLinearToGamma( gammaFactor ) {
  4839. this.copyLinearToGamma( this, gammaFactor );
  4840. return this;
  4841. }
  4842. copySRGBToLinear( color ) {
  4843. this.r = SRGBToLinear( color.r );
  4844. this.g = SRGBToLinear( color.g );
  4845. this.b = SRGBToLinear( color.b );
  4846. return this;
  4847. }
  4848. copyLinearToSRGB( color ) {
  4849. this.r = LinearToSRGB( color.r );
  4850. this.g = LinearToSRGB( color.g );
  4851. this.b = LinearToSRGB( color.b );
  4852. return this;
  4853. }
  4854. convertSRGBToLinear() {
  4855. this.copySRGBToLinear( this );
  4856. return this;
  4857. }
  4858. convertLinearToSRGB() {
  4859. this.copyLinearToSRGB( this );
  4860. return this;
  4861. }
  4862. getHex() {
  4863. return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
  4864. }
  4865. getHexString() {
  4866. return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
  4867. }
  4868. getHSL( target ) {
  4869. // h,s,l ranges are in 0.0 - 1.0
  4870. if ( target === undefined ) {
  4871. console.warn( 'THREE.Color: .getHSL() target is now required' );
  4872. target = { h: 0, s: 0, l: 0 };
  4873. }
  4874. const r = this.r, g = this.g, b = this.b;
  4875. const max = Math.max( r, g, b );
  4876. const min = Math.min( r, g, b );
  4877. let hue, saturation;
  4878. const lightness = ( min + max ) / 2.0;
  4879. if ( min === max ) {
  4880. hue = 0;
  4881. saturation = 0;
  4882. } else {
  4883. const delta = max - min;
  4884. saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
  4885. switch ( max ) {
  4886. case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
  4887. case g: hue = ( b - r ) / delta + 2; break;
  4888. case b: hue = ( r - g ) / delta + 4; break;
  4889. }
  4890. hue /= 6;
  4891. }
  4892. target.h = hue;
  4893. target.s = saturation;
  4894. target.l = lightness;
  4895. return target;
  4896. }
  4897. getStyle() {
  4898. return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
  4899. }
  4900. offsetHSL( h, s, l ) {
  4901. this.getHSL( _hslA );
  4902. _hslA.h += h; _hslA.s += s; _hslA.l += l;
  4903. this.setHSL( _hslA.h, _hslA.s, _hslA.l );
  4904. return this;
  4905. }
  4906. add( color ) {
  4907. this.r += color.r;
  4908. this.g += color.g;
  4909. this.b += color.b;
  4910. return this;
  4911. }
  4912. addColors( color1, color2 ) {
  4913. this.r = color1.r + color2.r;
  4914. this.g = color1.g + color2.g;
  4915. this.b = color1.b + color2.b;
  4916. return this;
  4917. }
  4918. addScalar( s ) {
  4919. this.r += s;
  4920. this.g += s;
  4921. this.b += s;
  4922. return this;
  4923. }
  4924. sub( color ) {
  4925. this.r = Math.max( 0, this.r - color.r );
  4926. this.g = Math.max( 0, this.g - color.g );
  4927. this.b = Math.max( 0, this.b - color.b );
  4928. return this;
  4929. }
  4930. multiply( color ) {
  4931. this.r *= color.r;
  4932. this.g *= color.g;
  4933. this.b *= color.b;
  4934. return this;
  4935. }
  4936. multiplyScalar( s ) {
  4937. this.r *= s;
  4938. this.g *= s;
  4939. this.b *= s;
  4940. return this;
  4941. }
  4942. lerp( color, alpha ) {
  4943. this.r += ( color.r - this.r ) * alpha;
  4944. this.g += ( color.g - this.g ) * alpha;
  4945. this.b += ( color.b - this.b ) * alpha;
  4946. return this;
  4947. }
  4948. lerpHSL( color, alpha ) {
  4949. this.getHSL( _hslA );
  4950. color.getHSL( _hslB );
  4951. const h = MathUtils$1.lerp( _hslA.h, _hslB.h, alpha );
  4952. const s = MathUtils$1.lerp( _hslA.s, _hslB.s, alpha );
  4953. const l = MathUtils$1.lerp( _hslA.l, _hslB.l, alpha );
  4954. this.setHSL( h, s, l );
  4955. return this;
  4956. }
  4957. equals( c ) {
  4958. return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
  4959. }
  4960. fromArray( array, offset = 0 ) {
  4961. this.r = array[ offset ];
  4962. this.g = array[ offset + 1 ];
  4963. this.b = array[ offset + 2 ];
  4964. return this;
  4965. }
  4966. toArray( array = [], offset = 0 ) {
  4967. array[ offset ] = this.r;
  4968. array[ offset + 1 ] = this.g;
  4969. array[ offset + 2 ] = this.b;
  4970. return array;
  4971. }
  4972. fromBufferAttribute( attribute, index ) {
  4973. this.r = attribute.getX( index );
  4974. this.g = attribute.getY( index );
  4975. this.b = attribute.getZ( index );
  4976. if ( attribute.normalized === true ) {
  4977. // assuming Uint8Array
  4978. this.r /= 255;
  4979. this.g /= 255;
  4980. this.b /= 255;
  4981. }
  4982. return this;
  4983. }
  4984. toJSON() {
  4985. return this.getHex();
  4986. }
  4987. }
  4988. Color.NAMES = _colorKeywords;
  4989. Color.prototype.r = 1;
  4990. Color.prototype.g = 1;
  4991. Color.prototype.b = 1;
  4992. class Face3 {
  4993. constructor( a, b, c, normal, color, materialIndex = 0 ) {
  4994. this.a = a;
  4995. this.b = b;
  4996. this.c = c;
  4997. this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
  4998. this.vertexNormals = Array.isArray( normal ) ? normal : [];
  4999. this.color = ( color && color.isColor ) ? color : new Color();
  5000. this.vertexColors = Array.isArray( color ) ? color : [];
  5001. this.materialIndex = materialIndex;
  5002. }
  5003. clone() {
  5004. return new this.constructor().copy( this );
  5005. }
  5006. copy( source ) {
  5007. this.a = source.a;
  5008. this.b = source.b;
  5009. this.c = source.c;
  5010. this.normal.copy( source.normal );
  5011. this.color.copy( source.color );
  5012. this.materialIndex = source.materialIndex;
  5013. for ( let i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
  5014. this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
  5015. }
  5016. for ( let i = 0, il = source.vertexColors.length; i < il; i ++ ) {
  5017. this.vertexColors[ i ] = source.vertexColors[ i ].clone();
  5018. }
  5019. return this;
  5020. }
  5021. }
  5022. let materialId = 0;
  5023. function Material() {
  5024. Object.defineProperty( this, 'id', { value: materialId ++ } );
  5025. this.uuid = MathUtils$1.generateUUID();
  5026. this.name = '';
  5027. this.type = 'Material';
  5028. this.fog = true;
  5029. this.blending = NormalBlending;
  5030. this.side = FrontSide;
  5031. this.flatShading = false;
  5032. this.vertexColors = false;
  5033. this.opacity = 1;
  5034. this.transparent = false;
  5035. this.blendSrc = SrcAlphaFactor;
  5036. this.blendDst = OneMinusSrcAlphaFactor;
  5037. this.blendEquation = AddEquation;
  5038. this.blendSrcAlpha = null;
  5039. this.blendDstAlpha = null;
  5040. this.blendEquationAlpha = null;
  5041. this.depthFunc = LessEqualDepth;
  5042. this.depthTest = true;
  5043. this.depthWrite = true;
  5044. this.stencilWriteMask = 0xff;
  5045. this.stencilFunc = AlwaysStencilFunc;
  5046. this.stencilRef = 0;
  5047. this.stencilFuncMask = 0xff;
  5048. this.stencilFail = KeepStencilOp;
  5049. this.stencilZFail = KeepStencilOp;
  5050. this.stencilZPass = KeepStencilOp;
  5051. this.stencilWrite = false;
  5052. this.clippingPlanes = null;
  5053. this.clipIntersection = false;
  5054. this.clipShadows = false;
  5055. this.shadowSide = null;
  5056. this.colorWrite = true;
  5057. this.precision = null; // override the renderer's default precision for this material
  5058. this.polygonOffset = false;
  5059. this.polygonOffsetFactor = 0;
  5060. this.polygonOffsetUnits = 0;
  5061. this.dithering = false;
  5062. this.alphaTest = 0;
  5063. this.premultipliedAlpha = false;
  5064. this.visible = true;
  5065. this.toneMapped = true;
  5066. this.userData = {};
  5067. this.version = 0;
  5068. }
  5069. Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
  5070. constructor: Material,
  5071. isMaterial: true,
  5072. onBeforeCompile: function ( /* shaderobject, renderer */ ) {},
  5073. customProgramCacheKey: function () {
  5074. return this.onBeforeCompile.toString();
  5075. },
  5076. setValues: function ( values ) {
  5077. if ( values === undefined ) return;
  5078. for ( const key in values ) {
  5079. const newValue = values[ key ];
  5080. if ( newValue === undefined ) {
  5081. console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
  5082. continue;
  5083. }
  5084. // for backward compatability if shading is set in the constructor
  5085. if ( key === 'shading' ) {
  5086. console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
  5087. this.flatShading = ( newValue === FlatShading$1 ) ? true : false;
  5088. continue;
  5089. }
  5090. const currentValue = this[ key ];
  5091. if ( currentValue === undefined ) {
  5092. //console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
  5093. continue;
  5094. }
  5095. if ( currentValue && currentValue.isColor ) {
  5096. currentValue.set( newValue );
  5097. } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
  5098. currentValue.copy( newValue );
  5099. } else {
  5100. this[ key ] = newValue;
  5101. }
  5102. }
  5103. },
  5104. toJSON: function ( meta ) {
  5105. const isRoot = ( meta === undefined || typeof meta === 'string' );
  5106. if ( isRoot ) {
  5107. meta = {
  5108. textures: {},
  5109. images: {}
  5110. };
  5111. }
  5112. const data = {
  5113. metadata: {
  5114. version: 4.5,
  5115. type: 'Material',
  5116. generator: 'Material.toJSON'
  5117. }
  5118. };
  5119. // standard Material serialization
  5120. data.uuid = this.uuid;
  5121. data.type = this.type;
  5122. if ( this.name !== '' ) data.name = this.name;
  5123. if ( this.color && this.color.isColor ) data.color = this.color.getHex();
  5124. if ( this.roughness !== undefined ) data.roughness = this.roughness;
  5125. if ( this.metalness !== undefined ) data.metalness = this.metalness;
  5126. if ( this.sheen && this.sheen.isColor ) data.sheen = this.sheen.getHex();
  5127. if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
  5128. if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
  5129. if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
  5130. if ( this.shininess !== undefined ) data.shininess = this.shininess;
  5131. if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
  5132. if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
  5133. if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
  5134. data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
  5135. }
  5136. if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
  5137. data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
  5138. }
  5139. if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
  5140. data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
  5141. data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
  5142. }
  5143. if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
  5144. if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
  5145. if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
  5146. if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
  5147. if ( this.aoMap && this.aoMap.isTexture ) {
  5148. data.aoMap = this.aoMap.toJSON( meta ).uuid;
  5149. data.aoMapIntensity = this.aoMapIntensity;
  5150. }
  5151. if ( this.bumpMap && this.bumpMap.isTexture ) {
  5152. data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
  5153. data.bumpScale = this.bumpScale;
  5154. }
  5155. if ( this.normalMap && this.normalMap.isTexture ) {
  5156. data.normalMap = this.normalMap.toJSON( meta ).uuid;
  5157. data.normalMapType = this.normalMapType;
  5158. data.normalScale = this.normalScale.toArray();
  5159. }
  5160. if ( this.displacementMap && this.displacementMap.isTexture ) {
  5161. data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
  5162. data.displacementScale = this.displacementScale;
  5163. data.displacementBias = this.displacementBias;
  5164. }
  5165. if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
  5166. if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
  5167. if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
  5168. if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
  5169. if ( this.envMap && this.envMap.isTexture ) {
  5170. data.envMap = this.envMap.toJSON( meta ).uuid;
  5171. data.reflectivity = this.reflectivity; // Scale behind envMap
  5172. data.refractionRatio = this.refractionRatio;
  5173. if ( this.combine !== undefined ) data.combine = this.combine;
  5174. if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
  5175. }
  5176. if ( this.gradientMap && this.gradientMap.isTexture ) {
  5177. data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
  5178. }
  5179. if ( this.size !== undefined ) data.size = this.size;
  5180. if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
  5181. if ( this.blending !== NormalBlending ) data.blending = this.blending;
  5182. if ( this.flatShading === true ) data.flatShading = this.flatShading;
  5183. if ( this.side !== FrontSide ) data.side = this.side;
  5184. if ( this.vertexColors ) data.vertexColors = true;
  5185. if ( this.opacity < 1 ) data.opacity = this.opacity;
  5186. if ( this.transparent === true ) data.transparent = this.transparent;
  5187. data.depthFunc = this.depthFunc;
  5188. data.depthTest = this.depthTest;
  5189. data.depthWrite = this.depthWrite;
  5190. data.stencilWrite = this.stencilWrite;
  5191. data.stencilWriteMask = this.stencilWriteMask;
  5192. data.stencilFunc = this.stencilFunc;
  5193. data.stencilRef = this.stencilRef;
  5194. data.stencilFuncMask = this.stencilFuncMask;
  5195. data.stencilFail = this.stencilFail;
  5196. data.stencilZFail = this.stencilZFail;
  5197. data.stencilZPass = this.stencilZPass;
  5198. // rotation (SpriteMaterial)
  5199. if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;
  5200. if ( this.polygonOffset === true ) data.polygonOffset = true;
  5201. if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
  5202. if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
  5203. if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;
  5204. if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
  5205. if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
  5206. if ( this.scale !== undefined ) data.scale = this.scale;
  5207. if ( this.dithering === true ) data.dithering = true;
  5208. if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
  5209. if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
  5210. if ( this.wireframe === true ) data.wireframe = this.wireframe;
  5211. if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
  5212. if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
  5213. if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
  5214. if ( this.morphTargets === true ) data.morphTargets = true;
  5215. if ( this.morphNormals === true ) data.morphNormals = true;
  5216. if ( this.skinning === true ) data.skinning = true;
  5217. if ( this.visible === false ) data.visible = false;
  5218. if ( this.toneMapped === false ) data.toneMapped = false;
  5219. if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
  5220. // TODO: Copied from Object3D.toJSON
  5221. function extractFromCache( cache ) {
  5222. const values = [];
  5223. for ( const key in cache ) {
  5224. const data = cache[ key ];
  5225. delete data.metadata;
  5226. values.push( data );
  5227. }
  5228. return values;
  5229. }
  5230. if ( isRoot ) {
  5231. const textures = extractFromCache( meta.textures );
  5232. const images = extractFromCache( meta.images );
  5233. if ( textures.length > 0 ) data.textures = textures;
  5234. if ( images.length > 0 ) data.images = images;
  5235. }
  5236. return data;
  5237. },
  5238. clone: function () {
  5239. return new this.constructor().copy( this );
  5240. },
  5241. copy: function ( source ) {
  5242. this.name = source.name;
  5243. this.fog = source.fog;
  5244. this.blending = source.blending;
  5245. this.side = source.side;
  5246. this.flatShading = source.flatShading;
  5247. this.vertexColors = source.vertexColors;
  5248. this.opacity = source.opacity;
  5249. this.transparent = source.transparent;
  5250. this.blendSrc = source.blendSrc;
  5251. this.blendDst = source.blendDst;
  5252. this.blendEquation = source.blendEquation;
  5253. this.blendSrcAlpha = source.blendSrcAlpha;
  5254. this.blendDstAlpha = source.blendDstAlpha;
  5255. this.blendEquationAlpha = source.blendEquationAlpha;
  5256. this.depthFunc = source.depthFunc;
  5257. this.depthTest = source.depthTest;
  5258. this.depthWrite = source.depthWrite;
  5259. this.stencilWriteMask = source.stencilWriteMask;
  5260. this.stencilFunc = source.stencilFunc;
  5261. this.stencilRef = source.stencilRef;
  5262. this.stencilFuncMask = source.stencilFuncMask;
  5263. this.stencilFail = source.stencilFail;
  5264. this.stencilZFail = source.stencilZFail;
  5265. this.stencilZPass = source.stencilZPass;
  5266. this.stencilWrite = source.stencilWrite;
  5267. const srcPlanes = source.clippingPlanes;
  5268. let dstPlanes = null;
  5269. if ( srcPlanes !== null ) {
  5270. const n = srcPlanes.length;
  5271. dstPlanes = new Array( n );
  5272. for ( let i = 0; i !== n; ++ i ) {
  5273. dstPlanes[ i ] = srcPlanes[ i ].clone();
  5274. }
  5275. }
  5276. this.clippingPlanes = dstPlanes;
  5277. this.clipIntersection = source.clipIntersection;
  5278. this.clipShadows = source.clipShadows;
  5279. this.shadowSide = source.shadowSide;
  5280. this.colorWrite = source.colorWrite;
  5281. this.precision = source.precision;
  5282. this.polygonOffset = source.polygonOffset;
  5283. this.polygonOffsetFactor = source.polygonOffsetFactor;
  5284. this.polygonOffsetUnits = source.polygonOffsetUnits;
  5285. this.dithering = source.dithering;
  5286. this.alphaTest = source.alphaTest;
  5287. this.premultipliedAlpha = source.premultipliedAlpha;
  5288. this.visible = source.visible;
  5289. this.toneMapped = source.toneMapped;
  5290. this.userData = JSON.parse( JSON.stringify( source.userData ) );
  5291. return this;
  5292. },
  5293. dispose: function () {
  5294. this.dispatchEvent( { type: 'dispose' } );
  5295. }
  5296. } );
  5297. Object.defineProperty( Material.prototype, 'needsUpdate', {
  5298. set: function ( value ) {
  5299. if ( value === true ) this.version ++;
  5300. }
  5301. } );
  5302. /**
  5303. * parameters = {
  5304. * color: <hex>,
  5305. * opacity: <float>,
  5306. * map: new THREE.Texture( <Image> ),
  5307. *
  5308. * lightMap: new THREE.Texture( <Image> ),
  5309. * lightMapIntensity: <float>
  5310. *
  5311. * aoMap: new THREE.Texture( <Image> ),
  5312. * aoMapIntensity: <float>
  5313. *
  5314. * specularMap: new THREE.Texture( <Image> ),
  5315. *
  5316. * alphaMap: new THREE.Texture( <Image> ),
  5317. *
  5318. * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
  5319. * combine: THREE.Multiply,
  5320. * reflectivity: <float>,
  5321. * refractionRatio: <float>,
  5322. *
  5323. * depthTest: <bool>,
  5324. * depthWrite: <bool>,
  5325. *
  5326. * wireframe: <boolean>,
  5327. * wireframeLinewidth: <float>,
  5328. *
  5329. * skinning: <bool>,
  5330. * morphTargets: <bool>
  5331. * }
  5332. */
  5333. function MeshBasicMaterial( parameters ) {
  5334. Material.call( this );
  5335. this.type = 'MeshBasicMaterial';
  5336. this.color = new Color( 0xffffff ); // emissive
  5337. this.map = null;
  5338. this.lightMap = null;
  5339. this.lightMapIntensity = 1.0;
  5340. this.aoMap = null;
  5341. this.aoMapIntensity = 1.0;
  5342. this.specularMap = null;
  5343. this.alphaMap = null;
  5344. this.envMap = null;
  5345. this.combine = MultiplyOperation;
  5346. this.reflectivity = 1;
  5347. this.refractionRatio = 0.98;
  5348. this.wireframe = false;
  5349. this.wireframeLinewidth = 1;
  5350. this.wireframeLinecap = 'round';
  5351. this.wireframeLinejoin = 'round';
  5352. this.skinning = false;
  5353. this.morphTargets = false;
  5354. this.setValues( parameters );
  5355. }
  5356. MeshBasicMaterial.prototype = Object.create( Material.prototype );
  5357. MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
  5358. MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
  5359. MeshBasicMaterial.prototype.copy = function ( source ) {
  5360. Material.prototype.copy.call( this, source );
  5361. this.color.copy( source.color );
  5362. this.map = source.map;
  5363. this.lightMap = source.lightMap;
  5364. this.lightMapIntensity = source.lightMapIntensity;
  5365. this.aoMap = source.aoMap;
  5366. this.aoMapIntensity = source.aoMapIntensity;
  5367. this.specularMap = source.specularMap;
  5368. this.alphaMap = source.alphaMap;
  5369. this.envMap = source.envMap;
  5370. this.combine = source.combine;
  5371. this.reflectivity = source.reflectivity;
  5372. this.refractionRatio = source.refractionRatio;
  5373. this.wireframe = source.wireframe;
  5374. this.wireframeLinewidth = source.wireframeLinewidth;
  5375. this.wireframeLinecap = source.wireframeLinecap;
  5376. this.wireframeLinejoin = source.wireframeLinejoin;
  5377. this.skinning = source.skinning;
  5378. this.morphTargets = source.morphTargets;
  5379. return this;
  5380. };
  5381. const _vector$3 = new Vector3();
  5382. const _vector2$1 = new Vector2();
  5383. function BufferAttribute( array, itemSize, normalized ) {
  5384. if ( Array.isArray( array ) ) {
  5385. throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
  5386. }
  5387. this.name = '';
  5388. this.array = array;
  5389. this.itemSize = itemSize;
  5390. this.count = array !== undefined ? array.length / itemSize : 0;
  5391. this.normalized = normalized === true;
  5392. this.usage = StaticDrawUsage;
  5393. this.updateRange = { offset: 0, count: - 1 };
  5394. this.version = 0;
  5395. }
  5396. Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
  5397. set: function ( value ) {
  5398. if ( value === true ) this.version ++;
  5399. }
  5400. } );
  5401. Object.assign( BufferAttribute.prototype, {
  5402. isBufferAttribute: true,
  5403. onUploadCallback: function () {},
  5404. setUsage: function ( value ) {
  5405. this.usage = value;
  5406. return this;
  5407. },
  5408. copy: function ( source ) {
  5409. this.name = source.name;
  5410. this.array = new source.array.constructor( source.array );
  5411. this.itemSize = source.itemSize;
  5412. this.count = source.count;
  5413. this.normalized = source.normalized;
  5414. this.usage = source.usage;
  5415. return this;
  5416. },
  5417. copyAt: function ( index1, attribute, index2 ) {
  5418. index1 *= this.itemSize;
  5419. index2 *= attribute.itemSize;
  5420. for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
  5421. this.array[ index1 + i ] = attribute.array[ index2 + i ];
  5422. }
  5423. return this;
  5424. },
  5425. copyArray: function ( array ) {
  5426. this.array.set( array );
  5427. return this;
  5428. },
  5429. copyColorsArray: function ( colors ) {
  5430. const array = this.array;
  5431. let offset = 0;
  5432. for ( let i = 0, l = colors.length; i < l; i ++ ) {
  5433. let color = colors[ i ];
  5434. if ( color === undefined ) {
  5435. console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
  5436. color = new Color();
  5437. }
  5438. array[ offset ++ ] = color.r;
  5439. array[ offset ++ ] = color.g;
  5440. array[ offset ++ ] = color.b;
  5441. }
  5442. return this;
  5443. },
  5444. copyVector2sArray: function ( vectors ) {
  5445. const array = this.array;
  5446. let offset = 0;
  5447. for ( let i = 0, l = vectors.length; i < l; i ++ ) {
  5448. let vector = vectors[ i ];
  5449. if ( vector === undefined ) {
  5450. console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
  5451. vector = new Vector2();
  5452. }
  5453. array[ offset ++ ] = vector.x;
  5454. array[ offset ++ ] = vector.y;
  5455. }
  5456. return this;
  5457. },
  5458. copyVector3sArray: function ( vectors ) {
  5459. const array = this.array;
  5460. let offset = 0;
  5461. for ( let i = 0, l = vectors.length; i < l; i ++ ) {
  5462. let vector = vectors[ i ];
  5463. if ( vector === undefined ) {
  5464. console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
  5465. vector = new Vector3();
  5466. }
  5467. array[ offset ++ ] = vector.x;
  5468. array[ offset ++ ] = vector.y;
  5469. array[ offset ++ ] = vector.z;
  5470. }
  5471. return this;
  5472. },
  5473. copyVector4sArray: function ( vectors ) {
  5474. const array = this.array;
  5475. let offset = 0;
  5476. for ( let i = 0, l = vectors.length; i < l; i ++ ) {
  5477. let vector = vectors[ i ];
  5478. if ( vector === undefined ) {
  5479. console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
  5480. vector = new Vector4();
  5481. }
  5482. array[ offset ++ ] = vector.x;
  5483. array[ offset ++ ] = vector.y;
  5484. array[ offset ++ ] = vector.z;
  5485. array[ offset ++ ] = vector.w;
  5486. }
  5487. return this;
  5488. },
  5489. applyMatrix3: function ( m ) {
  5490. if ( this.itemSize === 2 ) {
  5491. for ( let i = 0, l = this.count; i < l; i ++ ) {
  5492. _vector2$1.fromBufferAttribute( this, i );
  5493. _vector2$1.applyMatrix3( m );
  5494. this.setXY( i, _vector2$1.x, _vector2$1.y );
  5495. }
  5496. } else if ( this.itemSize === 3 ) {
  5497. for ( let i = 0, l = this.count; i < l; i ++ ) {
  5498. _vector$3.fromBufferAttribute( this, i );
  5499. _vector$3.applyMatrix3( m );
  5500. this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
  5501. }
  5502. }
  5503. return this;
  5504. },
  5505. applyMatrix4: function ( m ) {
  5506. for ( let i = 0, l = this.count; i < l; i ++ ) {
  5507. _vector$3.x = this.getX( i );
  5508. _vector$3.y = this.getY( i );
  5509. _vector$3.z = this.getZ( i );
  5510. _vector$3.applyMatrix4( m );
  5511. this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
  5512. }
  5513. return this;
  5514. },
  5515. applyNormalMatrix: function ( m ) {
  5516. for ( let i = 0, l = this.count; i < l; i ++ ) {
  5517. _vector$3.x = this.getX( i );
  5518. _vector$3.y = this.getY( i );
  5519. _vector$3.z = this.getZ( i );
  5520. _vector$3.applyNormalMatrix( m );
  5521. this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
  5522. }
  5523. return this;
  5524. },
  5525. transformDirection: function ( m ) {
  5526. for ( let i = 0, l = this.count; i < l; i ++ ) {
  5527. _vector$3.x = this.getX( i );
  5528. _vector$3.y = this.getY( i );
  5529. _vector$3.z = this.getZ( i );
  5530. _vector$3.transformDirection( m );
  5531. this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
  5532. }
  5533. return this;
  5534. },
  5535. set: function ( value, offset = 0 ) {
  5536. this.array.set( value, offset );
  5537. return this;
  5538. },
  5539. getX: function ( index ) {
  5540. return this.array[ index * this.itemSize ];
  5541. },
  5542. setX: function ( index, x ) {
  5543. this.array[ index * this.itemSize ] = x;
  5544. return this;
  5545. },
  5546. getY: function ( index ) {
  5547. return this.array[ index * this.itemSize + 1 ];
  5548. },
  5549. setY: function ( index, y ) {
  5550. this.array[ index * this.itemSize + 1 ] = y;
  5551. return this;
  5552. },
  5553. getZ: function ( index ) {
  5554. return this.array[ index * this.itemSize + 2 ];
  5555. },
  5556. setZ: function ( index, z ) {
  5557. this.array[ index * this.itemSize + 2 ] = z;
  5558. return this;
  5559. },
  5560. getW: function ( index ) {
  5561. return this.array[ index * this.itemSize + 3 ];
  5562. },
  5563. setW: function ( index, w ) {
  5564. this.array[ index * this.itemSize + 3 ] = w;
  5565. return this;
  5566. },
  5567. setXY: function ( index, x, y ) {
  5568. index *= this.itemSize;
  5569. this.array[ index + 0 ] = x;
  5570. this.array[ index + 1 ] = y;
  5571. return this;
  5572. },
  5573. setXYZ: function ( index, x, y, z ) {
  5574. index *= this.itemSize;
  5575. this.array[ index + 0 ] = x;
  5576. this.array[ index + 1 ] = y;
  5577. this.array[ index + 2 ] = z;
  5578. return this;
  5579. },
  5580. setXYZW: function ( index, x, y, z, w ) {
  5581. index *= this.itemSize;
  5582. this.array[ index + 0 ] = x;
  5583. this.array[ index + 1 ] = y;
  5584. this.array[ index + 2 ] = z;
  5585. this.array[ index + 3 ] = w;
  5586. return this;
  5587. },
  5588. onUpload: function ( callback ) {
  5589. this.onUploadCallback = callback;
  5590. return this;
  5591. },
  5592. clone: function () {
  5593. return new this.constructor( this.array, this.itemSize ).copy( this );
  5594. },
  5595. toJSON: function () {
  5596. return {
  5597. itemSize: this.itemSize,
  5598. type: this.array.constructor.name,
  5599. array: Array.prototype.slice.call( this.array ),
  5600. normalized: this.normalized
  5601. };
  5602. }
  5603. } );
  5604. //
  5605. function Int8BufferAttribute( array, itemSize, normalized ) {
  5606. BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
  5607. }
  5608. Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5609. Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
  5610. function Uint8BufferAttribute( array, itemSize, normalized ) {
  5611. BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
  5612. }
  5613. Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5614. Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
  5615. function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
  5616. BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
  5617. }
  5618. Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5619. Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
  5620. function Int16BufferAttribute( array, itemSize, normalized ) {
  5621. BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
  5622. }
  5623. Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5624. Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
  5625. function Uint16BufferAttribute( array, itemSize, normalized ) {
  5626. BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
  5627. }
  5628. Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5629. Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
  5630. function Int32BufferAttribute( array, itemSize, normalized ) {
  5631. BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
  5632. }
  5633. Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5634. Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
  5635. function Uint32BufferAttribute( array, itemSize, normalized ) {
  5636. BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
  5637. }
  5638. Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5639. Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
  5640. function Float16BufferAttribute( array, itemSize, normalized ) {
  5641. BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
  5642. }
  5643. Float16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5644. Float16BufferAttribute.prototype.constructor = Float16BufferAttribute;
  5645. Float16BufferAttribute.prototype.isFloat16BufferAttribute = true;
  5646. function Float32BufferAttribute( array, itemSize, normalized ) {
  5647. BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
  5648. }
  5649. Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5650. Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
  5651. function Float64BufferAttribute( array, itemSize, normalized ) {
  5652. BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
  5653. }
  5654. Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5655. Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
  5656. class DirectGeometry {
  5657. constructor() {
  5658. this.vertices = [];
  5659. this.normals = [];
  5660. this.colors = [];
  5661. this.uvs = [];
  5662. this.uvs2 = [];
  5663. this.groups = [];
  5664. this.morphTargets = {};
  5665. this.skinWeights = [];
  5666. this.skinIndices = [];
  5667. // this.lineDistances = [];
  5668. this.boundingBox = null;
  5669. this.boundingSphere = null;
  5670. // update flags
  5671. this.verticesNeedUpdate = false;
  5672. this.normalsNeedUpdate = false;
  5673. this.colorsNeedUpdate = false;
  5674. this.uvsNeedUpdate = false;
  5675. this.groupsNeedUpdate = false;
  5676. }
  5677. computeGroups( geometry ) {
  5678. const groups = [];
  5679. let group, i;
  5680. let materialIndex = undefined;
  5681. const faces = geometry.faces;
  5682. for ( i = 0; i < faces.length; i ++ ) {
  5683. const face = faces[ i ];
  5684. // materials
  5685. if ( face.materialIndex !== materialIndex ) {
  5686. materialIndex = face.materialIndex;
  5687. if ( group !== undefined ) {
  5688. group.count = ( i * 3 ) - group.start;
  5689. groups.push( group );
  5690. }
  5691. group = {
  5692. start: i * 3,
  5693. materialIndex: materialIndex
  5694. };
  5695. }
  5696. }
  5697. if ( group !== undefined ) {
  5698. group.count = ( i * 3 ) - group.start;
  5699. groups.push( group );
  5700. }
  5701. this.groups = groups;
  5702. }
  5703. fromGeometry( geometry ) {
  5704. const faces = geometry.faces;
  5705. const vertices = geometry.vertices;
  5706. const faceVertexUvs = geometry.faceVertexUvs;
  5707. const hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
  5708. const hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
  5709. // morphs
  5710. const morphTargets = geometry.morphTargets;
  5711. const morphTargetsLength = morphTargets.length;
  5712. let morphTargetsPosition;
  5713. if ( morphTargetsLength > 0 ) {
  5714. morphTargetsPosition = [];
  5715. for ( let i = 0; i < morphTargetsLength; i ++ ) {
  5716. morphTargetsPosition[ i ] = {
  5717. name: morphTargets[ i ].name,
  5718. data: []
  5719. };
  5720. }
  5721. this.morphTargets.position = morphTargetsPosition;
  5722. }
  5723. const morphNormals = geometry.morphNormals;
  5724. const morphNormalsLength = morphNormals.length;
  5725. let morphTargetsNormal;
  5726. if ( morphNormalsLength > 0 ) {
  5727. morphTargetsNormal = [];
  5728. for ( let i = 0; i < morphNormalsLength; i ++ ) {
  5729. morphTargetsNormal[ i ] = {
  5730. name: morphNormals[ i ].name,
  5731. data: []
  5732. };
  5733. }
  5734. this.morphTargets.normal = morphTargetsNormal;
  5735. }
  5736. // skins
  5737. const skinIndices = geometry.skinIndices;
  5738. const skinWeights = geometry.skinWeights;
  5739. const hasSkinIndices = skinIndices.length === vertices.length;
  5740. const hasSkinWeights = skinWeights.length === vertices.length;
  5741. //
  5742. if ( vertices.length > 0 && faces.length === 0 ) {
  5743. console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );
  5744. }
  5745. for ( let i = 0; i < faces.length; i ++ ) {
  5746. const face = faces[ i ];
  5747. this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
  5748. const vertexNormals = face.vertexNormals;
  5749. if ( vertexNormals.length === 3 ) {
  5750. this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
  5751. } else {
  5752. const normal = face.normal;
  5753. this.normals.push( normal, normal, normal );
  5754. }
  5755. const vertexColors = face.vertexColors;
  5756. if ( vertexColors.length === 3 ) {
  5757. this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
  5758. } else {
  5759. const color = face.color;
  5760. this.colors.push( color, color, color );
  5761. }
  5762. if ( hasFaceVertexUv === true ) {
  5763. const vertexUvs = faceVertexUvs[ 0 ][ i ];
  5764. if ( vertexUvs !== undefined ) {
  5765. this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
  5766. } else {
  5767. console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
  5768. this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
  5769. }
  5770. }
  5771. if ( hasFaceVertexUv2 === true ) {
  5772. const vertexUvs = faceVertexUvs[ 1 ][ i ];
  5773. if ( vertexUvs !== undefined ) {
  5774. this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
  5775. } else {
  5776. console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
  5777. this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
  5778. }
  5779. }
  5780. // morphs
  5781. for ( let j = 0; j < morphTargetsLength; j ++ ) {
  5782. const morphTarget = morphTargets[ j ].vertices;
  5783. morphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
  5784. }
  5785. for ( let j = 0; j < morphNormalsLength; j ++ ) {
  5786. const morphNormal = morphNormals[ j ].vertexNormals[ i ];
  5787. morphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );
  5788. }
  5789. // skins
  5790. if ( hasSkinIndices ) {
  5791. this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
  5792. }
  5793. if ( hasSkinWeights ) {
  5794. this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
  5795. }
  5796. }
  5797. this.computeGroups( geometry );
  5798. this.verticesNeedUpdate = geometry.verticesNeedUpdate;
  5799. this.normalsNeedUpdate = geometry.normalsNeedUpdate;
  5800. this.colorsNeedUpdate = geometry.colorsNeedUpdate;
  5801. this.uvsNeedUpdate = geometry.uvsNeedUpdate;
  5802. this.groupsNeedUpdate = geometry.groupsNeedUpdate;
  5803. if ( geometry.boundingSphere !== null ) {
  5804. this.boundingSphere = geometry.boundingSphere.clone();
  5805. }
  5806. if ( geometry.boundingBox !== null ) {
  5807. this.boundingBox = geometry.boundingBox.clone();
  5808. }
  5809. return this;
  5810. }
  5811. }
  5812. function arrayMax( array ) {
  5813. if ( array.length === 0 ) return - Infinity;
  5814. let max = array[ 0 ];
  5815. for ( let i = 1, l = array.length; i < l; ++ i ) {
  5816. if ( array[ i ] > max ) max = array[ i ];
  5817. }
  5818. return max;
  5819. }
  5820. const TYPED_ARRAYS = {
  5821. Int8Array: Int8Array,
  5822. Uint8Array: Uint8Array,
  5823. // Workaround for IE11 pre KB2929437. See #11440
  5824. Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
  5825. Int16Array: Int16Array,
  5826. Uint16Array: Uint16Array,
  5827. Int32Array: Int32Array,
  5828. Uint32Array: Uint32Array,
  5829. Float32Array: Float32Array,
  5830. Float64Array: Float64Array
  5831. };
  5832. function getTypedArray( type, buffer ) {
  5833. return new TYPED_ARRAYS[ type ]( buffer );
  5834. }
  5835. let _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
  5836. const _m1$2 = new Matrix4();
  5837. const _obj = new Object3D();
  5838. const _offset = new Vector3();
  5839. const _box$2 = new Box3();
  5840. const _boxMorphTargets = new Box3();
  5841. const _vector$4 = new Vector3();
  5842. function BufferGeometry() {
  5843. Object.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );
  5844. this.uuid = MathUtils$1.generateUUID();
  5845. this.name = '';
  5846. this.type = 'BufferGeometry';
  5847. this.index = null;
  5848. this.attributes = {};
  5849. this.morphAttributes = {};
  5850. this.morphTargetsRelative = false;
  5851. this.groups = [];
  5852. this.boundingBox = null;
  5853. this.boundingSphere = null;
  5854. this.drawRange = { start: 0, count: Infinity };
  5855. this.userData = {};
  5856. }
  5857. BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
  5858. constructor: BufferGeometry,
  5859. isBufferGeometry: true,
  5860. getIndex: function () {
  5861. return this.index;
  5862. },
  5863. setIndex: function ( index ) {
  5864. if ( Array.isArray( index ) ) {
  5865. this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
  5866. } else {
  5867. this.index = index;
  5868. }
  5869. return this;
  5870. },
  5871. getAttribute: function ( name ) {
  5872. return this.attributes[ name ];
  5873. },
  5874. setAttribute: function ( name, attribute ) {
  5875. this.attributes[ name ] = attribute;
  5876. return this;
  5877. },
  5878. deleteAttribute: function ( name ) {
  5879. delete this.attributes[ name ];
  5880. return this;
  5881. },
  5882. hasAttribute: function ( name ) {
  5883. return this.attributes[ name ] !== undefined;
  5884. },
  5885. addGroup: function ( start, count, materialIndex = 0 ) {
  5886. this.groups.push( {
  5887. start: start,
  5888. count: count,
  5889. materialIndex: materialIndex
  5890. } );
  5891. },
  5892. clearGroups: function () {
  5893. this.groups = [];
  5894. },
  5895. setDrawRange: function ( start, count ) {
  5896. this.drawRange.start = start;
  5897. this.drawRange.count = count;
  5898. },
  5899. applyMatrix4: function ( matrix ) {
  5900. const position = this.attributes.position;
  5901. if ( position !== undefined ) {
  5902. position.applyMatrix4( matrix );
  5903. position.needsUpdate = true;
  5904. }
  5905. const normal = this.attributes.normal;
  5906. if ( normal !== undefined ) {
  5907. const normalMatrix = new Matrix3().getNormalMatrix( matrix );
  5908. normal.applyNormalMatrix( normalMatrix );
  5909. normal.needsUpdate = true;
  5910. }
  5911. const tangent = this.attributes.tangent;
  5912. if ( tangent !== undefined ) {
  5913. tangent.transformDirection( matrix );
  5914. tangent.needsUpdate = true;
  5915. }
  5916. if ( this.boundingBox !== null ) {
  5917. this.computeBoundingBox();
  5918. }
  5919. if ( this.boundingSphere !== null ) {
  5920. this.computeBoundingSphere();
  5921. }
  5922. return this;
  5923. },
  5924. rotateX: function ( angle ) {
  5925. // rotate geometry around world x-axis
  5926. _m1$2.makeRotationX( angle );
  5927. this.applyMatrix4( _m1$2 );
  5928. return this;
  5929. },
  5930. rotateY: function ( angle ) {
  5931. // rotate geometry around world y-axis
  5932. _m1$2.makeRotationY( angle );
  5933. this.applyMatrix4( _m1$2 );
  5934. return this;
  5935. },
  5936. rotateZ: function ( angle ) {
  5937. // rotate geometry around world z-axis
  5938. _m1$2.makeRotationZ( angle );
  5939. this.applyMatrix4( _m1$2 );
  5940. return this;
  5941. },
  5942. translate: function ( x, y, z ) {
  5943. // translate geometry
  5944. _m1$2.makeTranslation( x, y, z );
  5945. this.applyMatrix4( _m1$2 );
  5946. return this;
  5947. },
  5948. scale: function ( x, y, z ) {
  5949. // scale geometry
  5950. _m1$2.makeScale( x, y, z );
  5951. this.applyMatrix4( _m1$2 );
  5952. return this;
  5953. },
  5954. lookAt: function ( vector ) {
  5955. _obj.lookAt( vector );
  5956. _obj.updateMatrix();
  5957. this.applyMatrix4( _obj.matrix );
  5958. return this;
  5959. },
  5960. center: function () {
  5961. this.computeBoundingBox();
  5962. this.boundingBox.getCenter( _offset ).negate();
  5963. this.translate( _offset.x, _offset.y, _offset.z );
  5964. return this;
  5965. },
  5966. setFromObject: function ( object ) {
  5967. // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
  5968. const geometry = object.geometry;
  5969. if ( object.isPoints || object.isLine ) {
  5970. const positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
  5971. const colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
  5972. this.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
  5973. this.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
  5974. if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
  5975. const lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
  5976. this.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
  5977. }
  5978. if ( geometry.boundingSphere !== null ) {
  5979. this.boundingSphere = geometry.boundingSphere.clone();
  5980. }
  5981. if ( geometry.boundingBox !== null ) {
  5982. this.boundingBox = geometry.boundingBox.clone();
  5983. }
  5984. } else if ( object.isMesh ) {
  5985. if ( geometry && geometry.isGeometry ) {
  5986. this.fromGeometry( geometry );
  5987. }
  5988. }
  5989. return this;
  5990. },
  5991. setFromPoints: function ( points ) {
  5992. const position = [];
  5993. for ( let i = 0, l = points.length; i < l; i ++ ) {
  5994. const point = points[ i ];
  5995. position.push( point.x, point.y, point.z || 0 );
  5996. }
  5997. this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
  5998. return this;
  5999. },
  6000. updateFromObject: function ( object ) {
  6001. let geometry = object.geometry;
  6002. if ( object.isMesh ) {
  6003. let direct = geometry.__directGeometry;
  6004. if ( geometry.elementsNeedUpdate === true ) {
  6005. direct = undefined;
  6006. geometry.elementsNeedUpdate = false;
  6007. }
  6008. if ( direct === undefined ) {
  6009. return this.fromGeometry( geometry );
  6010. }
  6011. direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
  6012. direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
  6013. direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
  6014. direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
  6015. direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
  6016. geometry.verticesNeedUpdate = false;
  6017. geometry.normalsNeedUpdate = false;
  6018. geometry.colorsNeedUpdate = false;
  6019. geometry.uvsNeedUpdate = false;
  6020. geometry.groupsNeedUpdate = false;
  6021. geometry = direct;
  6022. }
  6023. if ( geometry.verticesNeedUpdate === true ) {
  6024. const attribute = this.attributes.position;
  6025. if ( attribute !== undefined ) {
  6026. attribute.copyVector3sArray( geometry.vertices );
  6027. attribute.needsUpdate = true;
  6028. }
  6029. geometry.verticesNeedUpdate = false;
  6030. }
  6031. if ( geometry.normalsNeedUpdate === true ) {
  6032. const attribute = this.attributes.normal;
  6033. if ( attribute !== undefined ) {
  6034. attribute.copyVector3sArray( geometry.normals );
  6035. attribute.needsUpdate = true;
  6036. }
  6037. geometry.normalsNeedUpdate = false;
  6038. }
  6039. if ( geometry.colorsNeedUpdate === true ) {
  6040. const attribute = this.attributes.color;
  6041. if ( attribute !== undefined ) {
  6042. attribute.copyColorsArray( geometry.colors );
  6043. attribute.needsUpdate = true;
  6044. }
  6045. geometry.colorsNeedUpdate = false;
  6046. }
  6047. if ( geometry.uvsNeedUpdate ) {
  6048. const attribute = this.attributes.uv;
  6049. if ( attribute !== undefined ) {
  6050. attribute.copyVector2sArray( geometry.uvs );
  6051. attribute.needsUpdate = true;
  6052. }
  6053. geometry.uvsNeedUpdate = false;
  6054. }
  6055. if ( geometry.lineDistancesNeedUpdate ) {
  6056. const attribute = this.attributes.lineDistance;
  6057. if ( attribute !== undefined ) {
  6058. attribute.copyArray( geometry.lineDistances );
  6059. attribute.needsUpdate = true;
  6060. }
  6061. geometry.lineDistancesNeedUpdate = false;
  6062. }
  6063. if ( geometry.groupsNeedUpdate ) {
  6064. geometry.computeGroups( object.geometry );
  6065. this.groups = geometry.groups;
  6066. geometry.groupsNeedUpdate = false;
  6067. }
  6068. return this;
  6069. },
  6070. fromGeometry: function ( geometry ) {
  6071. geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
  6072. return this.fromDirectGeometry( geometry.__directGeometry );
  6073. },
  6074. fromDirectGeometry: function ( geometry ) {
  6075. const positions = new Float32Array( geometry.vertices.length * 3 );
  6076. this.setAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
  6077. if ( geometry.normals.length > 0 ) {
  6078. const normals = new Float32Array( geometry.normals.length * 3 );
  6079. this.setAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
  6080. }
  6081. if ( geometry.colors.length > 0 ) {
  6082. const colors = new Float32Array( geometry.colors.length * 3 );
  6083. this.setAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
  6084. }
  6085. if ( geometry.uvs.length > 0 ) {
  6086. const uvs = new Float32Array( geometry.uvs.length * 2 );
  6087. this.setAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
  6088. }
  6089. if ( geometry.uvs2.length > 0 ) {
  6090. const uvs2 = new Float32Array( geometry.uvs2.length * 2 );
  6091. this.setAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
  6092. }
  6093. // groups
  6094. this.groups = geometry.groups;
  6095. // morphs
  6096. for ( const name in geometry.morphTargets ) {
  6097. const array = [];
  6098. const morphTargets = geometry.morphTargets[ name ];
  6099. for ( let i = 0, l = morphTargets.length; i < l; i ++ ) {
  6100. const morphTarget = morphTargets[ i ];
  6101. const attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );
  6102. attribute.name = morphTarget.name;
  6103. array.push( attribute.copyVector3sArray( morphTarget.data ) );
  6104. }
  6105. this.morphAttributes[ name ] = array;
  6106. }
  6107. // skinning
  6108. if ( geometry.skinIndices.length > 0 ) {
  6109. const skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
  6110. this.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
  6111. }
  6112. if ( geometry.skinWeights.length > 0 ) {
  6113. const skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
  6114. this.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
  6115. }
  6116. //
  6117. if ( geometry.boundingSphere !== null ) {
  6118. this.boundingSphere = geometry.boundingSphere.clone();
  6119. }
  6120. if ( geometry.boundingBox !== null ) {
  6121. this.boundingBox = geometry.boundingBox.clone();
  6122. }
  6123. return this;
  6124. },
  6125. computeBoundingBox: function () {
  6126. if ( this.boundingBox === null ) {
  6127. this.boundingBox = new Box3();
  6128. }
  6129. const position = this.attributes.position;
  6130. const morphAttributesPosition = this.morphAttributes.position;
  6131. if ( position && position.isGLBufferAttribute ) {
  6132. console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this );
  6133. this.boundingBox.set(
  6134. new Vector3( - Infinity, - Infinity, - Infinity ),
  6135. new Vector3( + Infinity, + Infinity, + Infinity )
  6136. );
  6137. return;
  6138. }
  6139. if ( position !== undefined ) {
  6140. this.boundingBox.setFromBufferAttribute( position );
  6141. // process morph attributes if present
  6142. if ( morphAttributesPosition ) {
  6143. for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
  6144. const morphAttribute = morphAttributesPosition[ i ];
  6145. _box$2.setFromBufferAttribute( morphAttribute );
  6146. if ( this.morphTargetsRelative ) {
  6147. _vector$4.addVectors( this.boundingBox.min, _box$2.min );
  6148. this.boundingBox.expandByPoint( _vector$4 );
  6149. _vector$4.addVectors( this.boundingBox.max, _box$2.max );
  6150. this.boundingBox.expandByPoint( _vector$4 );
  6151. } else {
  6152. this.boundingBox.expandByPoint( _box$2.min );
  6153. this.boundingBox.expandByPoint( _box$2.max );
  6154. }
  6155. }
  6156. }
  6157. } else {
  6158. this.boundingBox.makeEmpty();
  6159. }
  6160. if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
  6161. console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
  6162. }
  6163. },
  6164. computeBoundingSphere: function () {
  6165. if ( this.boundingSphere === null ) {
  6166. this.boundingSphere = new Sphere();
  6167. }
  6168. const position = this.attributes.position;
  6169. const morphAttributesPosition = this.morphAttributes.position;
  6170. if ( position && position.isGLBufferAttribute ) {
  6171. console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this );
  6172. this.boundingSphere.set( new Vector3(), Infinity );
  6173. return;
  6174. }
  6175. if ( position ) {
  6176. // first, find the center of the bounding sphere
  6177. const center = this.boundingSphere.center;
  6178. _box$2.setFromBufferAttribute( position );
  6179. // process morph attributes if present
  6180. if ( morphAttributesPosition ) {
  6181. for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
  6182. const morphAttribute = morphAttributesPosition[ i ];
  6183. _boxMorphTargets.setFromBufferAttribute( morphAttribute );
  6184. if ( this.morphTargetsRelative ) {
  6185. _vector$4.addVectors( _box$2.min, _boxMorphTargets.min );
  6186. _box$2.expandByPoint( _vector$4 );
  6187. _vector$4.addVectors( _box$2.max, _boxMorphTargets.max );
  6188. _box$2.expandByPoint( _vector$4 );
  6189. } else {
  6190. _box$2.expandByPoint( _boxMorphTargets.min );
  6191. _box$2.expandByPoint( _boxMorphTargets.max );
  6192. }
  6193. }
  6194. }
  6195. _box$2.getCenter( center );
  6196. // second, try to find a boundingSphere with a radius smaller than the
  6197. // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
  6198. let maxRadiusSq = 0;
  6199. for ( let i = 0, il = position.count; i < il; i ++ ) {
  6200. _vector$4.fromBufferAttribute( position, i );
  6201. maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
  6202. }
  6203. // process morph attributes if present
  6204. if ( morphAttributesPosition ) {
  6205. for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
  6206. const morphAttribute = morphAttributesPosition[ i ];
  6207. const morphTargetsRelative = this.morphTargetsRelative;
  6208. for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
  6209. _vector$4.fromBufferAttribute( morphAttribute, j );
  6210. if ( morphTargetsRelative ) {
  6211. _offset.fromBufferAttribute( position, j );
  6212. _vector$4.add( _offset );
  6213. }
  6214. maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
  6215. }
  6216. }
  6217. }
  6218. this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
  6219. if ( isNaN( this.boundingSphere.radius ) ) {
  6220. console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
  6221. }
  6222. }
  6223. },
  6224. computeFaceNormals: function () {
  6225. // backwards compatibility
  6226. },
  6227. computeVertexNormals: function () {
  6228. const index = this.index;
  6229. const positionAttribute = this.getAttribute( 'position' );
  6230. if ( positionAttribute !== undefined ) {
  6231. let normalAttribute = this.getAttribute( 'normal' );
  6232. if ( normalAttribute === undefined ) {
  6233. normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
  6234. this.setAttribute( 'normal', normalAttribute );
  6235. } else {
  6236. // reset existing normals to zero
  6237. for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
  6238. normalAttribute.setXYZ( i, 0, 0, 0 );
  6239. }
  6240. }
  6241. const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
  6242. const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
  6243. const cb = new Vector3(), ab = new Vector3();
  6244. // indexed elements
  6245. if ( index ) {
  6246. for ( let i = 0, il = index.count; i < il; i += 3 ) {
  6247. const vA = index.getX( i + 0 );
  6248. const vB = index.getX( i + 1 );
  6249. const vC = index.getX( i + 2 );
  6250. pA.fromBufferAttribute( positionAttribute, vA );
  6251. pB.fromBufferAttribute( positionAttribute, vB );
  6252. pC.fromBufferAttribute( positionAttribute, vC );
  6253. cb.subVectors( pC, pB );
  6254. ab.subVectors( pA, pB );
  6255. cb.cross( ab );
  6256. nA.fromBufferAttribute( normalAttribute, vA );
  6257. nB.fromBufferAttribute( normalAttribute, vB );
  6258. nC.fromBufferAttribute( normalAttribute, vC );
  6259. nA.add( cb );
  6260. nB.add( cb );
  6261. nC.add( cb );
  6262. normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
  6263. normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
  6264. normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
  6265. }
  6266. } else {
  6267. // non-indexed elements (unconnected triangle soup)
  6268. for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
  6269. pA.fromBufferAttribute( positionAttribute, i + 0 );
  6270. pB.fromBufferAttribute( positionAttribute, i + 1 );
  6271. pC.fromBufferAttribute( positionAttribute, i + 2 );
  6272. cb.subVectors( pC, pB );
  6273. ab.subVectors( pA, pB );
  6274. cb.cross( ab );
  6275. normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
  6276. normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
  6277. normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
  6278. }
  6279. }
  6280. this.normalizeNormals();
  6281. normalAttribute.needsUpdate = true;
  6282. }
  6283. },
  6284. merge: function ( geometry, offset ) {
  6285. if ( ! ( geometry && geometry.isBufferGeometry ) ) {
  6286. console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
  6287. return;
  6288. }
  6289. if ( offset === undefined ) {
  6290. offset = 0;
  6291. console.warn(
  6292. 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
  6293. + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
  6294. );
  6295. }
  6296. const attributes = this.attributes;
  6297. for ( const key in attributes ) {
  6298. if ( geometry.attributes[ key ] === undefined ) continue;
  6299. const attribute1 = attributes[ key ];
  6300. const attributeArray1 = attribute1.array;
  6301. const attribute2 = geometry.attributes[ key ];
  6302. const attributeArray2 = attribute2.array;
  6303. const attributeOffset = attribute2.itemSize * offset;
  6304. const length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );
  6305. for ( let i = 0, j = attributeOffset; i < length; i ++, j ++ ) {
  6306. attributeArray1[ j ] = attributeArray2[ i ];
  6307. }
  6308. }
  6309. return this;
  6310. },
  6311. normalizeNormals: function () {
  6312. const normals = this.attributes.normal;
  6313. for ( let i = 0, il = normals.count; i < il; i ++ ) {
  6314. _vector$4.fromBufferAttribute( normals, i );
  6315. _vector$4.normalize();
  6316. normals.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );
  6317. }
  6318. },
  6319. toNonIndexed: function () {
  6320. function convertBufferAttribute( attribute, indices ) {
  6321. const array = attribute.array;
  6322. const itemSize = attribute.itemSize;
  6323. const normalized = attribute.normalized;
  6324. const array2 = new array.constructor( indices.length * itemSize );
  6325. let index = 0, index2 = 0;
  6326. for ( let i = 0, l = indices.length; i < l; i ++ ) {
  6327. index = indices[ i ] * itemSize;
  6328. for ( let j = 0; j < itemSize; j ++ ) {
  6329. array2[ index2 ++ ] = array[ index ++ ];
  6330. }
  6331. }
  6332. return new BufferAttribute( array2, itemSize, normalized );
  6333. }
  6334. //
  6335. if ( this.index === null ) {
  6336. console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
  6337. return this;
  6338. }
  6339. const geometry2 = new BufferGeometry();
  6340. const indices = this.index.array;
  6341. const attributes = this.attributes;
  6342. // attributes
  6343. for ( const name in attributes ) {
  6344. const attribute = attributes[ name ];
  6345. const newAttribute = convertBufferAttribute( attribute, indices );
  6346. geometry2.setAttribute( name, newAttribute );
  6347. }
  6348. // morph attributes
  6349. const morphAttributes = this.morphAttributes;
  6350. for ( const name in morphAttributes ) {
  6351. const morphArray = [];
  6352. const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
  6353. for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
  6354. const attribute = morphAttribute[ i ];
  6355. const newAttribute = convertBufferAttribute( attribute, indices );
  6356. morphArray.push( newAttribute );
  6357. }
  6358. geometry2.morphAttributes[ name ] = morphArray;
  6359. }
  6360. geometry2.morphTargetsRelative = this.morphTargetsRelative;
  6361. // groups
  6362. const groups = this.groups;
  6363. for ( let i = 0, l = groups.length; i < l; i ++ ) {
  6364. const group = groups[ i ];
  6365. geometry2.addGroup( group.start, group.count, group.materialIndex );
  6366. }
  6367. return geometry2;
  6368. },
  6369. toJSON: function () {
  6370. const data = {
  6371. metadata: {
  6372. version: 4.5,
  6373. type: 'BufferGeometry',
  6374. generator: 'BufferGeometry.toJSON'
  6375. }
  6376. };
  6377. // standard BufferGeometry serialization
  6378. data.uuid = this.uuid;
  6379. data.type = this.type;
  6380. if ( this.name !== '' ) data.name = this.name;
  6381. if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
  6382. if ( this.parameters !== undefined ) {
  6383. const parameters = this.parameters;
  6384. for ( const key in parameters ) {
  6385. if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
  6386. }
  6387. return data;
  6388. }
  6389. data.data = { attributes: {} };
  6390. const index = this.index;
  6391. if ( index !== null ) {
  6392. data.data.index = {
  6393. type: index.array.constructor.name,
  6394. array: Array.prototype.slice.call( index.array )
  6395. };
  6396. }
  6397. const attributes = this.attributes;
  6398. for ( const key in attributes ) {
  6399. const attribute = attributes[ key ];
  6400. const attributeData = attribute.toJSON( data.data );
  6401. if ( attribute.name !== '' ) attributeData.name = attribute.name;
  6402. data.data.attributes[ key ] = attributeData;
  6403. }
  6404. const morphAttributes = {};
  6405. let hasMorphAttributes = false;
  6406. for ( const key in this.morphAttributes ) {
  6407. const attributeArray = this.morphAttributes[ key ];
  6408. const array = [];
  6409. for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
  6410. const attribute = attributeArray[ i ];
  6411. const attributeData = attribute.toJSON( data.data );
  6412. if ( attribute.name !== '' ) attributeData.name = attribute.name;
  6413. array.push( attributeData );
  6414. }
  6415. if ( array.length > 0 ) {
  6416. morphAttributes[ key ] = array;
  6417. hasMorphAttributes = true;
  6418. }
  6419. }
  6420. if ( hasMorphAttributes ) {
  6421. data.data.morphAttributes = morphAttributes;
  6422. data.data.morphTargetsRelative = this.morphTargetsRelative;
  6423. }
  6424. const groups = this.groups;
  6425. if ( groups.length > 0 ) {
  6426. data.data.groups = JSON.parse( JSON.stringify( groups ) );
  6427. }
  6428. const boundingSphere = this.boundingSphere;
  6429. if ( boundingSphere !== null ) {
  6430. data.data.boundingSphere = {
  6431. center: boundingSphere.center.toArray(),
  6432. radius: boundingSphere.radius
  6433. };
  6434. }
  6435. return data;
  6436. },
  6437. clone: function () {
  6438. /*
  6439. // Handle primitives
  6440. const parameters = this.parameters;
  6441. if ( parameters !== undefined ) {
  6442. const values = [];
  6443. for ( const key in parameters ) {
  6444. values.push( parameters[ key ] );
  6445. }
  6446. const geometry = Object.create( this.constructor.prototype );
  6447. this.constructor.apply( geometry, values );
  6448. return geometry;
  6449. }
  6450. return new this.constructor().copy( this );
  6451. */
  6452. return new BufferGeometry().copy( this );
  6453. },
  6454. copy: function ( source ) {
  6455. // reset
  6456. this.index = null;
  6457. this.attributes = {};
  6458. this.morphAttributes = {};
  6459. this.groups = [];
  6460. this.boundingBox = null;
  6461. this.boundingSphere = null;
  6462. // used for storing cloned, shared data
  6463. const data = {};
  6464. // name
  6465. this.name = source.name;
  6466. // index
  6467. const index = source.index;
  6468. if ( index !== null ) {
  6469. this.setIndex( index.clone( data ) );
  6470. }
  6471. // attributes
  6472. const attributes = source.attributes;
  6473. for ( const name in attributes ) {
  6474. const attribute = attributes[ name ];
  6475. this.setAttribute( name, attribute.clone( data ) );
  6476. }
  6477. // morph attributes
  6478. const morphAttributes = source.morphAttributes;
  6479. for ( const name in morphAttributes ) {
  6480. const array = [];
  6481. const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
  6482. for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
  6483. array.push( morphAttribute[ i ].clone( data ) );
  6484. }
  6485. this.morphAttributes[ name ] = array;
  6486. }
  6487. this.morphTargetsRelative = source.morphTargetsRelative;
  6488. // groups
  6489. const groups = source.groups;
  6490. for ( let i = 0, l = groups.length; i < l; i ++ ) {
  6491. const group = groups[ i ];
  6492. this.addGroup( group.start, group.count, group.materialIndex );
  6493. }
  6494. // bounding box
  6495. const boundingBox = source.boundingBox;
  6496. if ( boundingBox !== null ) {
  6497. this.boundingBox = boundingBox.clone();
  6498. }
  6499. // bounding sphere
  6500. const boundingSphere = source.boundingSphere;
  6501. if ( boundingSphere !== null ) {
  6502. this.boundingSphere = boundingSphere.clone();
  6503. }
  6504. // draw range
  6505. this.drawRange.start = source.drawRange.start;
  6506. this.drawRange.count = source.drawRange.count;
  6507. // user data
  6508. this.userData = source.userData;
  6509. return this;
  6510. },
  6511. dispose: function () {
  6512. this.dispatchEvent( { type: 'dispose' } );
  6513. }
  6514. } );
  6515. const _inverseMatrix = new Matrix4();
  6516. const _ray = new Ray();
  6517. const _sphere = new Sphere();
  6518. const _vA = new Vector3();
  6519. const _vB = new Vector3();
  6520. const _vC = new Vector3();
  6521. const _tempA = new Vector3();
  6522. const _tempB = new Vector3();
  6523. const _tempC = new Vector3();
  6524. const _morphA = new Vector3();
  6525. const _morphB = new Vector3();
  6526. const _morphC = new Vector3();
  6527. const _uvA = new Vector2();
  6528. const _uvB = new Vector2();
  6529. const _uvC = new Vector2();
  6530. const _intersectionPoint = new Vector3();
  6531. const _intersectionPointWorld = new Vector3();
  6532. function Mesh( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
  6533. Object3D.call( this );
  6534. this.type = 'Mesh';
  6535. this.geometry = geometry;
  6536. this.material = material;
  6537. this.updateMorphTargets();
  6538. }
  6539. Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
  6540. constructor: Mesh,
  6541. isMesh: true,
  6542. copy: function ( source ) {
  6543. Object3D.prototype.copy.call( this, source );
  6544. if ( source.morphTargetInfluences !== undefined ) {
  6545. this.morphTargetInfluences = source.morphTargetInfluences.slice();
  6546. }
  6547. if ( source.morphTargetDictionary !== undefined ) {
  6548. this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
  6549. }
  6550. this.material = source.material;
  6551. this.geometry = source.geometry;
  6552. return this;
  6553. },
  6554. updateMorphTargets: function () {
  6555. const geometry = this.geometry;
  6556. if ( geometry.isBufferGeometry ) {
  6557. const morphAttributes = geometry.morphAttributes;
  6558. const keys = Object.keys( morphAttributes );
  6559. if ( keys.length > 0 ) {
  6560. const morphAttribute = morphAttributes[ keys[ 0 ] ];
  6561. if ( morphAttribute !== undefined ) {
  6562. this.morphTargetInfluences = [];
  6563. this.morphTargetDictionary = {};
  6564. for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
  6565. const name = morphAttribute[ m ].name || String( m );
  6566. this.morphTargetInfluences.push( 0 );
  6567. this.morphTargetDictionary[ name ] = m;
  6568. }
  6569. }
  6570. }
  6571. } else {
  6572. const morphTargets = geometry.morphTargets;
  6573. if ( morphTargets !== undefined && morphTargets.length > 0 ) {
  6574. console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
  6575. }
  6576. }
  6577. },
  6578. raycast: function ( raycaster, intersects ) {
  6579. const geometry = this.geometry;
  6580. const material = this.material;
  6581. const matrixWorld = this.matrixWorld;
  6582. if ( material === undefined ) return;
  6583. // Checking boundingSphere distance to ray
  6584. if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
  6585. _sphere.copy( geometry.boundingSphere );
  6586. _sphere.applyMatrix4( matrixWorld );
  6587. if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
  6588. //
  6589. _inverseMatrix.copy( matrixWorld ).invert();
  6590. _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
  6591. // Check boundingBox before continuing
  6592. if ( geometry.boundingBox !== null ) {
  6593. if ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;
  6594. }
  6595. let intersection;
  6596. if ( geometry.isBufferGeometry ) {
  6597. const index = geometry.index;
  6598. const position = geometry.attributes.position;
  6599. const morphPosition = geometry.morphAttributes.position;
  6600. const morphTargetsRelative = geometry.morphTargetsRelative;
  6601. const uv = geometry.attributes.uv;
  6602. const uv2 = geometry.attributes.uv2;
  6603. const groups = geometry.groups;
  6604. const drawRange = geometry.drawRange;
  6605. if ( index !== null ) {
  6606. // indexed buffer geometry
  6607. if ( Array.isArray( material ) ) {
  6608. for ( let i = 0, il = groups.length; i < il; i ++ ) {
  6609. const group = groups[ i ];
  6610. const groupMaterial = material[ group.materialIndex ];
  6611. const start = Math.max( group.start, drawRange.start );
  6612. const end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
  6613. for ( let j = start, jl = end; j < jl; j += 3 ) {
  6614. const a = index.getX( j );
  6615. const b = index.getX( j + 1 );
  6616. const c = index.getX( j + 2 );
  6617. intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
  6618. if ( intersection ) {
  6619. intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
  6620. intersection.face.materialIndex = group.materialIndex;
  6621. intersects.push( intersection );
  6622. }
  6623. }
  6624. }
  6625. } else {
  6626. const start = Math.max( 0, drawRange.start );
  6627. const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
  6628. for ( let i = start, il = end; i < il; i += 3 ) {
  6629. const a = index.getX( i );
  6630. const b = index.getX( i + 1 );
  6631. const c = index.getX( i + 2 );
  6632. intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
  6633. if ( intersection ) {
  6634. intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
  6635. intersects.push( intersection );
  6636. }
  6637. }
  6638. }
  6639. } else if ( position !== undefined ) {
  6640. // non-indexed buffer geometry
  6641. if ( Array.isArray( material ) ) {
  6642. for ( let i = 0, il = groups.length; i < il; i ++ ) {
  6643. const group = groups[ i ];
  6644. const groupMaterial = material[ group.materialIndex ];
  6645. const start = Math.max( group.start, drawRange.start );
  6646. const end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
  6647. for ( let j = start, jl = end; j < jl; j += 3 ) {
  6648. const a = j;
  6649. const b = j + 1;
  6650. const c = j + 2;
  6651. intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
  6652. if ( intersection ) {
  6653. intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
  6654. intersection.face.materialIndex = group.materialIndex;
  6655. intersects.push( intersection );
  6656. }
  6657. }
  6658. }
  6659. } else {
  6660. const start = Math.max( 0, drawRange.start );
  6661. const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
  6662. for ( let i = start, il = end; i < il; i += 3 ) {
  6663. const a = i;
  6664. const b = i + 1;
  6665. const c = i + 2;
  6666. intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
  6667. if ( intersection ) {
  6668. intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
  6669. intersects.push( intersection );
  6670. }
  6671. }
  6672. }
  6673. }
  6674. } else if ( geometry.isGeometry ) {
  6675. const isMultiMaterial = Array.isArray( material );
  6676. const vertices = geometry.vertices;
  6677. const faces = geometry.faces;
  6678. let uvs;
  6679. const faceVertexUvs = geometry.faceVertexUvs[ 0 ];
  6680. if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
  6681. for ( let f = 0, fl = faces.length; f < fl; f ++ ) {
  6682. const face = faces[ f ];
  6683. const faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
  6684. if ( faceMaterial === undefined ) continue;
  6685. const fvA = vertices[ face.a ];
  6686. const fvB = vertices[ face.b ];
  6687. const fvC = vertices[ face.c ];
  6688. intersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );
  6689. if ( intersection ) {
  6690. if ( uvs && uvs[ f ] ) {
  6691. const uvs_f = uvs[ f ];
  6692. _uvA.copy( uvs_f[ 0 ] );
  6693. _uvB.copy( uvs_f[ 1 ] );
  6694. _uvC.copy( uvs_f[ 2 ] );
  6695. intersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );
  6696. }
  6697. intersection.face = face;
  6698. intersection.faceIndex = f;
  6699. intersects.push( intersection );
  6700. }
  6701. }
  6702. }
  6703. }
  6704. } );
  6705. function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
  6706. let intersect;
  6707. if ( material.side === BackSide ) {
  6708. intersect = ray.intersectTriangle( pC, pB, pA, true, point );
  6709. } else {
  6710. intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
  6711. }
  6712. if ( intersect === null ) return null;
  6713. _intersectionPointWorld.copy( point );
  6714. _intersectionPointWorld.applyMatrix4( object.matrixWorld );
  6715. const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
  6716. if ( distance < raycaster.near || distance > raycaster.far ) return null;
  6717. return {
  6718. distance: distance,
  6719. point: _intersectionPointWorld.clone(),
  6720. object: object
  6721. };
  6722. }
  6723. function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {
  6724. _vA.fromBufferAttribute( position, a );
  6725. _vB.fromBufferAttribute( position, b );
  6726. _vC.fromBufferAttribute( position, c );
  6727. const morphInfluences = object.morphTargetInfluences;
  6728. if ( material.morphTargets && morphPosition && morphInfluences ) {
  6729. _morphA.set( 0, 0, 0 );
  6730. _morphB.set( 0, 0, 0 );
  6731. _morphC.set( 0, 0, 0 );
  6732. for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
  6733. const influence = morphInfluences[ i ];
  6734. const morphAttribute = morphPosition[ i ];
  6735. if ( influence === 0 ) continue;
  6736. _tempA.fromBufferAttribute( morphAttribute, a );
  6737. _tempB.fromBufferAttribute( morphAttribute, b );
  6738. _tempC.fromBufferAttribute( morphAttribute, c );
  6739. if ( morphTargetsRelative ) {
  6740. _morphA.addScaledVector( _tempA, influence );
  6741. _morphB.addScaledVector( _tempB, influence );
  6742. _morphC.addScaledVector( _tempC, influence );
  6743. } else {
  6744. _morphA.addScaledVector( _tempA.sub( _vA ), influence );
  6745. _morphB.addScaledVector( _tempB.sub( _vB ), influence );
  6746. _morphC.addScaledVector( _tempC.sub( _vC ), influence );
  6747. }
  6748. }
  6749. _vA.add( _morphA );
  6750. _vB.add( _morphB );
  6751. _vC.add( _morphC );
  6752. }
  6753. if ( object.isSkinnedMesh ) {
  6754. object.boneTransform( a, _vA );
  6755. object.boneTransform( b, _vB );
  6756. object.boneTransform( c, _vC );
  6757. }
  6758. const intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
  6759. if ( intersection ) {
  6760. if ( uv ) {
  6761. _uvA.fromBufferAttribute( uv, a );
  6762. _uvB.fromBufferAttribute( uv, b );
  6763. _uvC.fromBufferAttribute( uv, c );
  6764. intersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
  6765. }
  6766. if ( uv2 ) {
  6767. _uvA.fromBufferAttribute( uv2, a );
  6768. _uvB.fromBufferAttribute( uv2, b );
  6769. _uvC.fromBufferAttribute( uv2, c );
  6770. intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
  6771. }
  6772. const face = new Face3( a, b, c );
  6773. Triangle.getNormal( _vA, _vB, _vC, face.normal );
  6774. intersection.face = face;
  6775. }
  6776. return intersection;
  6777. }
  6778. class BoxBufferGeometry extends BufferGeometry {
  6779. constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
  6780. super();
  6781. this.type = 'BoxBufferGeometry';
  6782. this.parameters = {
  6783. width: width,
  6784. height: height,
  6785. depth: depth,
  6786. widthSegments: widthSegments,
  6787. heightSegments: heightSegments,
  6788. depthSegments: depthSegments
  6789. };
  6790. const scope = this;
  6791. // segments
  6792. widthSegments = Math.floor( widthSegments );
  6793. heightSegments = Math.floor( heightSegments );
  6794. depthSegments = Math.floor( depthSegments );
  6795. // buffers
  6796. const indices = [];
  6797. const vertices = [];
  6798. const normals = [];
  6799. const uvs = [];
  6800. // helper variables
  6801. let numberOfVertices = 0;
  6802. let groupStart = 0;
  6803. // build each side of the box geometry
  6804. buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
  6805. buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
  6806. buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
  6807. buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
  6808. buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
  6809. buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
  6810. // build geometry
  6811. this.setIndex( indices );
  6812. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  6813. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  6814. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  6815. function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
  6816. const segmentWidth = width / gridX;
  6817. const segmentHeight = height / gridY;
  6818. const widthHalf = width / 2;
  6819. const heightHalf = height / 2;
  6820. const depthHalf = depth / 2;
  6821. const gridX1 = gridX + 1;
  6822. const gridY1 = gridY + 1;
  6823. let vertexCounter = 0;
  6824. let groupCount = 0;
  6825. const vector = new Vector3();
  6826. // generate vertices, normals and uvs
  6827. for ( let iy = 0; iy < gridY1; iy ++ ) {
  6828. const y = iy * segmentHeight - heightHalf;
  6829. for ( let ix = 0; ix < gridX1; ix ++ ) {
  6830. const x = ix * segmentWidth - widthHalf;
  6831. // set values to correct vector component
  6832. vector[ u ] = x * udir;
  6833. vector[ v ] = y * vdir;
  6834. vector[ w ] = depthHalf;
  6835. // now apply vector to vertex buffer
  6836. vertices.push( vector.x, vector.y, vector.z );
  6837. // set values to correct vector component
  6838. vector[ u ] = 0;
  6839. vector[ v ] = 0;
  6840. vector[ w ] = depth > 0 ? 1 : - 1;
  6841. // now apply vector to normal buffer
  6842. normals.push( vector.x, vector.y, vector.z );
  6843. // uvs
  6844. uvs.push( ix / gridX );
  6845. uvs.push( 1 - ( iy / gridY ) );
  6846. // counters
  6847. vertexCounter += 1;
  6848. }
  6849. }
  6850. // indices
  6851. // 1. you need three indices to draw a single face
  6852. // 2. a single segment consists of two faces
  6853. // 3. so we need to generate six (2*3) indices per segment
  6854. for ( let iy = 0; iy < gridY; iy ++ ) {
  6855. for ( let ix = 0; ix < gridX; ix ++ ) {
  6856. const a = numberOfVertices + ix + gridX1 * iy;
  6857. const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
  6858. const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
  6859. const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
  6860. // faces
  6861. indices.push( a, b, d );
  6862. indices.push( b, c, d );
  6863. // increase counter
  6864. groupCount += 6;
  6865. }
  6866. }
  6867. // add a group to the geometry. this will ensure multi material support
  6868. scope.addGroup( groupStart, groupCount, materialIndex );
  6869. // calculate new start value for groups
  6870. groupStart += groupCount;
  6871. // update total number of vertices
  6872. numberOfVertices += vertexCounter;
  6873. }
  6874. }
  6875. }
  6876. /**
  6877. * Uniform Utilities
  6878. */
  6879. function cloneUniforms( src ) {
  6880. const dst = {};
  6881. for ( const u in src ) {
  6882. dst[ u ] = {};
  6883. for ( const p in src[ u ] ) {
  6884. const property = src[ u ][ p ];
  6885. if ( property && ( property.isColor ||
  6886. property.isMatrix3 || property.isMatrix4 ||
  6887. property.isVector2 || property.isVector3 || property.isVector4 ||
  6888. property.isTexture ) ) {
  6889. dst[ u ][ p ] = property.clone();
  6890. } else if ( Array.isArray( property ) ) {
  6891. dst[ u ][ p ] = property.slice();
  6892. } else {
  6893. dst[ u ][ p ] = property;
  6894. }
  6895. }
  6896. }
  6897. return dst;
  6898. }
  6899. function mergeUniforms( uniforms ) {
  6900. const merged = {};
  6901. for ( let u = 0; u < uniforms.length; u ++ ) {
  6902. const tmp = cloneUniforms( uniforms[ u ] );
  6903. for ( const p in tmp ) {
  6904. merged[ p ] = tmp[ p ];
  6905. }
  6906. }
  6907. return merged;
  6908. }
  6909. // Legacy
  6910. const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
  6911. var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
  6912. var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
  6913. /**
  6914. * parameters = {
  6915. * defines: { "label" : "value" },
  6916. * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
  6917. *
  6918. * fragmentShader: <string>,
  6919. * vertexShader: <string>,
  6920. *
  6921. * wireframe: <boolean>,
  6922. * wireframeLinewidth: <float>,
  6923. *
  6924. * lights: <bool>,
  6925. *
  6926. * skinning: <bool>,
  6927. * morphTargets: <bool>,
  6928. * morphNormals: <bool>
  6929. * }
  6930. */
  6931. function ShaderMaterial( parameters ) {
  6932. Material.call( this );
  6933. this.type = 'ShaderMaterial';
  6934. this.defines = {};
  6935. this.uniforms = {};
  6936. this.vertexShader = default_vertex;
  6937. this.fragmentShader = default_fragment;
  6938. this.linewidth = 1;
  6939. this.wireframe = false;
  6940. this.wireframeLinewidth = 1;
  6941. this.fog = false; // set to use scene fog
  6942. this.lights = false; // set to use scene lights
  6943. this.clipping = false; // set to use user-defined clipping planes
  6944. this.skinning = false; // set to use skinning attribute streams
  6945. this.morphTargets = false; // set to use morph targets
  6946. this.morphNormals = false; // set to use morph normals
  6947. this.extensions = {
  6948. derivatives: false, // set to use derivatives
  6949. fragDepth: false, // set to use fragment depth values
  6950. drawBuffers: false, // set to use draw buffers
  6951. shaderTextureLOD: false // set to use shader texture LOD
  6952. };
  6953. // When rendered geometry doesn't include these attributes but the material does,
  6954. // use these default values in WebGL. This avoids errors when buffer data is missing.
  6955. this.defaultAttributeValues = {
  6956. 'color': [ 1, 1, 1 ],
  6957. 'uv': [ 0, 0 ],
  6958. 'uv2': [ 0, 0 ]
  6959. };
  6960. this.index0AttributeName = undefined;
  6961. this.uniformsNeedUpdate = false;
  6962. this.glslVersion = null;
  6963. if ( parameters !== undefined ) {
  6964. if ( parameters.attributes !== undefined ) {
  6965. console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
  6966. }
  6967. this.setValues( parameters );
  6968. }
  6969. }
  6970. ShaderMaterial.prototype = Object.create( Material.prototype );
  6971. ShaderMaterial.prototype.constructor = ShaderMaterial;
  6972. ShaderMaterial.prototype.isShaderMaterial = true;
  6973. ShaderMaterial.prototype.copy = function ( source ) {
  6974. Material.prototype.copy.call( this, source );
  6975. this.fragmentShader = source.fragmentShader;
  6976. this.vertexShader = source.vertexShader;
  6977. this.uniforms = cloneUniforms( source.uniforms );
  6978. this.defines = Object.assign( {}, source.defines );
  6979. this.wireframe = source.wireframe;
  6980. this.wireframeLinewidth = source.wireframeLinewidth;
  6981. this.lights = source.lights;
  6982. this.clipping = source.clipping;
  6983. this.skinning = source.skinning;
  6984. this.morphTargets = source.morphTargets;
  6985. this.morphNormals = source.morphNormals;
  6986. this.extensions = Object.assign( {}, source.extensions );
  6987. this.glslVersion = source.glslVersion;
  6988. return this;
  6989. };
  6990. ShaderMaterial.prototype.toJSON = function ( meta ) {
  6991. const data = Material.prototype.toJSON.call( this, meta );
  6992. data.glslVersion = this.glslVersion;
  6993. data.uniforms = {};
  6994. for ( const name in this.uniforms ) {
  6995. const uniform = this.uniforms[ name ];
  6996. const value = uniform.value;
  6997. if ( value && value.isTexture ) {
  6998. data.uniforms[ name ] = {
  6999. type: 't',
  7000. value: value.toJSON( meta ).uuid
  7001. };
  7002. } else if ( value && value.isColor ) {
  7003. data.uniforms[ name ] = {
  7004. type: 'c',
  7005. value: value.getHex()
  7006. };
  7007. } else if ( value && value.isVector2 ) {
  7008. data.uniforms[ name ] = {
  7009. type: 'v2',
  7010. value: value.toArray()
  7011. };
  7012. } else if ( value && value.isVector3 ) {
  7013. data.uniforms[ name ] = {
  7014. type: 'v3',
  7015. value: value.toArray()
  7016. };
  7017. } else if ( value && value.isVector4 ) {
  7018. data.uniforms[ name ] = {
  7019. type: 'v4',
  7020. value: value.toArray()
  7021. };
  7022. } else if ( value && value.isMatrix3 ) {
  7023. data.uniforms[ name ] = {
  7024. type: 'm3',
  7025. value: value.toArray()
  7026. };
  7027. } else if ( value && value.isMatrix4 ) {
  7028. data.uniforms[ name ] = {
  7029. type: 'm4',
  7030. value: value.toArray()
  7031. };
  7032. } else {
  7033. data.uniforms[ name ] = {
  7034. value: value
  7035. };
  7036. // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
  7037. }
  7038. }
  7039. if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
  7040. data.vertexShader = this.vertexShader;
  7041. data.fragmentShader = this.fragmentShader;
  7042. const extensions = {};
  7043. for ( const key in this.extensions ) {
  7044. if ( this.extensions[ key ] === true ) extensions[ key ] = true;
  7045. }
  7046. if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
  7047. return data;
  7048. };
  7049. function Camera() {
  7050. Object3D.call( this );
  7051. this.type = 'Camera';
  7052. this.matrixWorldInverse = new Matrix4();
  7053. this.projectionMatrix = new Matrix4();
  7054. this.projectionMatrixInverse = new Matrix4();
  7055. }
  7056. Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
  7057. constructor: Camera,
  7058. isCamera: true,
  7059. copy: function ( source, recursive ) {
  7060. Object3D.prototype.copy.call( this, source, recursive );
  7061. this.matrixWorldInverse.copy( source.matrixWorldInverse );
  7062. this.projectionMatrix.copy( source.projectionMatrix );
  7063. this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
  7064. return this;
  7065. },
  7066. getWorldDirection: function ( target ) {
  7067. if ( target === undefined ) {
  7068. console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
  7069. target = new Vector3();
  7070. }
  7071. this.updateWorldMatrix( true, false );
  7072. const e = this.matrixWorld.elements;
  7073. return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
  7074. },
  7075. updateMatrixWorld: function ( force ) {
  7076. Object3D.prototype.updateMatrixWorld.call( this, force );
  7077. this.matrixWorldInverse.copy( this.matrixWorld ).invert();
  7078. },
  7079. updateWorldMatrix: function ( updateParents, updateChildren ) {
  7080. Object3D.prototype.updateWorldMatrix.call( this, updateParents, updateChildren );
  7081. this.matrixWorldInverse.copy( this.matrixWorld ).invert();
  7082. },
  7083. clone: function () {
  7084. return new this.constructor().copy( this );
  7085. }
  7086. } );
  7087. function PerspectiveCamera( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
  7088. Camera.call( this );
  7089. this.type = 'PerspectiveCamera';
  7090. this.fov = fov;
  7091. this.zoom = 1;
  7092. this.near = near;
  7093. this.far = far;
  7094. this.focus = 10;
  7095. this.aspect = aspect;
  7096. this.view = null;
  7097. this.filmGauge = 35; // width of the film (default in millimeters)
  7098. this.filmOffset = 0; // horizontal film offset (same unit as gauge)
  7099. this.updateProjectionMatrix();
  7100. }
  7101. PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
  7102. constructor: PerspectiveCamera,
  7103. isPerspectiveCamera: true,
  7104. copy: function ( source, recursive ) {
  7105. Camera.prototype.copy.call( this, source, recursive );
  7106. this.fov = source.fov;
  7107. this.zoom = source.zoom;
  7108. this.near = source.near;
  7109. this.far = source.far;
  7110. this.focus = source.focus;
  7111. this.aspect = source.aspect;
  7112. this.view = source.view === null ? null : Object.assign( {}, source.view );
  7113. this.filmGauge = source.filmGauge;
  7114. this.filmOffset = source.filmOffset;
  7115. return this;
  7116. },
  7117. /**
  7118. * Sets the FOV by focal length in respect to the current .filmGauge.
  7119. *
  7120. * The default film gauge is 35, so that the focal length can be specified for
  7121. * a 35mm (full frame) camera.
  7122. *
  7123. * Values for focal length and film gauge must have the same unit.
  7124. */
  7125. setFocalLength: function ( focalLength ) {
  7126. // see http://www.bobatkins.com/photography/technical/field_of_view.html
  7127. const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
  7128. this.fov = MathUtils$1.RAD2DEG * 2 * Math.atan( vExtentSlope );
  7129. this.updateProjectionMatrix();
  7130. },
  7131. /**
  7132. * Calculates the focal length from the current .fov and .filmGauge.
  7133. */
  7134. getFocalLength: function () {
  7135. const vExtentSlope = Math.tan( MathUtils$1.DEG2RAD * 0.5 * this.fov );
  7136. return 0.5 * this.getFilmHeight() / vExtentSlope;
  7137. },
  7138. getEffectiveFOV: function () {
  7139. return MathUtils$1.RAD2DEG * 2 * Math.atan(
  7140. Math.tan( MathUtils$1.DEG2RAD * 0.5 * this.fov ) / this.zoom );
  7141. },
  7142. getFilmWidth: function () {
  7143. // film not completely covered in portrait format (aspect < 1)
  7144. return this.filmGauge * Math.min( this.aspect, 1 );
  7145. },
  7146. getFilmHeight: function () {
  7147. // film not completely covered in landscape format (aspect > 1)
  7148. return this.filmGauge / Math.max( this.aspect, 1 );
  7149. },
  7150. /**
  7151. * Sets an offset in a larger frustum. This is useful for multi-window or
  7152. * multi-monitor/multi-machine setups.
  7153. *
  7154. * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
  7155. * the monitors are in grid like this
  7156. *
  7157. * +---+---+---+
  7158. * | A | B | C |
  7159. * +---+---+---+
  7160. * | D | E | F |
  7161. * +---+---+---+
  7162. *
  7163. * then for each monitor you would call it like this
  7164. *
  7165. * const w = 1920;
  7166. * const h = 1080;
  7167. * const fullWidth = w * 3;
  7168. * const fullHeight = h * 2;
  7169. *
  7170. * --A--
  7171. * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
  7172. * --B--
  7173. * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
  7174. * --C--
  7175. * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
  7176. * --D--
  7177. * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
  7178. * --E--
  7179. * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
  7180. * --F--
  7181. * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
  7182. *
  7183. * Note there is no reason monitors have to be the same size or in a grid.
  7184. */
  7185. setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
  7186. this.aspect = fullWidth / fullHeight;
  7187. if ( this.view === null ) {
  7188. this.view = {
  7189. enabled: true,
  7190. fullWidth: 1,
  7191. fullHeight: 1,
  7192. offsetX: 0,
  7193. offsetY: 0,
  7194. width: 1,
  7195. height: 1
  7196. };
  7197. }
  7198. this.view.enabled = true;
  7199. this.view.fullWidth = fullWidth;
  7200. this.view.fullHeight = fullHeight;
  7201. this.view.offsetX = x;
  7202. this.view.offsetY = y;
  7203. this.view.width = width;
  7204. this.view.height = height;
  7205. this.updateProjectionMatrix();
  7206. },
  7207. clearViewOffset: function () {
  7208. if ( this.view !== null ) {
  7209. this.view.enabled = false;
  7210. }
  7211. this.updateProjectionMatrix();
  7212. },
  7213. updateProjectionMatrix: function () {
  7214. const near = this.near;
  7215. let top = near * Math.tan( MathUtils$1.DEG2RAD * 0.5 * this.fov ) / this.zoom;
  7216. let height = 2 * top;
  7217. let width = this.aspect * height;
  7218. let left = - 0.5 * width;
  7219. const view = this.view;
  7220. if ( this.view !== null && this.view.enabled ) {
  7221. const fullWidth = view.fullWidth,
  7222. fullHeight = view.fullHeight;
  7223. left += view.offsetX * width / fullWidth;
  7224. top -= view.offsetY * height / fullHeight;
  7225. width *= view.width / fullWidth;
  7226. height *= view.height / fullHeight;
  7227. }
  7228. const skew = this.filmOffset;
  7229. if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
  7230. this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
  7231. this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
  7232. },
  7233. toJSON: function ( meta ) {
  7234. const data = Object3D.prototype.toJSON.call( this, meta );
  7235. data.object.fov = this.fov;
  7236. data.object.zoom = this.zoom;
  7237. data.object.near = this.near;
  7238. data.object.far = this.far;
  7239. data.object.focus = this.focus;
  7240. data.object.aspect = this.aspect;
  7241. if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
  7242. data.object.filmGauge = this.filmGauge;
  7243. data.object.filmOffset = this.filmOffset;
  7244. return data;
  7245. }
  7246. } );
  7247. const fov = 90, aspect = 1;
  7248. function CubeCamera( near, far, renderTarget ) {
  7249. Object3D.call( this );
  7250. this.type = 'CubeCamera';
  7251. if ( renderTarget.isWebGLCubeRenderTarget !== true ) {
  7252. console.error( 'THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.' );
  7253. return;
  7254. }
  7255. this.renderTarget = renderTarget;
  7256. const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
  7257. cameraPX.layers = this.layers;
  7258. cameraPX.up.set( 0, - 1, 0 );
  7259. cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
  7260. this.add( cameraPX );
  7261. const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
  7262. cameraNX.layers = this.layers;
  7263. cameraNX.up.set( 0, - 1, 0 );
  7264. cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
  7265. this.add( cameraNX );
  7266. const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
  7267. cameraPY.layers = this.layers;
  7268. cameraPY.up.set( 0, 0, 1 );
  7269. cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
  7270. this.add( cameraPY );
  7271. const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
  7272. cameraNY.layers = this.layers;
  7273. cameraNY.up.set( 0, 0, - 1 );
  7274. cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
  7275. this.add( cameraNY );
  7276. const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
  7277. cameraPZ.layers = this.layers;
  7278. cameraPZ.up.set( 0, - 1, 0 );
  7279. cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
  7280. this.add( cameraPZ );
  7281. const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
  7282. cameraNZ.layers = this.layers;
  7283. cameraNZ.up.set( 0, - 1, 0 );
  7284. cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
  7285. this.add( cameraNZ );
  7286. this.update = function ( renderer, scene ) {
  7287. if ( this.parent === null ) this.updateMatrixWorld();
  7288. const currentXrEnabled = renderer.xr.enabled;
  7289. const currentRenderTarget = renderer.getRenderTarget();
  7290. renderer.xr.enabled = false;
  7291. const generateMipmaps = renderTarget.texture.generateMipmaps;
  7292. renderTarget.texture.generateMipmaps = false;
  7293. renderer.setRenderTarget( renderTarget, 0 );
  7294. renderer.render( scene, cameraPX );
  7295. renderer.setRenderTarget( renderTarget, 1 );
  7296. renderer.render( scene, cameraNX );
  7297. renderer.setRenderTarget( renderTarget, 2 );
  7298. renderer.render( scene, cameraPY );
  7299. renderer.setRenderTarget( renderTarget, 3 );
  7300. renderer.render( scene, cameraNY );
  7301. renderer.setRenderTarget( renderTarget, 4 );
  7302. renderer.render( scene, cameraPZ );
  7303. renderTarget.texture.generateMipmaps = generateMipmaps;
  7304. renderer.setRenderTarget( renderTarget, 5 );
  7305. renderer.render( scene, cameraNZ );
  7306. renderer.setRenderTarget( currentRenderTarget );
  7307. renderer.xr.enabled = currentXrEnabled;
  7308. };
  7309. }
  7310. CubeCamera.prototype = Object.create( Object3D.prototype );
  7311. CubeCamera.prototype.constructor = CubeCamera;
  7312. function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
  7313. images = images !== undefined ? images : [];
  7314. mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
  7315. format = format !== undefined ? format : RGBFormat;
  7316. Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
  7317. this.flipY = false;
  7318. // Why CubeTexture._needsFlipEnvMap is necessary:
  7319. //
  7320. // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
  7321. // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
  7322. // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
  7323. // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
  7324. // and the flag _needsFlipEnvMap controls this conversion. The flip is not required (and thus _needsFlipEnvMap is set to false)
  7325. // when using WebGLCubeRenderTarget.texture as a cube texture.
  7326. this._needsFlipEnvMap = true;
  7327. }
  7328. CubeTexture.prototype = Object.create( Texture.prototype );
  7329. CubeTexture.prototype.constructor = CubeTexture;
  7330. CubeTexture.prototype.isCubeTexture = true;
  7331. Object.defineProperty( CubeTexture.prototype, 'images', {
  7332. get: function () {
  7333. return this.image;
  7334. },
  7335. set: function ( value ) {
  7336. this.image = value;
  7337. }
  7338. } );
  7339. function WebGLCubeRenderTarget( size, options, dummy ) {
  7340. if ( Number.isInteger( options ) ) {
  7341. console.warn( 'THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )' );
  7342. options = dummy;
  7343. }
  7344. WebGLRenderTarget.call( this, size, size, options );
  7345. options = options || {};
  7346. this.texture = new CubeTexture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
  7347. this.texture._needsFlipEnvMap = false;
  7348. }
  7349. WebGLCubeRenderTarget.prototype = Object.create( WebGLRenderTarget.prototype );
  7350. WebGLCubeRenderTarget.prototype.constructor = WebGLCubeRenderTarget;
  7351. WebGLCubeRenderTarget.prototype.isWebGLCubeRenderTarget = true;
  7352. WebGLCubeRenderTarget.prototype.fromEquirectangularTexture = function ( renderer, texture ) {
  7353. this.texture.type = texture.type;
  7354. this.texture.format = RGBAFormat; // see #18859
  7355. this.texture.encoding = texture.encoding;
  7356. this.texture.generateMipmaps = texture.generateMipmaps;
  7357. this.texture.minFilter = texture.minFilter;
  7358. this.texture.magFilter = texture.magFilter;
  7359. const shader = {
  7360. uniforms: {
  7361. tEquirect: { value: null },
  7362. },
  7363. vertexShader: /* glsl */`
  7364. varying vec3 vWorldDirection;
  7365. vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
  7366. return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
  7367. }
  7368. void main() {
  7369. vWorldDirection = transformDirection( position, modelMatrix );
  7370. #include <begin_vertex>
  7371. #include <project_vertex>
  7372. }
  7373. `,
  7374. fragmentShader: /* glsl */`
  7375. uniform sampler2D tEquirect;
  7376. varying vec3 vWorldDirection;
  7377. #include <common>
  7378. void main() {
  7379. vec3 direction = normalize( vWorldDirection );
  7380. vec2 sampleUV = equirectUv( direction );
  7381. gl_FragColor = texture2D( tEquirect, sampleUV );
  7382. }
  7383. `
  7384. };
  7385. const geometry = new BoxBufferGeometry( 5, 5, 5 );
  7386. const material = new ShaderMaterial( {
  7387. name: 'CubemapFromEquirect',
  7388. uniforms: cloneUniforms( shader.uniforms ),
  7389. vertexShader: shader.vertexShader,
  7390. fragmentShader: shader.fragmentShader,
  7391. side: BackSide,
  7392. blending: NoBlending
  7393. } );
  7394. material.uniforms.tEquirect.value = texture;
  7395. const mesh = new Mesh( geometry, material );
  7396. const currentMinFilter = texture.minFilter;
  7397. // Avoid blurred poles
  7398. if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
  7399. const camera = new CubeCamera( 1, 10, this );
  7400. camera.update( renderer, mesh );
  7401. texture.minFilter = currentMinFilter;
  7402. mesh.geometry.dispose();
  7403. mesh.material.dispose();
  7404. return this;
  7405. };
  7406. WebGLCubeRenderTarget.prototype.clear = function ( renderer, color, depth, stencil ) {
  7407. const currentRenderTarget = renderer.getRenderTarget();
  7408. for ( let i = 0; i < 6; i ++ ) {
  7409. renderer.setRenderTarget( this, i );
  7410. renderer.clear( color, depth, stencil );
  7411. }
  7412. renderer.setRenderTarget( currentRenderTarget );
  7413. };
  7414. function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
  7415. Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
  7416. this.image = { data: data || null, width: width || 1, height: height || 1 };
  7417. this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
  7418. this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
  7419. this.generateMipmaps = false;
  7420. this.flipY = false;
  7421. this.unpackAlignment = 1;
  7422. this.needsUpdate = true;
  7423. }
  7424. DataTexture.prototype = Object.create( Texture.prototype );
  7425. DataTexture.prototype.constructor = DataTexture;
  7426. DataTexture.prototype.isDataTexture = true;
  7427. const _sphere$1 = /*@__PURE__*/ new Sphere();
  7428. const _vector$5 = /*@__PURE__*/ new Vector3();
  7429. class Frustum {
  7430. constructor( p0, p1, p2, p3, p4, p5 ) {
  7431. this.planes = [
  7432. ( p0 !== undefined ) ? p0 : new Plane(),
  7433. ( p1 !== undefined ) ? p1 : new Plane(),
  7434. ( p2 !== undefined ) ? p2 : new Plane(),
  7435. ( p3 !== undefined ) ? p3 : new Plane(),
  7436. ( p4 !== undefined ) ? p4 : new Plane(),
  7437. ( p5 !== undefined ) ? p5 : new Plane()
  7438. ];
  7439. }
  7440. set( p0, p1, p2, p3, p4, p5 ) {
  7441. const planes = this.planes;
  7442. planes[ 0 ].copy( p0 );
  7443. planes[ 1 ].copy( p1 );
  7444. planes[ 2 ].copy( p2 );
  7445. planes[ 3 ].copy( p3 );
  7446. planes[ 4 ].copy( p4 );
  7447. planes[ 5 ].copy( p5 );
  7448. return this;
  7449. }
  7450. clone() {
  7451. return new this.constructor().copy( this );
  7452. }
  7453. copy( frustum ) {
  7454. const planes = this.planes;
  7455. for ( let i = 0; i < 6; i ++ ) {
  7456. planes[ i ].copy( frustum.planes[ i ] );
  7457. }
  7458. return this;
  7459. }
  7460. setFromProjectionMatrix( m ) {
  7461. const planes = this.planes;
  7462. const me = m.elements;
  7463. const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
  7464. const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
  7465. const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
  7466. const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
  7467. planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
  7468. planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
  7469. planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
  7470. planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
  7471. planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
  7472. planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
  7473. return this;
  7474. }
  7475. intersectsObject( object ) {
  7476. const geometry = object.geometry;
  7477. if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
  7478. _sphere$1.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
  7479. return this.intersectsSphere( _sphere$1 );
  7480. }
  7481. intersectsSprite( sprite ) {
  7482. _sphere$1.center.set( 0, 0, 0 );
  7483. _sphere$1.radius = 0.7071067811865476;
  7484. _sphere$1.applyMatrix4( sprite.matrixWorld );
  7485. return this.intersectsSphere( _sphere$1 );
  7486. }
  7487. intersectsSphere( sphere ) {
  7488. const planes = this.planes;
  7489. const center = sphere.center;
  7490. const negRadius = - sphere.radius;
  7491. for ( let i = 0; i < 6; i ++ ) {
  7492. const distance = planes[ i ].distanceToPoint( center );
  7493. if ( distance < negRadius ) {
  7494. return false;
  7495. }
  7496. }
  7497. return true;
  7498. }
  7499. intersectsBox( box ) {
  7500. const planes = this.planes;
  7501. for ( let i = 0; i < 6; i ++ ) {
  7502. const plane = planes[ i ];
  7503. // corner at max distance
  7504. _vector$5.x = plane.normal.x > 0 ? box.max.x : box.min.x;
  7505. _vector$5.y = plane.normal.y > 0 ? box.max.y : box.min.y;
  7506. _vector$5.z = plane.normal.z > 0 ? box.max.z : box.min.z;
  7507. if ( plane.distanceToPoint( _vector$5 ) < 0 ) {
  7508. return false;
  7509. }
  7510. }
  7511. return true;
  7512. }
  7513. containsPoint( point ) {
  7514. const planes = this.planes;
  7515. for ( let i = 0; i < 6; i ++ ) {
  7516. if ( planes[ i ].distanceToPoint( point ) < 0 ) {
  7517. return false;
  7518. }
  7519. }
  7520. return true;
  7521. }
  7522. }
  7523. function WebGLAnimation() {
  7524. let context = null;
  7525. let isAnimating = false;
  7526. let animationLoop = null;
  7527. let requestId = null;
  7528. function onAnimationFrame( time, frame ) {
  7529. animationLoop( time, frame );
  7530. requestId = context.requestAnimationFrame( onAnimationFrame );
  7531. }
  7532. return {
  7533. start: function () {
  7534. if ( isAnimating === true ) return;
  7535. if ( animationLoop === null ) return;
  7536. requestId = context.requestAnimationFrame( onAnimationFrame );
  7537. isAnimating = true;
  7538. },
  7539. stop: function () {
  7540. context.cancelAnimationFrame( requestId );
  7541. isAnimating = false;
  7542. },
  7543. setAnimationLoop: function ( callback ) {
  7544. animationLoop = callback;
  7545. },
  7546. setContext: function ( value ) {
  7547. context = value;
  7548. }
  7549. };
  7550. }
  7551. function WebGLAttributes( gl, capabilities ) {
  7552. const isWebGL2 = capabilities.isWebGL2;
  7553. const buffers = new WeakMap();
  7554. function createBuffer( attribute, bufferType ) {
  7555. const array = attribute.array;
  7556. const usage = attribute.usage;
  7557. const buffer = gl.createBuffer();
  7558. gl.bindBuffer( bufferType, buffer );
  7559. gl.bufferData( bufferType, array, usage );
  7560. attribute.onUploadCallback();
  7561. let type = 5126;
  7562. if ( array instanceof Float32Array ) {
  7563. type = 5126;
  7564. } else if ( array instanceof Float64Array ) {
  7565. console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
  7566. } else if ( array instanceof Uint16Array ) {
  7567. if ( attribute.isFloat16BufferAttribute ) {
  7568. if ( isWebGL2 ) {
  7569. type = 5131;
  7570. } else {
  7571. console.warn( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
  7572. }
  7573. } else {
  7574. type = 5123;
  7575. }
  7576. } else if ( array instanceof Int16Array ) {
  7577. type = 5122;
  7578. } else if ( array instanceof Uint32Array ) {
  7579. type = 5125;
  7580. } else if ( array instanceof Int32Array ) {
  7581. type = 5124;
  7582. } else if ( array instanceof Int8Array ) {
  7583. type = 5120;
  7584. } else if ( array instanceof Uint8Array ) {
  7585. type = 5121;
  7586. }
  7587. return {
  7588. buffer: buffer,
  7589. type: type,
  7590. bytesPerElement: array.BYTES_PER_ELEMENT,
  7591. version: attribute.version
  7592. };
  7593. }
  7594. function updateBuffer( buffer, attribute, bufferType ) {
  7595. const array = attribute.array;
  7596. const updateRange = attribute.updateRange;
  7597. gl.bindBuffer( bufferType, buffer );
  7598. if ( updateRange.count === - 1 ) {
  7599. // Not using update ranges
  7600. gl.bufferSubData( bufferType, 0, array );
  7601. } else {
  7602. if ( isWebGL2 ) {
  7603. gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
  7604. array, updateRange.offset, updateRange.count );
  7605. } else {
  7606. gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
  7607. array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
  7608. }
  7609. updateRange.count = - 1; // reset range
  7610. }
  7611. }
  7612. //
  7613. function get( attribute ) {
  7614. if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
  7615. return buffers.get( attribute );
  7616. }
  7617. function remove( attribute ) {
  7618. if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
  7619. const data = buffers.get( attribute );
  7620. if ( data ) {
  7621. gl.deleteBuffer( data.buffer );
  7622. buffers.delete( attribute );
  7623. }
  7624. }
  7625. function update( attribute, bufferType ) {
  7626. if ( attribute.isGLBufferAttribute ) {
  7627. const cached = buffers.get( attribute );
  7628. if ( ! cached || cached.version < attribute.version ) {
  7629. buffers.set( attribute, {
  7630. buffer: attribute.buffer,
  7631. type: attribute.type,
  7632. bytesPerElement: attribute.elementSize,
  7633. version: attribute.version
  7634. } );
  7635. }
  7636. return;
  7637. }
  7638. if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
  7639. const data = buffers.get( attribute );
  7640. if ( data === undefined ) {
  7641. buffers.set( attribute, createBuffer( attribute, bufferType ) );
  7642. } else if ( data.version < attribute.version ) {
  7643. updateBuffer( data.buffer, attribute, bufferType );
  7644. data.version = attribute.version;
  7645. }
  7646. }
  7647. return {
  7648. get: get,
  7649. remove: remove,
  7650. update: update
  7651. };
  7652. }
  7653. class PlaneBufferGeometry extends BufferGeometry {
  7654. constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
  7655. super();
  7656. this.type = 'PlaneBufferGeometry';
  7657. this.parameters = {
  7658. width: width,
  7659. height: height,
  7660. widthSegments: widthSegments,
  7661. heightSegments: heightSegments
  7662. };
  7663. const width_half = width / 2;
  7664. const height_half = height / 2;
  7665. const gridX = Math.floor( widthSegments );
  7666. const gridY = Math.floor( heightSegments );
  7667. const gridX1 = gridX + 1;
  7668. const gridY1 = gridY + 1;
  7669. const segment_width = width / gridX;
  7670. const segment_height = height / gridY;
  7671. //
  7672. const indices = [];
  7673. const vertices = [];
  7674. const normals = [];
  7675. const uvs = [];
  7676. for ( let iy = 0; iy < gridY1; iy ++ ) {
  7677. const y = iy * segment_height - height_half;
  7678. for ( let ix = 0; ix < gridX1; ix ++ ) {
  7679. const x = ix * segment_width - width_half;
  7680. vertices.push( x, - y, 0 );
  7681. normals.push( 0, 0, 1 );
  7682. uvs.push( ix / gridX );
  7683. uvs.push( 1 - ( iy / gridY ) );
  7684. }
  7685. }
  7686. for ( let iy = 0; iy < gridY; iy ++ ) {
  7687. for ( let ix = 0; ix < gridX; ix ++ ) {
  7688. const a = ix + gridX1 * iy;
  7689. const b = ix + gridX1 * ( iy + 1 );
  7690. const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
  7691. const d = ( ix + 1 ) + gridX1 * iy;
  7692. indices.push( a, b, d );
  7693. indices.push( b, c, d );
  7694. }
  7695. }
  7696. this.setIndex( indices );
  7697. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  7698. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  7699. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  7700. }
  7701. }
  7702. var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
  7703. var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
  7704. var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif";
  7705. var aomap_fragment = "#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.specularRoughness );\n\t#endif\n#endif";
  7706. var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
  7707. var begin_vertex = "vec3 transformed = vec3( position );";
  7708. var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
  7709. var bsdfs = "vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\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\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\n}\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\treturn Fr * fresnel + F0;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_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_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\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}\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\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_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie(float roughness, float NoH) {\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\nfloat V_Neubelt(float NoV, float NoL) {\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n}\n#endif";
  7710. var bumpmap_pars_fragment = "#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 ) {\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 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\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";
  7711. var clipping_planes_fragment = "#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";
  7712. var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
  7713. var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
  7714. var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
  7715. var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
  7716. var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
  7717. var color_pars_vertex = "#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
  7718. var color_vertex = "#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor.xyz *= color.xyz;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif";
  7719. var common = "#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; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\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 max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\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 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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\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}";
  7720. var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_maxMipLevel 8.0\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_maxTileSize 256.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\tfloat texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 1.0 );\n\t\tvec2 f = fract( uv );\n\t\tuv += 0.5 - f;\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\tif ( mipInt < cubeUV_maxMipLevel ) {\n\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t}\n\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\tuv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n\t\tuv *= texelSize;\n\t\tvec3 tl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x += texelSize;\n\t\tvec3 tr = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.y += texelSize;\n\t\tvec3 br = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x -= texelSize;\n\t\tvec3 bl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tvec3 tm = mix( tl, tr, f.x );\n\t\tvec3 bm = mix( bl, br, f.x );\n\t\treturn mix( tm, bm, f.y );\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_maxMipLevel );\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";
  7721. var defaultnormal_vertex = "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";
  7722. var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
  7723. var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif";
  7724. var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
  7725. var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
  7726. var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
  7727. var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\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}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}";
  7728. var envmap_fragment = "#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#ifndef ENVMAP_TYPE_CUBE_UV\n\t\tenvColor = envMapTexelToLinear( envColor );\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";
  7729. var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\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";
  7730. var envmap_pars_fragment = "#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";
  7731. var envmap_pars_vertex = "#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";
  7732. var envmap_vertex = "#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";
  7733. var fog_vertex = "#ifdef USE_FOG\n\tfogDepth = - mvPosition.z;\n#endif";
  7734. var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif";
  7735. var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
  7736. var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\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";
  7737. var gradientmap_pars_fragment = "#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 texture2D( gradientMap, coord ).rgb;\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}";
  7738. var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n#endif";
  7739. var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
  7740. var lights_lambert_vertex = "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 );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\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\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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 );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif";
  7741. var lights_pars_begin = "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 GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\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 getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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 getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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 getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif";
  7742. var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif";
  7743. var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
  7744. var lights_toon_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_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_Diffuse_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)";
  7745. var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
  7746. var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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_Diffuse_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)";
  7747. var lights_physical_fragment = "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.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n#ifdef REFLECTIVITY\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#endif\n#ifdef CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\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_SHEEN\n\tmaterial.sheenColor = sheen;\n#endif";
  7748. var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat specularRoughness;\n\tvec3 specularColor;\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\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.specularRoughness;\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#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tccIrradiance *= PI;\n\t\t#endif\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_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_Diffuse_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 CLEARCOAT\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += clearcoatInv * 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}";
  7749. var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\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\tgetPointDirectLightIrradiance( 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\tgetSpotDirectLightIrradiance( 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\tgetDirectionalDirectLightIrradiance( 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 );\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 );\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";
  7750. var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\t#ifdef CLEARCOAT\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\n\t#endif\n#endif";
  7751. var lights_fragment_end = "#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";
  7752. var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
  7753. 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";
  7754. var logdepthbuf_pars_vertex = "#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";
  7755. var logdepthbuf_vertex = "#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";
  7756. var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif";
  7757. var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
  7758. var map_particle_fragment = "#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\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif";
  7759. var map_particle_pars_fragment = "#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";
  7760. var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
  7761. var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
  7762. var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif";
  7763. var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\t\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\t\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
  7764. var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t#endif\n#endif";
  7765. var normal_fragment_begin = "#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 * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\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 * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\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;";
  7766. var normal_fragment_maps = "#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 * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\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 );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif";
  7767. var normalmap_pars_fragment = "#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 ) {\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\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif";
  7768. var clearcoat_normal_fragment_begin = "#ifdef CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif";
  7769. var clearcoat_normal_fragment_maps = "#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 );\n\t#endif\n#endif";
  7770. var clearcoat_pars_fragment = "#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";
  7771. var packing = "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}";
  7772. var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
  7773. var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;";
  7774. var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
  7775. var dithering_pars_fragment = "#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";
  7776. var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
  7777. var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
  7778. var shadowmap_pars_fragment = "#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";
  7779. var shadowmap_pars_vertex = "#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";
  7780. var shadowmap_vertex = "#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";
  7781. var shadowmask_pars_fragment = "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}";
  7782. var skinbase_vertex = "#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";
  7783. var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif";
  7784. var skinning_vertex = "#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";
  7785. var skinnormal_vertex = "#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";
  7786. var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif";
  7787. var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
  7788. var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
  7789. var tonemapping_pars_fragment = "#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; }";
  7790. var transmissionmap_fragment = "#ifdef USE_TRANSMISSIONMAP\n\ttotalTransmission *= texture2D( transmissionMap, vUv ).r;\n#endif";
  7791. var transmissionmap_pars_fragment = "#ifdef USE_TRANSMISSIONMAP\n\tuniform sampler2D transmissionMap;\n#endif";
  7792. var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif";
  7793. 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";
  7794. var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
  7795. var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
  7796. 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";
  7797. var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";
  7798. var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\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";
  7799. var background_frag = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
  7800. var background_vert = "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}";
  7801. var cube_frag = "#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}";
  7802. var cube_vert = "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}";
  7803. var depth_frag = "#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 <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}";
  7804. var depth_vert = "#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}";
  7805. var distanceRGBA_frag = "#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 <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}";
  7806. var distanceRGBA_vert = "#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}";
  7807. var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
  7808. var equirect_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}";
  7809. var linedashed_frag = "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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
  7810. var linedashed_vert = "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 <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}";
  7811. var meshbasic_frag = "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 <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\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}";
  7812. var meshbasic_vert = "#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 <skinbase_vertex>\n\t#ifdef USE_ENVMAP\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinnormal_vertex>\n\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 <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}";
  7813. var meshlambert_frag = "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 <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_Diffuse_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_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}";
  7814. var meshlambert_vert = "#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 <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}";
  7815. var meshmatcap_frag = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <fog_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\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}";
  7816. var meshmatcap_vert = "#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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 <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 <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\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\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
  7817. var meshtoon_frag = "#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 <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 <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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}";
  7818. var meshtoon_vert = "#define TOON\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\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 <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 <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#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\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
  7819. var meshphong_frag = "#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 <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 <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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}";
  7820. var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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 <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 <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#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\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
  7821. var meshphysical_frag = "#define STANDARD\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSMISSION\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef TRANSMISSION\n\tuniform float transmission;\n#endif\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\nvarying vec3 vViewPosition;\n#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\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 <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <transmissionmap_pars_fragment>\n#include <bsdfs>\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 <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_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#ifdef TRANSMISSION\n\t\tfloat totalTransmission = transmission;\n\t#endif\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 <transmissionmap_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 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#ifdef TRANSMISSION\n\t\tdiffuseColor.a *= mix( saturate( 1. - totalTransmission + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) ), 1.0, metalness );\n\t#endif\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}";
  7822. var meshphysical_vert = "#define STANDARD\nvarying vec3 vViewPosition;\n#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\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 <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 <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#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\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}";
  7823. var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#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\n#include <packing>\n#include <uv_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}";
  7824. var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#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\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 <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#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\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}";
  7825. var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
  7826. var points_vert = "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 <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}";
  7827. var shadow_frag = "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}";
  7828. var shadow_vert = "#include <common>\n#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_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 <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
  7829. var sprite_frag = "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 <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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
  7830. var sprite_vert = "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}";
  7831. const ShaderChunk = {
  7832. alphamap_fragment: alphamap_fragment,
  7833. alphamap_pars_fragment: alphamap_pars_fragment,
  7834. alphatest_fragment: alphatest_fragment,
  7835. aomap_fragment: aomap_fragment,
  7836. aomap_pars_fragment: aomap_pars_fragment,
  7837. begin_vertex: begin_vertex,
  7838. beginnormal_vertex: beginnormal_vertex,
  7839. bsdfs: bsdfs,
  7840. bumpmap_pars_fragment: bumpmap_pars_fragment,
  7841. clipping_planes_fragment: clipping_planes_fragment,
  7842. clipping_planes_pars_fragment: clipping_planes_pars_fragment,
  7843. clipping_planes_pars_vertex: clipping_planes_pars_vertex,
  7844. clipping_planes_vertex: clipping_planes_vertex,
  7845. color_fragment: color_fragment,
  7846. color_pars_fragment: color_pars_fragment,
  7847. color_pars_vertex: color_pars_vertex,
  7848. color_vertex: color_vertex,
  7849. common: common,
  7850. cube_uv_reflection_fragment: cube_uv_reflection_fragment,
  7851. defaultnormal_vertex: defaultnormal_vertex,
  7852. displacementmap_pars_vertex: displacementmap_pars_vertex,
  7853. displacementmap_vertex: displacementmap_vertex,
  7854. emissivemap_fragment: emissivemap_fragment,
  7855. emissivemap_pars_fragment: emissivemap_pars_fragment,
  7856. encodings_fragment: encodings_fragment,
  7857. encodings_pars_fragment: encodings_pars_fragment,
  7858. envmap_fragment: envmap_fragment,
  7859. envmap_common_pars_fragment: envmap_common_pars_fragment,
  7860. envmap_pars_fragment: envmap_pars_fragment,
  7861. envmap_pars_vertex: envmap_pars_vertex,
  7862. envmap_physical_pars_fragment: envmap_physical_pars_fragment,
  7863. envmap_vertex: envmap_vertex,
  7864. fog_vertex: fog_vertex,
  7865. fog_pars_vertex: fog_pars_vertex,
  7866. fog_fragment: fog_fragment,
  7867. fog_pars_fragment: fog_pars_fragment,
  7868. gradientmap_pars_fragment: gradientmap_pars_fragment,
  7869. lightmap_fragment: lightmap_fragment,
  7870. lightmap_pars_fragment: lightmap_pars_fragment,
  7871. lights_lambert_vertex: lights_lambert_vertex,
  7872. lights_pars_begin: lights_pars_begin,
  7873. lights_toon_fragment: lights_toon_fragment,
  7874. lights_toon_pars_fragment: lights_toon_pars_fragment,
  7875. lights_phong_fragment: lights_phong_fragment,
  7876. lights_phong_pars_fragment: lights_phong_pars_fragment,
  7877. lights_physical_fragment: lights_physical_fragment,
  7878. lights_physical_pars_fragment: lights_physical_pars_fragment,
  7879. lights_fragment_begin: lights_fragment_begin,
  7880. lights_fragment_maps: lights_fragment_maps,
  7881. lights_fragment_end: lights_fragment_end,
  7882. logdepthbuf_fragment: logdepthbuf_fragment,
  7883. logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
  7884. logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
  7885. logdepthbuf_vertex: logdepthbuf_vertex,
  7886. map_fragment: map_fragment,
  7887. map_pars_fragment: map_pars_fragment,
  7888. map_particle_fragment: map_particle_fragment,
  7889. map_particle_pars_fragment: map_particle_pars_fragment,
  7890. metalnessmap_fragment: metalnessmap_fragment,
  7891. metalnessmap_pars_fragment: metalnessmap_pars_fragment,
  7892. morphnormal_vertex: morphnormal_vertex,
  7893. morphtarget_pars_vertex: morphtarget_pars_vertex,
  7894. morphtarget_vertex: morphtarget_vertex,
  7895. normal_fragment_begin: normal_fragment_begin,
  7896. normal_fragment_maps: normal_fragment_maps,
  7897. normalmap_pars_fragment: normalmap_pars_fragment,
  7898. clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
  7899. clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
  7900. clearcoat_pars_fragment: clearcoat_pars_fragment,
  7901. packing: packing,
  7902. premultiplied_alpha_fragment: premultiplied_alpha_fragment,
  7903. project_vertex: project_vertex,
  7904. dithering_fragment: dithering_fragment,
  7905. dithering_pars_fragment: dithering_pars_fragment,
  7906. roughnessmap_fragment: roughnessmap_fragment,
  7907. roughnessmap_pars_fragment: roughnessmap_pars_fragment,
  7908. shadowmap_pars_fragment: shadowmap_pars_fragment,
  7909. shadowmap_pars_vertex: shadowmap_pars_vertex,
  7910. shadowmap_vertex: shadowmap_vertex,
  7911. shadowmask_pars_fragment: shadowmask_pars_fragment,
  7912. skinbase_vertex: skinbase_vertex,
  7913. skinning_pars_vertex: skinning_pars_vertex,
  7914. skinning_vertex: skinning_vertex,
  7915. skinnormal_vertex: skinnormal_vertex,
  7916. specularmap_fragment: specularmap_fragment,
  7917. specularmap_pars_fragment: specularmap_pars_fragment,
  7918. tonemapping_fragment: tonemapping_fragment,
  7919. tonemapping_pars_fragment: tonemapping_pars_fragment,
  7920. transmissionmap_fragment: transmissionmap_fragment,
  7921. transmissionmap_pars_fragment: transmissionmap_pars_fragment,
  7922. uv_pars_fragment: uv_pars_fragment,
  7923. uv_pars_vertex: uv_pars_vertex,
  7924. uv_vertex: uv_vertex,
  7925. uv2_pars_fragment: uv2_pars_fragment,
  7926. uv2_pars_vertex: uv2_pars_vertex,
  7927. uv2_vertex: uv2_vertex,
  7928. worldpos_vertex: worldpos_vertex,
  7929. background_frag: background_frag,
  7930. background_vert: background_vert,
  7931. cube_frag: cube_frag,
  7932. cube_vert: cube_vert,
  7933. depth_frag: depth_frag,
  7934. depth_vert: depth_vert,
  7935. distanceRGBA_frag: distanceRGBA_frag,
  7936. distanceRGBA_vert: distanceRGBA_vert,
  7937. equirect_frag: equirect_frag,
  7938. equirect_vert: equirect_vert,
  7939. linedashed_frag: linedashed_frag,
  7940. linedashed_vert: linedashed_vert,
  7941. meshbasic_frag: meshbasic_frag,
  7942. meshbasic_vert: meshbasic_vert,
  7943. meshlambert_frag: meshlambert_frag,
  7944. meshlambert_vert: meshlambert_vert,
  7945. meshmatcap_frag: meshmatcap_frag,
  7946. meshmatcap_vert: meshmatcap_vert,
  7947. meshtoon_frag: meshtoon_frag,
  7948. meshtoon_vert: meshtoon_vert,
  7949. meshphong_frag: meshphong_frag,
  7950. meshphong_vert: meshphong_vert,
  7951. meshphysical_frag: meshphysical_frag,
  7952. meshphysical_vert: meshphysical_vert,
  7953. normal_frag: normal_frag,
  7954. normal_vert: normal_vert,
  7955. points_frag: points_frag,
  7956. points_vert: points_vert,
  7957. shadow_frag: shadow_frag,
  7958. shadow_vert: shadow_vert,
  7959. sprite_frag: sprite_frag,
  7960. sprite_vert: sprite_vert
  7961. };
  7962. /**
  7963. * Uniforms library for shared webgl shaders
  7964. */
  7965. const UniformsLib = {
  7966. common: {
  7967. diffuse: { value: new Color( 0xeeeeee ) },
  7968. opacity: { value: 1.0 },
  7969. map: { value: null },
  7970. uvTransform: { value: new Matrix3() },
  7971. uv2Transform: { value: new Matrix3() },
  7972. alphaMap: { value: null },
  7973. },
  7974. specularmap: {
  7975. specularMap: { value: null },
  7976. },
  7977. envmap: {
  7978. envMap: { value: null },
  7979. flipEnvMap: { value: - 1 },
  7980. reflectivity: { value: 1.0 },
  7981. refractionRatio: { value: 0.98 },
  7982. maxMipLevel: { value: 0 }
  7983. },
  7984. aomap: {
  7985. aoMap: { value: null },
  7986. aoMapIntensity: { value: 1 }
  7987. },
  7988. lightmap: {
  7989. lightMap: { value: null },
  7990. lightMapIntensity: { value: 1 }
  7991. },
  7992. emissivemap: {
  7993. emissiveMap: { value: null }
  7994. },
  7995. bumpmap: {
  7996. bumpMap: { value: null },
  7997. bumpScale: { value: 1 }
  7998. },
  7999. normalmap: {
  8000. normalMap: { value: null },
  8001. normalScale: { value: new Vector2( 1, 1 ) }
  8002. },
  8003. displacementmap: {
  8004. displacementMap: { value: null },
  8005. displacementScale: { value: 1 },
  8006. displacementBias: { value: 0 }
  8007. },
  8008. roughnessmap: {
  8009. roughnessMap: { value: null }
  8010. },
  8011. metalnessmap: {
  8012. metalnessMap: { value: null }
  8013. },
  8014. gradientmap: {
  8015. gradientMap: { value: null }
  8016. },
  8017. fog: {
  8018. fogDensity: { value: 0.00025 },
  8019. fogNear: { value: 1 },
  8020. fogFar: { value: 2000 },
  8021. fogColor: { value: new Color( 0xffffff ) }
  8022. },
  8023. lights: {
  8024. ambientLightColor: { value: [] },
  8025. lightProbe: { value: [] },
  8026. directionalLights: { value: [], properties: {
  8027. direction: {},
  8028. color: {}
  8029. } },
  8030. directionalLightShadows: { value: [], properties: {
  8031. shadowBias: {},
  8032. shadowNormalBias: {},
  8033. shadowRadius: {},
  8034. shadowMapSize: {}
  8035. } },
  8036. directionalShadowMap: { value: [] },
  8037. directionalShadowMatrix: { value: [] },
  8038. spotLights: { value: [], properties: {
  8039. color: {},
  8040. position: {},
  8041. direction: {},
  8042. distance: {},
  8043. coneCos: {},
  8044. penumbraCos: {},
  8045. decay: {}
  8046. } },
  8047. spotLightShadows: { value: [], properties: {
  8048. shadowBias: {},
  8049. shadowNormalBias: {},
  8050. shadowRadius: {},
  8051. shadowMapSize: {}
  8052. } },
  8053. spotShadowMap: { value: [] },
  8054. spotShadowMatrix: { value: [] },
  8055. pointLights: { value: [], properties: {
  8056. color: {},
  8057. position: {},
  8058. decay: {},
  8059. distance: {}
  8060. } },
  8061. pointLightShadows: { value: [], properties: {
  8062. shadowBias: {},
  8063. shadowNormalBias: {},
  8064. shadowRadius: {},
  8065. shadowMapSize: {},
  8066. shadowCameraNear: {},
  8067. shadowCameraFar: {}
  8068. } },
  8069. pointShadowMap: { value: [] },
  8070. pointShadowMatrix: { value: [] },
  8071. hemisphereLights: { value: [], properties: {
  8072. direction: {},
  8073. skyColor: {},
  8074. groundColor: {}
  8075. } },
  8076. // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
  8077. rectAreaLights: { value: [], properties: {
  8078. color: {},
  8079. position: {},
  8080. width: {},
  8081. height: {}
  8082. } },
  8083. ltc_1: { value: null },
  8084. ltc_2: { value: null }
  8085. },
  8086. points: {
  8087. diffuse: { value: new Color( 0xeeeeee ) },
  8088. opacity: { value: 1.0 },
  8089. size: { value: 1.0 },
  8090. scale: { value: 1.0 },
  8091. map: { value: null },
  8092. alphaMap: { value: null },
  8093. uvTransform: { value: new Matrix3() }
  8094. },
  8095. sprite: {
  8096. diffuse: { value: new Color( 0xeeeeee ) },
  8097. opacity: { value: 1.0 },
  8098. center: { value: new Vector2( 0.5, 0.5 ) },
  8099. rotation: { value: 0.0 },
  8100. map: { value: null },
  8101. alphaMap: { value: null },
  8102. uvTransform: { value: new Matrix3() }
  8103. }
  8104. };
  8105. const ShaderLib = {
  8106. basic: {
  8107. uniforms: mergeUniforms( [
  8108. UniformsLib.common,
  8109. UniformsLib.specularmap,
  8110. UniformsLib.envmap,
  8111. UniformsLib.aomap,
  8112. UniformsLib.lightmap,
  8113. UniformsLib.fog
  8114. ] ),
  8115. vertexShader: ShaderChunk.meshbasic_vert,
  8116. fragmentShader: ShaderChunk.meshbasic_frag
  8117. },
  8118. lambert: {
  8119. uniforms: mergeUniforms( [
  8120. UniformsLib.common,
  8121. UniformsLib.specularmap,
  8122. UniformsLib.envmap,
  8123. UniformsLib.aomap,
  8124. UniformsLib.lightmap,
  8125. UniformsLib.emissivemap,
  8126. UniformsLib.fog,
  8127. UniformsLib.lights,
  8128. {
  8129. emissive: { value: new Color( 0x000000 ) }
  8130. }
  8131. ] ),
  8132. vertexShader: ShaderChunk.meshlambert_vert,
  8133. fragmentShader: ShaderChunk.meshlambert_frag
  8134. },
  8135. phong: {
  8136. uniforms: mergeUniforms( [
  8137. UniformsLib.common,
  8138. UniformsLib.specularmap,
  8139. UniformsLib.envmap,
  8140. UniformsLib.aomap,
  8141. UniformsLib.lightmap,
  8142. UniformsLib.emissivemap,
  8143. UniformsLib.bumpmap,
  8144. UniformsLib.normalmap,
  8145. UniformsLib.displacementmap,
  8146. UniformsLib.fog,
  8147. UniformsLib.lights,
  8148. {
  8149. emissive: { value: new Color( 0x000000 ) },
  8150. specular: { value: new Color( 0x111111 ) },
  8151. shininess: { value: 30 }
  8152. }
  8153. ] ),
  8154. vertexShader: ShaderChunk.meshphong_vert,
  8155. fragmentShader: ShaderChunk.meshphong_frag
  8156. },
  8157. standard: {
  8158. uniforms: mergeUniforms( [
  8159. UniformsLib.common,
  8160. UniformsLib.envmap,
  8161. UniformsLib.aomap,
  8162. UniformsLib.lightmap,
  8163. UniformsLib.emissivemap,
  8164. UniformsLib.bumpmap,
  8165. UniformsLib.normalmap,
  8166. UniformsLib.displacementmap,
  8167. UniformsLib.roughnessmap,
  8168. UniformsLib.metalnessmap,
  8169. UniformsLib.fog,
  8170. UniformsLib.lights,
  8171. {
  8172. emissive: { value: new Color( 0x000000 ) },
  8173. roughness: { value: 1.0 },
  8174. metalness: { value: 0.0 },
  8175. envMapIntensity: { value: 1 } // temporary
  8176. }
  8177. ] ),
  8178. vertexShader: ShaderChunk.meshphysical_vert,
  8179. fragmentShader: ShaderChunk.meshphysical_frag
  8180. },
  8181. toon: {
  8182. uniforms: mergeUniforms( [
  8183. UniformsLib.common,
  8184. UniformsLib.aomap,
  8185. UniformsLib.lightmap,
  8186. UniformsLib.emissivemap,
  8187. UniformsLib.bumpmap,
  8188. UniformsLib.normalmap,
  8189. UniformsLib.displacementmap,
  8190. UniformsLib.gradientmap,
  8191. UniformsLib.fog,
  8192. UniformsLib.lights,
  8193. {
  8194. emissive: { value: new Color( 0x000000 ) }
  8195. }
  8196. ] ),
  8197. vertexShader: ShaderChunk.meshtoon_vert,
  8198. fragmentShader: ShaderChunk.meshtoon_frag
  8199. },
  8200. matcap: {
  8201. uniforms: mergeUniforms( [
  8202. UniformsLib.common,
  8203. UniformsLib.bumpmap,
  8204. UniformsLib.normalmap,
  8205. UniformsLib.displacementmap,
  8206. UniformsLib.fog,
  8207. {
  8208. matcap: { value: null }
  8209. }
  8210. ] ),
  8211. vertexShader: ShaderChunk.meshmatcap_vert,
  8212. fragmentShader: ShaderChunk.meshmatcap_frag
  8213. },
  8214. points: {
  8215. uniforms: mergeUniforms( [
  8216. UniformsLib.points,
  8217. UniformsLib.fog
  8218. ] ),
  8219. vertexShader: ShaderChunk.points_vert,
  8220. fragmentShader: ShaderChunk.points_frag
  8221. },
  8222. dashed: {
  8223. uniforms: mergeUniforms( [
  8224. UniformsLib.common,
  8225. UniformsLib.fog,
  8226. {
  8227. scale: { value: 1 },
  8228. dashSize: { value: 1 },
  8229. totalSize: { value: 2 }
  8230. }
  8231. ] ),
  8232. vertexShader: ShaderChunk.linedashed_vert,
  8233. fragmentShader: ShaderChunk.linedashed_frag
  8234. },
  8235. depth: {
  8236. uniforms: mergeUniforms( [
  8237. UniformsLib.common,
  8238. UniformsLib.displacementmap
  8239. ] ),
  8240. vertexShader: ShaderChunk.depth_vert,
  8241. fragmentShader: ShaderChunk.depth_frag
  8242. },
  8243. normal: {
  8244. uniforms: mergeUniforms( [
  8245. UniformsLib.common,
  8246. UniformsLib.bumpmap,
  8247. UniformsLib.normalmap,
  8248. UniformsLib.displacementmap,
  8249. {
  8250. opacity: { value: 1.0 }
  8251. }
  8252. ] ),
  8253. vertexShader: ShaderChunk.normal_vert,
  8254. fragmentShader: ShaderChunk.normal_frag
  8255. },
  8256. sprite: {
  8257. uniforms: mergeUniforms( [
  8258. UniformsLib.sprite,
  8259. UniformsLib.fog
  8260. ] ),
  8261. vertexShader: ShaderChunk.sprite_vert,
  8262. fragmentShader: ShaderChunk.sprite_frag
  8263. },
  8264. background: {
  8265. uniforms: {
  8266. uvTransform: { value: new Matrix3() },
  8267. t2D: { value: null },
  8268. },
  8269. vertexShader: ShaderChunk.background_vert,
  8270. fragmentShader: ShaderChunk.background_frag
  8271. },
  8272. /* -------------------------------------------------------------------------
  8273. // Cube map shader
  8274. ------------------------------------------------------------------------- */
  8275. cube: {
  8276. uniforms: mergeUniforms( [
  8277. UniformsLib.envmap,
  8278. {
  8279. opacity: { value: 1.0 }
  8280. }
  8281. ] ),
  8282. vertexShader: ShaderChunk.cube_vert,
  8283. fragmentShader: ShaderChunk.cube_frag
  8284. },
  8285. equirect: {
  8286. uniforms: {
  8287. tEquirect: { value: null },
  8288. },
  8289. vertexShader: ShaderChunk.equirect_vert,
  8290. fragmentShader: ShaderChunk.equirect_frag
  8291. },
  8292. distanceRGBA: {
  8293. uniforms: mergeUniforms( [
  8294. UniformsLib.common,
  8295. UniformsLib.displacementmap,
  8296. {
  8297. referencePosition: { value: new Vector3() },
  8298. nearDistance: { value: 1 },
  8299. farDistance: { value: 1000 }
  8300. }
  8301. ] ),
  8302. vertexShader: ShaderChunk.distanceRGBA_vert,
  8303. fragmentShader: ShaderChunk.distanceRGBA_frag
  8304. },
  8305. shadow: {
  8306. uniforms: mergeUniforms( [
  8307. UniformsLib.lights,
  8308. UniformsLib.fog,
  8309. {
  8310. color: { value: new Color( 0x00000 ) },
  8311. opacity: { value: 1.0 }
  8312. },
  8313. ] ),
  8314. vertexShader: ShaderChunk.shadow_vert,
  8315. fragmentShader: ShaderChunk.shadow_frag
  8316. }
  8317. };
  8318. ShaderLib.physical = {
  8319. uniforms: mergeUniforms( [
  8320. ShaderLib.standard.uniforms,
  8321. {
  8322. clearcoat: { value: 0 },
  8323. clearcoatMap: { value: null },
  8324. clearcoatRoughness: { value: 0 },
  8325. clearcoatRoughnessMap: { value: null },
  8326. clearcoatNormalScale: { value: new Vector2( 1, 1 ) },
  8327. clearcoatNormalMap: { value: null },
  8328. sheen: { value: new Color( 0x000000 ) },
  8329. transmission: { value: 0 },
  8330. transmissionMap: { value: null },
  8331. }
  8332. ] ),
  8333. vertexShader: ShaderChunk.meshphysical_vert,
  8334. fragmentShader: ShaderChunk.meshphysical_frag
  8335. };
  8336. function WebGLBackground( renderer, cubemaps, state, objects, premultipliedAlpha ) {
  8337. const clearColor = new Color( 0x000000 );
  8338. let clearAlpha = 0;
  8339. let planeMesh;
  8340. let boxMesh;
  8341. let currentBackground = null;
  8342. let currentBackgroundVersion = 0;
  8343. let currentTonemapping = null;
  8344. function render( renderList, scene, camera, forceClear ) {
  8345. let background = scene.isScene === true ? scene.background : null;
  8346. if ( background && background.isTexture ) {
  8347. background = cubemaps.get( background );
  8348. }
  8349. // Ignore background in AR
  8350. // TODO: Reconsider this.
  8351. const xr = renderer.xr;
  8352. const session = xr.getSession && xr.getSession();
  8353. if ( session && session.environmentBlendMode === 'additive' ) {
  8354. background = null;
  8355. }
  8356. if ( background === null ) {
  8357. setClear( clearColor, clearAlpha );
  8358. } else if ( background && background.isColor ) {
  8359. setClear( background, 1 );
  8360. forceClear = true;
  8361. }
  8362. if ( renderer.autoClear || forceClear ) {
  8363. renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
  8364. }
  8365. if ( background && ( background.isCubeTexture || background.isWebGLCubeRenderTarget || background.mapping === CubeUVReflectionMapping ) ) {
  8366. if ( boxMesh === undefined ) {
  8367. boxMesh = new Mesh(
  8368. new BoxBufferGeometry( 1, 1, 1 ),
  8369. new ShaderMaterial( {
  8370. name: 'BackgroundCubeMaterial',
  8371. uniforms: cloneUniforms( ShaderLib.cube.uniforms ),
  8372. vertexShader: ShaderLib.cube.vertexShader,
  8373. fragmentShader: ShaderLib.cube.fragmentShader,
  8374. side: BackSide,
  8375. depthTest: false,
  8376. depthWrite: false,
  8377. fog: false
  8378. } )
  8379. );
  8380. boxMesh.geometry.deleteAttribute( 'normal' );
  8381. boxMesh.geometry.deleteAttribute( 'uv' );
  8382. boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
  8383. this.matrixWorld.copyPosition( camera.matrixWorld );
  8384. };
  8385. // enable code injection for non-built-in material
  8386. Object.defineProperty( boxMesh.material, 'envMap', {
  8387. get: function () {
  8388. return this.uniforms.envMap.value;
  8389. }
  8390. } );
  8391. objects.update( boxMesh );
  8392. }
  8393. if ( background.isWebGLCubeRenderTarget ) {
  8394. // TODO Deprecate
  8395. background = background.texture;
  8396. }
  8397. boxMesh.material.uniforms.envMap.value = background;
  8398. boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background._needsFlipEnvMap ) ? - 1 : 1;
  8399. if ( currentBackground !== background ||
  8400. currentBackgroundVersion !== background.version ||
  8401. currentTonemapping !== renderer.toneMapping ) {
  8402. boxMesh.material.needsUpdate = true;
  8403. currentBackground = background;
  8404. currentBackgroundVersion = background.version;
  8405. currentTonemapping = renderer.toneMapping;
  8406. }
  8407. // push to the pre-sorted opaque render list
  8408. renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
  8409. } else if ( background && background.isTexture ) {
  8410. if ( planeMesh === undefined ) {
  8411. planeMesh = new Mesh(
  8412. new PlaneBufferGeometry( 2, 2 ),
  8413. new ShaderMaterial( {
  8414. name: 'BackgroundMaterial',
  8415. uniforms: cloneUniforms( ShaderLib.background.uniforms ),
  8416. vertexShader: ShaderLib.background.vertexShader,
  8417. fragmentShader: ShaderLib.background.fragmentShader,
  8418. side: FrontSide,
  8419. depthTest: false,
  8420. depthWrite: false,
  8421. fog: false
  8422. } )
  8423. );
  8424. planeMesh.geometry.deleteAttribute( 'normal' );
  8425. // enable code injection for non-built-in material
  8426. Object.defineProperty( planeMesh.material, 'map', {
  8427. get: function () {
  8428. return this.uniforms.t2D.value;
  8429. }
  8430. } );
  8431. objects.update( planeMesh );
  8432. }
  8433. planeMesh.material.uniforms.t2D.value = background;
  8434. if ( background.matrixAutoUpdate === true ) {
  8435. background.updateMatrix();
  8436. }
  8437. planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
  8438. if ( currentBackground !== background ||
  8439. currentBackgroundVersion !== background.version ||
  8440. currentTonemapping !== renderer.toneMapping ) {
  8441. planeMesh.material.needsUpdate = true;
  8442. currentBackground = background;
  8443. currentBackgroundVersion = background.version;
  8444. currentTonemapping = renderer.toneMapping;
  8445. }
  8446. // push to the pre-sorted opaque render list
  8447. renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
  8448. }
  8449. }
  8450. function setClear( color, alpha ) {
  8451. state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
  8452. }
  8453. return {
  8454. getClearColor: function () {
  8455. return clearColor;
  8456. },
  8457. setClearColor: function ( color, alpha = 1 ) {
  8458. clearColor.set( color );
  8459. clearAlpha = alpha;
  8460. setClear( clearColor, clearAlpha );
  8461. },
  8462. getClearAlpha: function () {
  8463. return clearAlpha;
  8464. },
  8465. setClearAlpha: function ( alpha ) {
  8466. clearAlpha = alpha;
  8467. setClear( clearColor, clearAlpha );
  8468. },
  8469. render: render
  8470. };
  8471. }
  8472. function WebGLBindingStates( gl, extensions, attributes, capabilities ) {
  8473. const maxVertexAttributes = gl.getParameter( 34921 );
  8474. const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' );
  8475. const vaoAvailable = capabilities.isWebGL2 || extension !== null;
  8476. const bindingStates = {};
  8477. const defaultState = createBindingState( null );
  8478. let currentState = defaultState;
  8479. function setup( object, material, program, geometry, index ) {
  8480. let updateBuffers = false;
  8481. if ( vaoAvailable ) {
  8482. const state = getBindingState( geometry, program, material );
  8483. if ( currentState !== state ) {
  8484. currentState = state;
  8485. bindVertexArrayObject( currentState.object );
  8486. }
  8487. updateBuffers = needsUpdate( geometry, index );
  8488. if ( updateBuffers ) saveCache( geometry, index );
  8489. } else {
  8490. const wireframe = ( material.wireframe === true );
  8491. if ( currentState.geometry !== geometry.id ||
  8492. currentState.program !== program.id ||
  8493. currentState.wireframe !== wireframe ) {
  8494. currentState.geometry = geometry.id;
  8495. currentState.program = program.id;
  8496. currentState.wireframe = wireframe;
  8497. updateBuffers = true;
  8498. }
  8499. }
  8500. if ( object.isInstancedMesh === true ) {
  8501. updateBuffers = true;
  8502. }
  8503. if ( index !== null ) {
  8504. attributes.update( index, 34963 );
  8505. }
  8506. if ( updateBuffers ) {
  8507. setupVertexAttributes( object, material, program, geometry );
  8508. if ( index !== null ) {
  8509. gl.bindBuffer( 34963, attributes.get( index ).buffer );
  8510. }
  8511. }
  8512. }
  8513. function createVertexArrayObject() {
  8514. if ( capabilities.isWebGL2 ) return gl.createVertexArray();
  8515. return extension.createVertexArrayOES();
  8516. }
  8517. function bindVertexArrayObject( vao ) {
  8518. if ( capabilities.isWebGL2 ) return gl.bindVertexArray( vao );
  8519. return extension.bindVertexArrayOES( vao );
  8520. }
  8521. function deleteVertexArrayObject( vao ) {
  8522. if ( capabilities.isWebGL2 ) return gl.deleteVertexArray( vao );
  8523. return extension.deleteVertexArrayOES( vao );
  8524. }
  8525. function getBindingState( geometry, program, material ) {
  8526. const wireframe = ( material.wireframe === true );
  8527. let programMap = bindingStates[ geometry.id ];
  8528. if ( programMap === undefined ) {
  8529. programMap = {};
  8530. bindingStates[ geometry.id ] = programMap;
  8531. }
  8532. let stateMap = programMap[ program.id ];
  8533. if ( stateMap === undefined ) {
  8534. stateMap = {};
  8535. programMap[ program.id ] = stateMap;
  8536. }
  8537. let state = stateMap[ wireframe ];
  8538. if ( state === undefined ) {
  8539. state = createBindingState( createVertexArrayObject() );
  8540. stateMap[ wireframe ] = state;
  8541. }
  8542. return state;
  8543. }
  8544. function createBindingState( vao ) {
  8545. const newAttributes = [];
  8546. const enabledAttributes = [];
  8547. const attributeDivisors = [];
  8548. for ( let i = 0; i < maxVertexAttributes; i ++ ) {
  8549. newAttributes[ i ] = 0;
  8550. enabledAttributes[ i ] = 0;
  8551. attributeDivisors[ i ] = 0;
  8552. }
  8553. return {
  8554. // for backward compatibility on non-VAO support browser
  8555. geometry: null,
  8556. program: null,
  8557. wireframe: false,
  8558. newAttributes: newAttributes,
  8559. enabledAttributes: enabledAttributes,
  8560. attributeDivisors: attributeDivisors,
  8561. object: vao,
  8562. attributes: {},
  8563. index: null
  8564. };
  8565. }
  8566. function needsUpdate( geometry, index ) {
  8567. const cachedAttributes = currentState.attributes;
  8568. const geometryAttributes = geometry.attributes;
  8569. let attributesNum = 0;
  8570. for ( const key in geometryAttributes ) {
  8571. const cachedAttribute = cachedAttributes[ key ];
  8572. const geometryAttribute = geometryAttributes[ key ];
  8573. if ( cachedAttribute === undefined ) return true;
  8574. if ( cachedAttribute.attribute !== geometryAttribute ) return true;
  8575. if ( cachedAttribute.data !== geometryAttribute.data ) return true;
  8576. attributesNum ++;
  8577. }
  8578. if ( currentState.attributesNum !== attributesNum ) return true;
  8579. if ( currentState.index !== index ) return true;
  8580. return false;
  8581. }
  8582. function saveCache( geometry, index ) {
  8583. const cache = {};
  8584. const attributes = geometry.attributes;
  8585. let attributesNum = 0;
  8586. for ( const key in attributes ) {
  8587. const attribute = attributes[ key ];
  8588. const data = {};
  8589. data.attribute = attribute;
  8590. if ( attribute.data ) {
  8591. data.data = attribute.data;
  8592. }
  8593. cache[ key ] = data;
  8594. attributesNum ++;
  8595. }
  8596. currentState.attributes = cache;
  8597. currentState.attributesNum = attributesNum;
  8598. currentState.index = index;
  8599. }
  8600. function initAttributes() {
  8601. const newAttributes = currentState.newAttributes;
  8602. for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
  8603. newAttributes[ i ] = 0;
  8604. }
  8605. }
  8606. function enableAttribute( attribute ) {
  8607. enableAttributeAndDivisor( attribute, 0 );
  8608. }
  8609. function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
  8610. const newAttributes = currentState.newAttributes;
  8611. const enabledAttributes = currentState.enabledAttributes;
  8612. const attributeDivisors = currentState.attributeDivisors;
  8613. newAttributes[ attribute ] = 1;
  8614. if ( enabledAttributes[ attribute ] === 0 ) {
  8615. gl.enableVertexAttribArray( attribute );
  8616. enabledAttributes[ attribute ] = 1;
  8617. }
  8618. if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
  8619. const extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
  8620. extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
  8621. attributeDivisors[ attribute ] = meshPerAttribute;
  8622. }
  8623. }
  8624. function disableUnusedAttributes() {
  8625. const newAttributes = currentState.newAttributes;
  8626. const enabledAttributes = currentState.enabledAttributes;
  8627. for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
  8628. if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
  8629. gl.disableVertexAttribArray( i );
  8630. enabledAttributes[ i ] = 0;
  8631. }
  8632. }
  8633. }
  8634. function vertexAttribPointer( index, size, type, normalized, stride, offset ) {
  8635. if ( capabilities.isWebGL2 === true && ( type === 5124 || type === 5125 ) ) {
  8636. gl.vertexAttribIPointer( index, size, type, stride, offset );
  8637. } else {
  8638. gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
  8639. }
  8640. }
  8641. function setupVertexAttributes( object, material, program, geometry ) {
  8642. if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {
  8643. if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;
  8644. }
  8645. initAttributes();
  8646. const geometryAttributes = geometry.attributes;
  8647. const programAttributes = program.getAttributes();
  8648. const materialDefaultAttributeValues = material.defaultAttributeValues;
  8649. for ( const name in programAttributes ) {
  8650. const programAttribute = programAttributes[ name ];
  8651. if ( programAttribute >= 0 ) {
  8652. const geometryAttribute = geometryAttributes[ name ];
  8653. if ( geometryAttribute !== undefined ) {
  8654. const normalized = geometryAttribute.normalized;
  8655. const size = geometryAttribute.itemSize;
  8656. const attribute = attributes.get( geometryAttribute );
  8657. // TODO Attribute may not be available on context restore
  8658. if ( attribute === undefined ) continue;
  8659. const buffer = attribute.buffer;
  8660. const type = attribute.type;
  8661. const bytesPerElement = attribute.bytesPerElement;
  8662. if ( geometryAttribute.isInterleavedBufferAttribute ) {
  8663. const data = geometryAttribute.data;
  8664. const stride = data.stride;
  8665. const offset = geometryAttribute.offset;
  8666. if ( data && data.isInstancedInterleavedBuffer ) {
  8667. enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
  8668. if ( geometry._maxInstanceCount === undefined ) {
  8669. geometry._maxInstanceCount = data.meshPerAttribute * data.count;
  8670. }
  8671. } else {
  8672. enableAttribute( programAttribute );
  8673. }
  8674. gl.bindBuffer( 34962, buffer );
  8675. vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
  8676. } else {
  8677. if ( geometryAttribute.isInstancedBufferAttribute ) {
  8678. enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
  8679. if ( geometry._maxInstanceCount === undefined ) {
  8680. geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
  8681. }
  8682. } else {
  8683. enableAttribute( programAttribute );
  8684. }
  8685. gl.bindBuffer( 34962, buffer );
  8686. vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
  8687. }
  8688. } else if ( name === 'instanceMatrix' ) {
  8689. const attribute = attributes.get( object.instanceMatrix );
  8690. // TODO Attribute may not be available on context restore
  8691. if ( attribute === undefined ) continue;
  8692. const buffer = attribute.buffer;
  8693. const type = attribute.type;
  8694. enableAttributeAndDivisor( programAttribute + 0, 1 );
  8695. enableAttributeAndDivisor( programAttribute + 1, 1 );
  8696. enableAttributeAndDivisor( programAttribute + 2, 1 );
  8697. enableAttributeAndDivisor( programAttribute + 3, 1 );
  8698. gl.bindBuffer( 34962, buffer );
  8699. gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );
  8700. gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );
  8701. gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );
  8702. gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );
  8703. } else if ( name === 'instanceColor' ) {
  8704. const attribute = attributes.get( object.instanceColor );
  8705. // TODO Attribute may not be available on context restore
  8706. if ( attribute === undefined ) continue;
  8707. const buffer = attribute.buffer;
  8708. const type = attribute.type;
  8709. enableAttributeAndDivisor( programAttribute, 1 );
  8710. gl.bindBuffer( 34962, buffer );
  8711. gl.vertexAttribPointer( programAttribute, 3, type, false, 12, 0 );
  8712. } else if ( materialDefaultAttributeValues !== undefined ) {
  8713. const value = materialDefaultAttributeValues[ name ];
  8714. if ( value !== undefined ) {
  8715. switch ( value.length ) {
  8716. case 2:
  8717. gl.vertexAttrib2fv( programAttribute, value );
  8718. break;
  8719. case 3:
  8720. gl.vertexAttrib3fv( programAttribute, value );
  8721. break;
  8722. case 4:
  8723. gl.vertexAttrib4fv( programAttribute, value );
  8724. break;
  8725. default:
  8726. gl.vertexAttrib1fv( programAttribute, value );
  8727. }
  8728. }
  8729. }
  8730. }
  8731. }
  8732. disableUnusedAttributes();
  8733. }
  8734. function dispose() {
  8735. reset();
  8736. for ( const geometryId in bindingStates ) {
  8737. const programMap = bindingStates[ geometryId ];
  8738. for ( const programId in programMap ) {
  8739. const stateMap = programMap[ programId ];
  8740. for ( const wireframe in stateMap ) {
  8741. deleteVertexArrayObject( stateMap[ wireframe ].object );
  8742. delete stateMap[ wireframe ];
  8743. }
  8744. delete programMap[ programId ];
  8745. }
  8746. delete bindingStates[ geometryId ];
  8747. }
  8748. }
  8749. function releaseStatesOfGeometry( geometry ) {
  8750. if ( bindingStates[ geometry.id ] === undefined ) return;
  8751. const programMap = bindingStates[ geometry.id ];
  8752. for ( const programId in programMap ) {
  8753. const stateMap = programMap[ programId ];
  8754. for ( const wireframe in stateMap ) {
  8755. deleteVertexArrayObject( stateMap[ wireframe ].object );
  8756. delete stateMap[ wireframe ];
  8757. }
  8758. delete programMap[ programId ];
  8759. }
  8760. delete bindingStates[ geometry.id ];
  8761. }
  8762. function releaseStatesOfProgram( program ) {
  8763. for ( const geometryId in bindingStates ) {
  8764. const programMap = bindingStates[ geometryId ];
  8765. if ( programMap[ program.id ] === undefined ) continue;
  8766. const stateMap = programMap[ program.id ];
  8767. for ( const wireframe in stateMap ) {
  8768. deleteVertexArrayObject( stateMap[ wireframe ].object );
  8769. delete stateMap[ wireframe ];
  8770. }
  8771. delete programMap[ program.id ];
  8772. }
  8773. }
  8774. function reset() {
  8775. resetDefaultState();
  8776. if ( currentState === defaultState ) return;
  8777. currentState = defaultState;
  8778. bindVertexArrayObject( currentState.object );
  8779. }
  8780. // for backward-compatilibity
  8781. function resetDefaultState() {
  8782. defaultState.geometry = null;
  8783. defaultState.program = null;
  8784. defaultState.wireframe = false;
  8785. }
  8786. return {
  8787. setup: setup,
  8788. reset: reset,
  8789. resetDefaultState: resetDefaultState,
  8790. dispose: dispose,
  8791. releaseStatesOfGeometry: releaseStatesOfGeometry,
  8792. releaseStatesOfProgram: releaseStatesOfProgram,
  8793. initAttributes: initAttributes,
  8794. enableAttribute: enableAttribute,
  8795. disableUnusedAttributes: disableUnusedAttributes
  8796. };
  8797. }
  8798. function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
  8799. const isWebGL2 = capabilities.isWebGL2;
  8800. let mode;
  8801. function setMode( value ) {
  8802. mode = value;
  8803. }
  8804. function render( start, count ) {
  8805. gl.drawArrays( mode, start, count );
  8806. info.update( count, mode, 1 );
  8807. }
  8808. function renderInstances( start, count, primcount ) {
  8809. if ( primcount === 0 ) return;
  8810. let extension, methodName;
  8811. if ( isWebGL2 ) {
  8812. extension = gl;
  8813. methodName = 'drawArraysInstanced';
  8814. } else {
  8815. extension = extensions.get( 'ANGLE_instanced_arrays' );
  8816. methodName = 'drawArraysInstancedANGLE';
  8817. if ( extension === null ) {
  8818. console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
  8819. return;
  8820. }
  8821. }
  8822. extension[ methodName ]( mode, start, count, primcount );
  8823. info.update( count, mode, primcount );
  8824. }
  8825. //
  8826. this.setMode = setMode;
  8827. this.render = render;
  8828. this.renderInstances = renderInstances;
  8829. }
  8830. function WebGLCapabilities( gl, extensions, parameters ) {
  8831. let maxAnisotropy;
  8832. function getMaxAnisotropy() {
  8833. if ( maxAnisotropy !== undefined ) return maxAnisotropy;
  8834. const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
  8835. if ( extension !== null ) {
  8836. maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
  8837. } else {
  8838. maxAnisotropy = 0;
  8839. }
  8840. return maxAnisotropy;
  8841. }
  8842. function getMaxPrecision( precision ) {
  8843. if ( precision === 'highp' ) {
  8844. if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&
  8845. gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {
  8846. return 'highp';
  8847. }
  8848. precision = 'mediump';
  8849. }
  8850. if ( precision === 'mediump' ) {
  8851. if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&
  8852. gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {
  8853. return 'mediump';
  8854. }
  8855. }
  8856. return 'lowp';
  8857. }
  8858. /* eslint-disable no-undef */
  8859. const isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||
  8860. ( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );
  8861. /* eslint-enable no-undef */
  8862. let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
  8863. const maxPrecision = getMaxPrecision( precision );
  8864. if ( maxPrecision !== precision ) {
  8865. console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
  8866. precision = maxPrecision;
  8867. }
  8868. const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
  8869. const maxTextures = gl.getParameter( 34930 );
  8870. const maxVertexTextures = gl.getParameter( 35660 );
  8871. const maxTextureSize = gl.getParameter( 3379 );
  8872. const maxCubemapSize = gl.getParameter( 34076 );
  8873. const maxAttributes = gl.getParameter( 34921 );
  8874. const maxVertexUniforms = gl.getParameter( 36347 );
  8875. const maxVaryings = gl.getParameter( 36348 );
  8876. const maxFragmentUniforms = gl.getParameter( 36349 );
  8877. const vertexTextures = maxVertexTextures > 0;
  8878. const floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
  8879. const floatVertexTextures = vertexTextures && floatFragmentTextures;
  8880. const maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;
  8881. return {
  8882. isWebGL2: isWebGL2,
  8883. getMaxAnisotropy: getMaxAnisotropy,
  8884. getMaxPrecision: getMaxPrecision,
  8885. precision: precision,
  8886. logarithmicDepthBuffer: logarithmicDepthBuffer,
  8887. maxTextures: maxTextures,
  8888. maxVertexTextures: maxVertexTextures,
  8889. maxTextureSize: maxTextureSize,
  8890. maxCubemapSize: maxCubemapSize,
  8891. maxAttributes: maxAttributes,
  8892. maxVertexUniforms: maxVertexUniforms,
  8893. maxVaryings: maxVaryings,
  8894. maxFragmentUniforms: maxFragmentUniforms,
  8895. vertexTextures: vertexTextures,
  8896. floatFragmentTextures: floatFragmentTextures,
  8897. floatVertexTextures: floatVertexTextures,
  8898. maxSamples: maxSamples
  8899. };
  8900. }
  8901. function WebGLClipping( properties ) {
  8902. const scope = this;
  8903. let globalState = null,
  8904. numGlobalPlanes = 0,
  8905. localClippingEnabled = false,
  8906. renderingShadows = false;
  8907. const plane = new Plane(),
  8908. viewNormalMatrix = new Matrix3(),
  8909. uniform = { value: null, needsUpdate: false };
  8910. this.uniform = uniform;
  8911. this.numPlanes = 0;
  8912. this.numIntersection = 0;
  8913. this.init = function ( planes, enableLocalClipping, camera ) {
  8914. const enabled =
  8915. planes.length !== 0 ||
  8916. enableLocalClipping ||
  8917. // enable state of previous frame - the clipping code has to
  8918. // run another frame in order to reset the state:
  8919. numGlobalPlanes !== 0 ||
  8920. localClippingEnabled;
  8921. localClippingEnabled = enableLocalClipping;
  8922. globalState = projectPlanes( planes, camera, 0 );
  8923. numGlobalPlanes = planes.length;
  8924. return enabled;
  8925. };
  8926. this.beginShadows = function () {
  8927. renderingShadows = true;
  8928. projectPlanes( null );
  8929. };
  8930. this.endShadows = function () {
  8931. renderingShadows = false;
  8932. resetGlobalState();
  8933. };
  8934. this.setState = function ( material, camera, useCache ) {
  8935. const planes = material.clippingPlanes,
  8936. clipIntersection = material.clipIntersection,
  8937. clipShadows = material.clipShadows;
  8938. const materialProperties = properties.get( material );
  8939. if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
  8940. // there's no local clipping
  8941. if ( renderingShadows ) {
  8942. // there's no global clipping
  8943. projectPlanes( null );
  8944. } else {
  8945. resetGlobalState();
  8946. }
  8947. } else {
  8948. const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
  8949. lGlobal = nGlobal * 4;
  8950. let dstArray = materialProperties.clippingState || null;
  8951. uniform.value = dstArray; // ensure unique state
  8952. dstArray = projectPlanes( planes, camera, lGlobal, useCache );
  8953. for ( let i = 0; i !== lGlobal; ++ i ) {
  8954. dstArray[ i ] = globalState[ i ];
  8955. }
  8956. materialProperties.clippingState = dstArray;
  8957. this.numIntersection = clipIntersection ? this.numPlanes : 0;
  8958. this.numPlanes += nGlobal;
  8959. }
  8960. };
  8961. function resetGlobalState() {
  8962. if ( uniform.value !== globalState ) {
  8963. uniform.value = globalState;
  8964. uniform.needsUpdate = numGlobalPlanes > 0;
  8965. }
  8966. scope.numPlanes = numGlobalPlanes;
  8967. scope.numIntersection = 0;
  8968. }
  8969. function projectPlanes( planes, camera, dstOffset, skipTransform ) {
  8970. const nPlanes = planes !== null ? planes.length : 0;
  8971. let dstArray = null;
  8972. if ( nPlanes !== 0 ) {
  8973. dstArray = uniform.value;
  8974. if ( skipTransform !== true || dstArray === null ) {
  8975. const flatSize = dstOffset + nPlanes * 4,
  8976. viewMatrix = camera.matrixWorldInverse;
  8977. viewNormalMatrix.getNormalMatrix( viewMatrix );
  8978. if ( dstArray === null || dstArray.length < flatSize ) {
  8979. dstArray = new Float32Array( flatSize );
  8980. }
  8981. for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
  8982. plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
  8983. plane.normal.toArray( dstArray, i4 );
  8984. dstArray[ i4 + 3 ] = plane.constant;
  8985. }
  8986. }
  8987. uniform.value = dstArray;
  8988. uniform.needsUpdate = true;
  8989. }
  8990. scope.numPlanes = nPlanes;
  8991. scope.numIntersection = 0;
  8992. return dstArray;
  8993. }
  8994. }
  8995. function WebGLCubeMaps( renderer ) {
  8996. let cubemaps = new WeakMap();
  8997. function mapTextureMapping( texture, mapping ) {
  8998. if ( mapping === EquirectangularReflectionMapping ) {
  8999. texture.mapping = CubeReflectionMapping;
  9000. } else if ( mapping === EquirectangularRefractionMapping ) {
  9001. texture.mapping = CubeRefractionMapping;
  9002. }
  9003. return texture;
  9004. }
  9005. function get( texture ) {
  9006. if ( texture && texture.isTexture ) {
  9007. const mapping = texture.mapping;
  9008. if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
  9009. if ( cubemaps.has( texture ) ) {
  9010. const cubemap = cubemaps.get( texture ).texture;
  9011. return mapTextureMapping( cubemap, texture.mapping );
  9012. } else {
  9013. const image = texture.image;
  9014. if ( image && image.height > 0 ) {
  9015. const currentRenderList = renderer.getRenderList();
  9016. const currentRenderTarget = renderer.getRenderTarget();
  9017. const renderTarget = new WebGLCubeRenderTarget( image.height / 2 );
  9018. renderTarget.fromEquirectangularTexture( renderer, texture );
  9019. cubemaps.set( texture, renderTarget );
  9020. renderer.setRenderTarget( currentRenderTarget );
  9021. renderer.setRenderList( currentRenderList );
  9022. texture.addEventListener( 'dispose', onTextureDispose );
  9023. return mapTextureMapping( renderTarget.texture, texture.mapping );
  9024. } else {
  9025. // image not yet ready. try the conversion next frame
  9026. return null;
  9027. }
  9028. }
  9029. }
  9030. }
  9031. return texture;
  9032. }
  9033. function onTextureDispose( event ) {
  9034. const texture = event.target;
  9035. texture.removeEventListener( 'dispose', onTextureDispose );
  9036. const cubemap = cubemaps.get( texture );
  9037. if ( cubemap !== undefined ) {
  9038. cubemaps.delete( texture );
  9039. cubemap.dispose();
  9040. }
  9041. }
  9042. function dispose() {
  9043. cubemaps = new WeakMap();
  9044. }
  9045. return {
  9046. get: get,
  9047. dispose: dispose
  9048. };
  9049. }
  9050. function WebGLExtensions( gl ) {
  9051. const extensions = {};
  9052. return {
  9053. has: function ( name ) {
  9054. if ( extensions[ name ] !== undefined ) {
  9055. return extensions[ name ] !== null;
  9056. }
  9057. let extension;
  9058. switch ( name ) {
  9059. case 'WEBGL_depth_texture':
  9060. extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
  9061. break;
  9062. case 'EXT_texture_filter_anisotropic':
  9063. extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
  9064. break;
  9065. case 'WEBGL_compressed_texture_s3tc':
  9066. extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
  9067. break;
  9068. case 'WEBGL_compressed_texture_pvrtc':
  9069. extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
  9070. break;
  9071. default:
  9072. extension = gl.getExtension( name );
  9073. }
  9074. extensions[ name ] = extension;
  9075. return extension !== null;
  9076. },
  9077. get: function ( name ) {
  9078. if ( ! this.has( name ) ) {
  9079. console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
  9080. }
  9081. return extensions[ name ];
  9082. }
  9083. };
  9084. }
  9085. function WebGLGeometries( gl, attributes, info, bindingStates ) {
  9086. const geometries = new WeakMap();
  9087. const wireframeAttributes = new WeakMap();
  9088. function onGeometryDispose( event ) {
  9089. const geometry = event.target;
  9090. const buffergeometry = geometries.get( geometry );
  9091. if ( buffergeometry.index !== null ) {
  9092. attributes.remove( buffergeometry.index );
  9093. }
  9094. for ( const name in buffergeometry.attributes ) {
  9095. attributes.remove( buffergeometry.attributes[ name ] );
  9096. }
  9097. geometry.removeEventListener( 'dispose', onGeometryDispose );
  9098. geometries.delete( geometry );
  9099. const attribute = wireframeAttributes.get( buffergeometry );
  9100. if ( attribute ) {
  9101. attributes.remove( attribute );
  9102. wireframeAttributes.delete( buffergeometry );
  9103. }
  9104. bindingStates.releaseStatesOfGeometry( buffergeometry );
  9105. if ( geometry.isInstancedBufferGeometry === true ) {
  9106. delete geometry._maxInstanceCount;
  9107. }
  9108. //
  9109. info.memory.geometries --;
  9110. }
  9111. function get( object, geometry ) {
  9112. let buffergeometry = geometries.get( geometry );
  9113. if ( buffergeometry ) return buffergeometry;
  9114. geometry.addEventListener( 'dispose', onGeometryDispose );
  9115. if ( geometry.isBufferGeometry ) {
  9116. buffergeometry = geometry;
  9117. } else if ( geometry.isGeometry ) {
  9118. if ( geometry._bufferGeometry === undefined ) {
  9119. geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
  9120. }
  9121. buffergeometry = geometry._bufferGeometry;
  9122. }
  9123. geometries.set( geometry, buffergeometry );
  9124. info.memory.geometries ++;
  9125. return buffergeometry;
  9126. }
  9127. function update( geometry ) {
  9128. const geometryAttributes = geometry.attributes;
  9129. // Updating index buffer in VAO now. See WebGLBindingStates.
  9130. for ( const name in geometryAttributes ) {
  9131. attributes.update( geometryAttributes[ name ], 34962 );
  9132. }
  9133. // morph targets
  9134. const morphAttributes = geometry.morphAttributes;
  9135. for ( const name in morphAttributes ) {
  9136. const array = morphAttributes[ name ];
  9137. for ( let i = 0, l = array.length; i < l; i ++ ) {
  9138. attributes.update( array[ i ], 34962 );
  9139. }
  9140. }
  9141. }
  9142. function updateWireframeAttribute( geometry ) {
  9143. const indices = [];
  9144. const geometryIndex = geometry.index;
  9145. const geometryPosition = geometry.attributes.position;
  9146. let version = 0;
  9147. if ( geometryIndex !== null ) {
  9148. const array = geometryIndex.array;
  9149. version = geometryIndex.version;
  9150. for ( let i = 0, l = array.length; i < l; i += 3 ) {
  9151. const a = array[ i + 0 ];
  9152. const b = array[ i + 1 ];
  9153. const c = array[ i + 2 ];
  9154. indices.push( a, b, b, c, c, a );
  9155. }
  9156. } else {
  9157. const array = geometryPosition.array;
  9158. version = geometryPosition.version;
  9159. for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
  9160. const a = i + 0;
  9161. const b = i + 1;
  9162. const c = i + 2;
  9163. indices.push( a, b, b, c, c, a );
  9164. }
  9165. }
  9166. const attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
  9167. attribute.version = version;
  9168. // Updating index buffer in VAO now. See WebGLBindingStates
  9169. //
  9170. const previousAttribute = wireframeAttributes.get( geometry );
  9171. if ( previousAttribute ) attributes.remove( previousAttribute );
  9172. //
  9173. wireframeAttributes.set( geometry, attribute );
  9174. }
  9175. function getWireframeAttribute( geometry ) {
  9176. const currentAttribute = wireframeAttributes.get( geometry );
  9177. if ( currentAttribute ) {
  9178. const geometryIndex = geometry.index;
  9179. if ( geometryIndex !== null ) {
  9180. // if the attribute is obsolete, create a new one
  9181. if ( currentAttribute.version < geometryIndex.version ) {
  9182. updateWireframeAttribute( geometry );
  9183. }
  9184. }
  9185. } else {
  9186. updateWireframeAttribute( geometry );
  9187. }
  9188. return wireframeAttributes.get( geometry );
  9189. }
  9190. return {
  9191. get: get,
  9192. update: update,
  9193. getWireframeAttribute: getWireframeAttribute
  9194. };
  9195. }
  9196. function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
  9197. const isWebGL2 = capabilities.isWebGL2;
  9198. let mode;
  9199. function setMode( value ) {
  9200. mode = value;
  9201. }
  9202. let type, bytesPerElement;
  9203. function setIndex( value ) {
  9204. type = value.type;
  9205. bytesPerElement = value.bytesPerElement;
  9206. }
  9207. function render( start, count ) {
  9208. gl.drawElements( mode, count, type, start * bytesPerElement );
  9209. info.update( count, mode, 1 );
  9210. }
  9211. function renderInstances( start, count, primcount ) {
  9212. if ( primcount === 0 ) return;
  9213. let extension, methodName;
  9214. if ( isWebGL2 ) {
  9215. extension = gl;
  9216. methodName = 'drawElementsInstanced';
  9217. } else {
  9218. extension = extensions.get( 'ANGLE_instanced_arrays' );
  9219. methodName = 'drawElementsInstancedANGLE';
  9220. if ( extension === null ) {
  9221. console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
  9222. return;
  9223. }
  9224. }
  9225. extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );
  9226. info.update( count, mode, primcount );
  9227. }
  9228. //
  9229. this.setMode = setMode;
  9230. this.setIndex = setIndex;
  9231. this.render = render;
  9232. this.renderInstances = renderInstances;
  9233. }
  9234. function WebGLInfo( gl ) {
  9235. const memory = {
  9236. geometries: 0,
  9237. textures: 0
  9238. };
  9239. const render = {
  9240. frame: 0,
  9241. calls: 0,
  9242. triangles: 0,
  9243. points: 0,
  9244. lines: 0
  9245. };
  9246. function update( count, mode, instanceCount ) {
  9247. render.calls ++;
  9248. switch ( mode ) {
  9249. case 4:
  9250. render.triangles += instanceCount * ( count / 3 );
  9251. break;
  9252. case 1:
  9253. render.lines += instanceCount * ( count / 2 );
  9254. break;
  9255. case 3:
  9256. render.lines += instanceCount * ( count - 1 );
  9257. break;
  9258. case 2:
  9259. render.lines += instanceCount * count;
  9260. break;
  9261. case 0:
  9262. render.points += instanceCount * count;
  9263. break;
  9264. default:
  9265. console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
  9266. break;
  9267. }
  9268. }
  9269. function reset() {
  9270. render.frame ++;
  9271. render.calls = 0;
  9272. render.triangles = 0;
  9273. render.points = 0;
  9274. render.lines = 0;
  9275. }
  9276. return {
  9277. memory: memory,
  9278. render: render,
  9279. programs: null,
  9280. autoReset: true,
  9281. reset: reset,
  9282. update: update
  9283. };
  9284. }
  9285. function numericalSort( a, b ) {
  9286. return a[ 0 ] - b[ 0 ];
  9287. }
  9288. function absNumericalSort( a, b ) {
  9289. return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
  9290. }
  9291. function WebGLMorphtargets( gl ) {
  9292. const influencesList = {};
  9293. const morphInfluences = new Float32Array( 8 );
  9294. const workInfluences = [];
  9295. for ( let i = 0; i < 8; i ++ ) {
  9296. workInfluences[ i ] = [ i, 0 ];
  9297. }
  9298. function update( object, geometry, material, program ) {
  9299. const objectInfluences = object.morphTargetInfluences;
  9300. // When object doesn't have morph target influences defined, we treat it as a 0-length array
  9301. // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
  9302. const length = objectInfluences === undefined ? 0 : objectInfluences.length;
  9303. let influences = influencesList[ geometry.id ];
  9304. if ( influences === undefined ) {
  9305. // initialise list
  9306. influences = [];
  9307. for ( let i = 0; i < length; i ++ ) {
  9308. influences[ i ] = [ i, 0 ];
  9309. }
  9310. influencesList[ geometry.id ] = influences;
  9311. }
  9312. // Collect influences
  9313. for ( let i = 0; i < length; i ++ ) {
  9314. const influence = influences[ i ];
  9315. influence[ 0 ] = i;
  9316. influence[ 1 ] = objectInfluences[ i ];
  9317. }
  9318. influences.sort( absNumericalSort );
  9319. for ( let i = 0; i < 8; i ++ ) {
  9320. if ( i < length && influences[ i ][ 1 ] ) {
  9321. workInfluences[ i ][ 0 ] = influences[ i ][ 0 ];
  9322. workInfluences[ i ][ 1 ] = influences[ i ][ 1 ];
  9323. } else {
  9324. workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER;
  9325. workInfluences[ i ][ 1 ] = 0;
  9326. }
  9327. }
  9328. workInfluences.sort( numericalSort );
  9329. const morphTargets = material.morphTargets && geometry.morphAttributes.position;
  9330. const morphNormals = material.morphNormals && geometry.morphAttributes.normal;
  9331. let morphInfluencesSum = 0;
  9332. for ( let i = 0; i < 8; i ++ ) {
  9333. const influence = workInfluences[ i ];
  9334. const index = influence[ 0 ];
  9335. const value = influence[ 1 ];
  9336. if ( index !== Number.MAX_SAFE_INTEGER && value ) {
  9337. if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) {
  9338. geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
  9339. }
  9340. if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) {
  9341. geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
  9342. }
  9343. morphInfluences[ i ] = value;
  9344. morphInfluencesSum += value;
  9345. } else {
  9346. if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) {
  9347. geometry.deleteAttribute( 'morphTarget' + i );
  9348. }
  9349. if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) {
  9350. geometry.deleteAttribute( 'morphNormal' + i );
  9351. }
  9352. morphInfluences[ i ] = 0;
  9353. }
  9354. }
  9355. // GLSL shader uses formula baseinfluence * base + sum(target * influence)
  9356. // This allows us to switch between absolute morphs and relative morphs without changing shader code
  9357. // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
  9358. const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
  9359. program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
  9360. program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
  9361. }
  9362. return {
  9363. update: update
  9364. };
  9365. }
  9366. function WebGLObjects( gl, geometries, attributes, info ) {
  9367. let updateMap = new WeakMap();
  9368. function update( object ) {
  9369. const frame = info.render.frame;
  9370. const geometry = object.geometry;
  9371. const buffergeometry = geometries.get( object, geometry );
  9372. // Update once per frame
  9373. if ( updateMap.get( buffergeometry ) !== frame ) {
  9374. if ( geometry.isGeometry ) {
  9375. buffergeometry.updateFromObject( object );
  9376. }
  9377. geometries.update( buffergeometry );
  9378. updateMap.set( buffergeometry, frame );
  9379. }
  9380. if ( object.isInstancedMesh ) {
  9381. if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
  9382. object.addEventListener( 'dispose', onInstancedMeshDispose );
  9383. }
  9384. attributes.update( object.instanceMatrix, 34962 );
  9385. if ( object.instanceColor !== null ) {
  9386. attributes.update( object.instanceColor, 34962 );
  9387. }
  9388. }
  9389. return buffergeometry;
  9390. }
  9391. function dispose() {
  9392. updateMap = new WeakMap();
  9393. }
  9394. function onInstancedMeshDispose( event ) {
  9395. const instancedMesh = event.target;
  9396. instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
  9397. attributes.remove( instancedMesh.instanceMatrix );
  9398. if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
  9399. }
  9400. return {
  9401. update: update,
  9402. dispose: dispose
  9403. };
  9404. }
  9405. function DataTexture2DArray( data = null, width = 1, height = 1, depth = 1 ) {
  9406. Texture.call( this, null );
  9407. this.image = { data, width, height, depth };
  9408. this.magFilter = NearestFilter;
  9409. this.minFilter = NearestFilter;
  9410. this.wrapR = ClampToEdgeWrapping;
  9411. this.generateMipmaps = false;
  9412. this.flipY = false;
  9413. this.needsUpdate = true;
  9414. }
  9415. DataTexture2DArray.prototype = Object.create( Texture.prototype );
  9416. DataTexture2DArray.prototype.constructor = DataTexture2DArray;
  9417. DataTexture2DArray.prototype.isDataTexture2DArray = true;
  9418. function DataTexture3D( data = null, width = 1, height = 1, depth = 1 ) {
  9419. // We're going to add .setXXX() methods for setting properties later.
  9420. // Users can still set in DataTexture3D directly.
  9421. //
  9422. // const texture = new THREE.DataTexture3D( data, width, height, depth );
  9423. // texture.anisotropy = 16;
  9424. //
  9425. // See #14839
  9426. Texture.call( this, null );
  9427. this.image = { data, width, height, depth };
  9428. this.magFilter = NearestFilter;
  9429. this.minFilter = NearestFilter;
  9430. this.wrapR = ClampToEdgeWrapping;
  9431. this.generateMipmaps = false;
  9432. this.flipY = false;
  9433. this.needsUpdate = true;
  9434. }
  9435. DataTexture3D.prototype = Object.create( Texture.prototype );
  9436. DataTexture3D.prototype.constructor = DataTexture3D;
  9437. DataTexture3D.prototype.isDataTexture3D = true;
  9438. /**
  9439. * Uniforms of a program.
  9440. * Those form a tree structure with a special top-level container for the root,
  9441. * which you get by calling 'new WebGLUniforms( gl, program )'.
  9442. *
  9443. *
  9444. * Properties of inner nodes including the top-level container:
  9445. *
  9446. * .seq - array of nested uniforms
  9447. * .map - nested uniforms by name
  9448. *
  9449. *
  9450. * Methods of all nodes except the top-level container:
  9451. *
  9452. * .setValue( gl, value, [textures] )
  9453. *
  9454. * uploads a uniform value(s)
  9455. * the 'textures' parameter is needed for sampler uniforms
  9456. *
  9457. *
  9458. * Static methods of the top-level container (textures factorizations):
  9459. *
  9460. * .upload( gl, seq, values, textures )
  9461. *
  9462. * sets uniforms in 'seq' to 'values[id].value'
  9463. *
  9464. * .seqWithValue( seq, values ) : filteredSeq
  9465. *
  9466. * filters 'seq' entries with corresponding entry in values
  9467. *
  9468. *
  9469. * Methods of the top-level container (textures factorizations):
  9470. *
  9471. * .setValue( gl, name, value, textures )
  9472. *
  9473. * sets uniform with name 'name' to 'value'
  9474. *
  9475. * .setOptional( gl, obj, prop )
  9476. *
  9477. * like .set for an optional property of the object
  9478. *
  9479. */
  9480. const emptyTexture = new Texture();
  9481. const emptyTexture2dArray = new DataTexture2DArray();
  9482. const emptyTexture3d = new DataTexture3D();
  9483. const emptyCubeTexture = new CubeTexture();
  9484. // --- Utilities ---
  9485. // Array Caches (provide typed arrays for temporary by size)
  9486. const arrayCacheF32 = [];
  9487. const arrayCacheI32 = [];
  9488. // Float32Array caches used for uploading Matrix uniforms
  9489. const mat4array = new Float32Array( 16 );
  9490. const mat3array = new Float32Array( 9 );
  9491. const mat2array = new Float32Array( 4 );
  9492. // Flattening for arrays of vectors and matrices
  9493. function flatten( array, nBlocks, blockSize ) {
  9494. const firstElem = array[ 0 ];
  9495. if ( firstElem <= 0 || firstElem > 0 ) return array;
  9496. // unoptimized: ! isNaN( firstElem )
  9497. // see http://jacksondunstan.com/articles/983
  9498. const n = nBlocks * blockSize;
  9499. let r = arrayCacheF32[ n ];
  9500. if ( r === undefined ) {
  9501. r = new Float32Array( n );
  9502. arrayCacheF32[ n ] = r;
  9503. }
  9504. if ( nBlocks !== 0 ) {
  9505. firstElem.toArray( r, 0 );
  9506. for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) {
  9507. offset += blockSize;
  9508. array[ i ].toArray( r, offset );
  9509. }
  9510. }
  9511. return r;
  9512. }
  9513. function arraysEqual( a, b ) {
  9514. if ( a.length !== b.length ) return false;
  9515. for ( let i = 0, l = a.length; i < l; i ++ ) {
  9516. if ( a[ i ] !== b[ i ] ) return false;
  9517. }
  9518. return true;
  9519. }
  9520. function copyArray( a, b ) {
  9521. for ( let i = 0, l = b.length; i < l; i ++ ) {
  9522. a[ i ] = b[ i ];
  9523. }
  9524. }
  9525. // Texture unit allocation
  9526. function allocTexUnits( textures, n ) {
  9527. let r = arrayCacheI32[ n ];
  9528. if ( r === undefined ) {
  9529. r = new Int32Array( n );
  9530. arrayCacheI32[ n ] = r;
  9531. }
  9532. for ( let i = 0; i !== n; ++ i ) {
  9533. r[ i ] = textures.allocateTextureUnit();
  9534. }
  9535. return r;
  9536. }
  9537. // --- Setters ---
  9538. // Note: Defining these methods externally, because they come in a bunch
  9539. // and this way their names minify.
  9540. // Single scalar
  9541. function setValueV1f( gl, v ) {
  9542. const cache = this.cache;
  9543. if ( cache[ 0 ] === v ) return;
  9544. gl.uniform1f( this.addr, v );
  9545. cache[ 0 ] = v;
  9546. }
  9547. // Single float vector (from flat array or THREE.VectorN)
  9548. function setValueV2f( gl, v ) {
  9549. const cache = this.cache;
  9550. if ( v.x !== undefined ) {
  9551. if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
  9552. gl.uniform2f( this.addr, v.x, v.y );
  9553. cache[ 0 ] = v.x;
  9554. cache[ 1 ] = v.y;
  9555. }
  9556. } else {
  9557. if ( arraysEqual( cache, v ) ) return;
  9558. gl.uniform2fv( this.addr, v );
  9559. copyArray( cache, v );
  9560. }
  9561. }
  9562. function setValueV3f( gl, v ) {
  9563. const cache = this.cache;
  9564. if ( v.x !== undefined ) {
  9565. if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
  9566. gl.uniform3f( this.addr, v.x, v.y, v.z );
  9567. cache[ 0 ] = v.x;
  9568. cache[ 1 ] = v.y;
  9569. cache[ 2 ] = v.z;
  9570. }
  9571. } else if ( v.r !== undefined ) {
  9572. if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
  9573. gl.uniform3f( this.addr, v.r, v.g, v.b );
  9574. cache[ 0 ] = v.r;
  9575. cache[ 1 ] = v.g;
  9576. cache[ 2 ] = v.b;
  9577. }
  9578. } else {
  9579. if ( arraysEqual( cache, v ) ) return;
  9580. gl.uniform3fv( this.addr, v );
  9581. copyArray( cache, v );
  9582. }
  9583. }
  9584. function setValueV4f( gl, v ) {
  9585. const cache = this.cache;
  9586. if ( v.x !== undefined ) {
  9587. if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
  9588. gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
  9589. cache[ 0 ] = v.x;
  9590. cache[ 1 ] = v.y;
  9591. cache[ 2 ] = v.z;
  9592. cache[ 3 ] = v.w;
  9593. }
  9594. } else {
  9595. if ( arraysEqual( cache, v ) ) return;
  9596. gl.uniform4fv( this.addr, v );
  9597. copyArray( cache, v );
  9598. }
  9599. }
  9600. // Single matrix (from flat array or MatrixN)
  9601. function setValueM2( gl, v ) {
  9602. const cache = this.cache;
  9603. const elements = v.elements;
  9604. if ( elements === undefined ) {
  9605. if ( arraysEqual( cache, v ) ) return;
  9606. gl.uniformMatrix2fv( this.addr, false, v );
  9607. copyArray( cache, v );
  9608. } else {
  9609. if ( arraysEqual( cache, elements ) ) return;
  9610. mat2array.set( elements );
  9611. gl.uniformMatrix2fv( this.addr, false, mat2array );
  9612. copyArray( cache, elements );
  9613. }
  9614. }
  9615. function setValueM3( gl, v ) {
  9616. const cache = this.cache;
  9617. const elements = v.elements;
  9618. if ( elements === undefined ) {
  9619. if ( arraysEqual( cache, v ) ) return;
  9620. gl.uniformMatrix3fv( this.addr, false, v );
  9621. copyArray( cache, v );
  9622. } else {
  9623. if ( arraysEqual( cache, elements ) ) return;
  9624. mat3array.set( elements );
  9625. gl.uniformMatrix3fv( this.addr, false, mat3array );
  9626. copyArray( cache, elements );
  9627. }
  9628. }
  9629. function setValueM4( gl, v ) {
  9630. const cache = this.cache;
  9631. const elements = v.elements;
  9632. if ( elements === undefined ) {
  9633. if ( arraysEqual( cache, v ) ) return;
  9634. gl.uniformMatrix4fv( this.addr, false, v );
  9635. copyArray( cache, v );
  9636. } else {
  9637. if ( arraysEqual( cache, elements ) ) return;
  9638. mat4array.set( elements );
  9639. gl.uniformMatrix4fv( this.addr, false, mat4array );
  9640. copyArray( cache, elements );
  9641. }
  9642. }
  9643. // Single texture (2D / Cube)
  9644. function setValueT1( gl, v, textures ) {
  9645. const cache = this.cache;
  9646. const unit = textures.allocateTextureUnit();
  9647. if ( cache[ 0 ] !== unit ) {
  9648. gl.uniform1i( this.addr, unit );
  9649. cache[ 0 ] = unit;
  9650. }
  9651. textures.safeSetTexture2D( v || emptyTexture, unit );
  9652. }
  9653. function setValueT2DArray1( gl, v, textures ) {
  9654. const cache = this.cache;
  9655. const unit = textures.allocateTextureUnit();
  9656. if ( cache[ 0 ] !== unit ) {
  9657. gl.uniform1i( this.addr, unit );
  9658. cache[ 0 ] = unit;
  9659. }
  9660. textures.setTexture2DArray( v || emptyTexture2dArray, unit );
  9661. }
  9662. function setValueT3D1( gl, v, textures ) {
  9663. const cache = this.cache;
  9664. const unit = textures.allocateTextureUnit();
  9665. if ( cache[ 0 ] !== unit ) {
  9666. gl.uniform1i( this.addr, unit );
  9667. cache[ 0 ] = unit;
  9668. }
  9669. textures.setTexture3D( v || emptyTexture3d, unit );
  9670. }
  9671. function setValueT6( gl, v, textures ) {
  9672. const cache = this.cache;
  9673. const unit = textures.allocateTextureUnit();
  9674. if ( cache[ 0 ] !== unit ) {
  9675. gl.uniform1i( this.addr, unit );
  9676. cache[ 0 ] = unit;
  9677. }
  9678. textures.safeSetTextureCube( v || emptyCubeTexture, unit );
  9679. }
  9680. // Integer / Boolean vectors or arrays thereof (always flat arrays)
  9681. function setValueV1i( gl, v ) {
  9682. const cache = this.cache;
  9683. if ( cache[ 0 ] === v ) return;
  9684. gl.uniform1i( this.addr, v );
  9685. cache[ 0 ] = v;
  9686. }
  9687. function setValueV2i( gl, v ) {
  9688. const cache = this.cache;
  9689. if ( arraysEqual( cache, v ) ) return;
  9690. gl.uniform2iv( this.addr, v );
  9691. copyArray( cache, v );
  9692. }
  9693. function setValueV3i( gl, v ) {
  9694. const cache = this.cache;
  9695. if ( arraysEqual( cache, v ) ) return;
  9696. gl.uniform3iv( this.addr, v );
  9697. copyArray( cache, v );
  9698. }
  9699. function setValueV4i( gl, v ) {
  9700. const cache = this.cache;
  9701. if ( arraysEqual( cache, v ) ) return;
  9702. gl.uniform4iv( this.addr, v );
  9703. copyArray( cache, v );
  9704. }
  9705. // uint
  9706. function setValueV1ui( gl, v ) {
  9707. const cache = this.cache;
  9708. if ( cache[ 0 ] === v ) return;
  9709. gl.uniform1ui( this.addr, v );
  9710. cache[ 0 ] = v;
  9711. }
  9712. // Helper to pick the right setter for the singular case
  9713. function getSingularSetter( type ) {
  9714. switch ( type ) {
  9715. case 0x1406: return setValueV1f; // FLOAT
  9716. case 0x8b50: return setValueV2f; // _VEC2
  9717. case 0x8b51: return setValueV3f; // _VEC3
  9718. case 0x8b52: return setValueV4f; // _VEC4
  9719. case 0x8b5a: return setValueM2; // _MAT2
  9720. case 0x8b5b: return setValueM3; // _MAT3
  9721. case 0x8b5c: return setValueM4; // _MAT4
  9722. case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
  9723. case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
  9724. case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
  9725. case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
  9726. case 0x1405: return setValueV1ui; // UINT
  9727. case 0x8b5e: // SAMPLER_2D
  9728. case 0x8d66: // SAMPLER_EXTERNAL_OES
  9729. case 0x8dca: // INT_SAMPLER_2D
  9730. case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
  9731. case 0x8b62: // SAMPLER_2D_SHADOW
  9732. return setValueT1;
  9733. case 0x8b5f: // SAMPLER_3D
  9734. case 0x8dcb: // INT_SAMPLER_3D
  9735. case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
  9736. return setValueT3D1;
  9737. case 0x8b60: // SAMPLER_CUBE
  9738. case 0x8dcc: // INT_SAMPLER_CUBE
  9739. case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
  9740. case 0x8dc5: // SAMPLER_CUBE_SHADOW
  9741. return setValueT6;
  9742. case 0x8dc1: // SAMPLER_2D_ARRAY
  9743. case 0x8dcf: // INT_SAMPLER_2D_ARRAY
  9744. case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
  9745. case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
  9746. return setValueT2DArray1;
  9747. }
  9748. }
  9749. // Array of scalars
  9750. function setValueV1fArray( gl, v ) {
  9751. gl.uniform1fv( this.addr, v );
  9752. }
  9753. // Integer / Boolean vectors or arrays thereof (always flat arrays)
  9754. function setValueV1iArray( gl, v ) {
  9755. gl.uniform1iv( this.addr, v );
  9756. }
  9757. function setValueV2iArray( gl, v ) {
  9758. gl.uniform2iv( this.addr, v );
  9759. }
  9760. function setValueV3iArray( gl, v ) {
  9761. gl.uniform3iv( this.addr, v );
  9762. }
  9763. function setValueV4iArray( gl, v ) {
  9764. gl.uniform4iv( this.addr, v );
  9765. }
  9766. // Array of vectors (flat or from THREE classes)
  9767. function setValueV2fArray( gl, v ) {
  9768. const data = flatten( v, this.size, 2 );
  9769. gl.uniform2fv( this.addr, data );
  9770. }
  9771. function setValueV3fArray( gl, v ) {
  9772. const data = flatten( v, this.size, 3 );
  9773. gl.uniform3fv( this.addr, data );
  9774. }
  9775. function setValueV4fArray( gl, v ) {
  9776. const data = flatten( v, this.size, 4 );
  9777. gl.uniform4fv( this.addr, data );
  9778. }
  9779. // Array of matrices (flat or from THREE clases)
  9780. function setValueM2Array( gl, v ) {
  9781. const data = flatten( v, this.size, 4 );
  9782. gl.uniformMatrix2fv( this.addr, false, data );
  9783. }
  9784. function setValueM3Array( gl, v ) {
  9785. const data = flatten( v, this.size, 9 );
  9786. gl.uniformMatrix3fv( this.addr, false, data );
  9787. }
  9788. function setValueM4Array( gl, v ) {
  9789. const data = flatten( v, this.size, 16 );
  9790. gl.uniformMatrix4fv( this.addr, false, data );
  9791. }
  9792. // Array of textures (2D / Cube)
  9793. function setValueT1Array( gl, v, textures ) {
  9794. const n = v.length;
  9795. const units = allocTexUnits( textures, n );
  9796. gl.uniform1iv( this.addr, units );
  9797. for ( let i = 0; i !== n; ++ i ) {
  9798. textures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );
  9799. }
  9800. }
  9801. function setValueT6Array( gl, v, textures ) {
  9802. const n = v.length;
  9803. const units = allocTexUnits( textures, n );
  9804. gl.uniform1iv( this.addr, units );
  9805. for ( let i = 0; i !== n; ++ i ) {
  9806. textures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
  9807. }
  9808. }
  9809. // Helper to pick the right setter for a pure (bottom-level) array
  9810. function getPureArraySetter( type ) {
  9811. switch ( type ) {
  9812. case 0x1406: return setValueV1fArray; // FLOAT
  9813. case 0x8b50: return setValueV2fArray; // _VEC2
  9814. case 0x8b51: return setValueV3fArray; // _VEC3
  9815. case 0x8b52: return setValueV4fArray; // _VEC4
  9816. case 0x8b5a: return setValueM2Array; // _MAT2
  9817. case 0x8b5b: return setValueM3Array; // _MAT3
  9818. case 0x8b5c: return setValueM4Array; // _MAT4
  9819. case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
  9820. case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
  9821. case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
  9822. case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
  9823. case 0x8b5e: // SAMPLER_2D
  9824. case 0x8d66: // SAMPLER_EXTERNAL_OES
  9825. case 0x8dca: // INT_SAMPLER_2D
  9826. case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
  9827. case 0x8b62: // SAMPLER_2D_SHADOW
  9828. return setValueT1Array;
  9829. case 0x8b60: // SAMPLER_CUBE
  9830. case 0x8dcc: // INT_SAMPLER_CUBE
  9831. case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
  9832. case 0x8dc5: // SAMPLER_CUBE_SHADOW
  9833. return setValueT6Array;
  9834. }
  9835. }
  9836. // --- Uniform Classes ---
  9837. function SingleUniform( id, activeInfo, addr ) {
  9838. this.id = id;
  9839. this.addr = addr;
  9840. this.cache = [];
  9841. this.setValue = getSingularSetter( activeInfo.type );
  9842. // this.path = activeInfo.name; // DEBUG
  9843. }
  9844. function PureArrayUniform( id, activeInfo, addr ) {
  9845. this.id = id;
  9846. this.addr = addr;
  9847. this.cache = [];
  9848. this.size = activeInfo.size;
  9849. this.setValue = getPureArraySetter( activeInfo.type );
  9850. // this.path = activeInfo.name; // DEBUG
  9851. }
  9852. PureArrayUniform.prototype.updateCache = function ( data ) {
  9853. const cache = this.cache;
  9854. if ( data instanceof Float32Array && cache.length !== data.length ) {
  9855. this.cache = new Float32Array( data.length );
  9856. }
  9857. copyArray( cache, data );
  9858. };
  9859. function StructuredUniform( id ) {
  9860. this.id = id;
  9861. this.seq = [];
  9862. this.map = {};
  9863. }
  9864. StructuredUniform.prototype.setValue = function ( gl, value, textures ) {
  9865. const seq = this.seq;
  9866. for ( let i = 0, n = seq.length; i !== n; ++ i ) {
  9867. const u = seq[ i ];
  9868. u.setValue( gl, value[ u.id ], textures );
  9869. }
  9870. };
  9871. // --- Top-level ---
  9872. // Parser - builds up the property tree from the path strings
  9873. const RePathPart = /(\w+)(\])?(\[|\.)?/g;
  9874. // extracts
  9875. // - the identifier (member name or array index)
  9876. // - followed by an optional right bracket (found when array index)
  9877. // - followed by an optional left bracket or dot (type of subscript)
  9878. //
  9879. // Note: These portions can be read in a non-overlapping fashion and
  9880. // allow straightforward parsing of the hierarchy that WebGL encodes
  9881. // in the uniform names.
  9882. function addUniform( container, uniformObject ) {
  9883. container.seq.push( uniformObject );
  9884. container.map[ uniformObject.id ] = uniformObject;
  9885. }
  9886. function parseUniform( activeInfo, addr, container ) {
  9887. const path = activeInfo.name,
  9888. pathLength = path.length;
  9889. // reset RegExp object, because of the early exit of a previous run
  9890. RePathPart.lastIndex = 0;
  9891. while ( true ) {
  9892. const match = RePathPart.exec( path ),
  9893. matchEnd = RePathPart.lastIndex;
  9894. let id = match[ 1 ];
  9895. const idIsIndex = match[ 2 ] === ']',
  9896. subscript = match[ 3 ];
  9897. if ( idIsIndex ) id = id | 0; // convert to integer
  9898. if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
  9899. // bare name or "pure" bottom-level array "[0]" suffix
  9900. addUniform( container, subscript === undefined ?
  9901. new SingleUniform( id, activeInfo, addr ) :
  9902. new PureArrayUniform( id, activeInfo, addr ) );
  9903. break;
  9904. } else {
  9905. // step into inner node / create it in case it doesn't exist
  9906. const map = container.map;
  9907. let next = map[ id ];
  9908. if ( next === undefined ) {
  9909. next = new StructuredUniform( id );
  9910. addUniform( container, next );
  9911. }
  9912. container = next;
  9913. }
  9914. }
  9915. }
  9916. // Root Container
  9917. function WebGLUniforms( gl, program ) {
  9918. this.seq = [];
  9919. this.map = {};
  9920. const n = gl.getProgramParameter( program, 35718 );
  9921. for ( let i = 0; i < n; ++ i ) {
  9922. const info = gl.getActiveUniform( program, i ),
  9923. addr = gl.getUniformLocation( program, info.name );
  9924. parseUniform( info, addr, this );
  9925. }
  9926. }
  9927. WebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {
  9928. const u = this.map[ name ];
  9929. if ( u !== undefined ) u.setValue( gl, value, textures );
  9930. };
  9931. WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
  9932. const v = object[ name ];
  9933. if ( v !== undefined ) this.setValue( gl, name, v );
  9934. };
  9935. // Static interface
  9936. WebGLUniforms.upload = function ( gl, seq, values, textures ) {
  9937. for ( let i = 0, n = seq.length; i !== n; ++ i ) {
  9938. const u = seq[ i ],
  9939. v = values[ u.id ];
  9940. if ( v.needsUpdate !== false ) {
  9941. // note: always updating when .needsUpdate is undefined
  9942. u.setValue( gl, v.value, textures );
  9943. }
  9944. }
  9945. };
  9946. WebGLUniforms.seqWithValue = function ( seq, values ) {
  9947. const r = [];
  9948. for ( let i = 0, n = seq.length; i !== n; ++ i ) {
  9949. const u = seq[ i ];
  9950. if ( u.id in values ) r.push( u );
  9951. }
  9952. return r;
  9953. };
  9954. function WebGLShader( gl, type, string ) {
  9955. const shader = gl.createShader( type );
  9956. gl.shaderSource( shader, string );
  9957. gl.compileShader( shader );
  9958. return shader;
  9959. }
  9960. let programIdCount = 0;
  9961. function addLineNumbers( string ) {
  9962. const lines = string.split( '\n' );
  9963. for ( let i = 0; i < lines.length; i ++ ) {
  9964. lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
  9965. }
  9966. return lines.join( '\n' );
  9967. }
  9968. function getEncodingComponents( encoding ) {
  9969. switch ( encoding ) {
  9970. case LinearEncoding:
  9971. return [ 'Linear', '( value )' ];
  9972. case sRGBEncoding:
  9973. return [ 'sRGB', '( value )' ];
  9974. case RGBEEncoding:
  9975. return [ 'RGBE', '( value )' ];
  9976. case RGBM7Encoding:
  9977. return [ 'RGBM', '( value, 7.0 )' ];
  9978. case RGBM16Encoding:
  9979. return [ 'RGBM', '( value, 16.0 )' ];
  9980. case RGBDEncoding:
  9981. return [ 'RGBD', '( value, 256.0 )' ];
  9982. case GammaEncoding:
  9983. return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
  9984. case LogLuvEncoding:
  9985. return [ 'LogLuv', '( value )' ];
  9986. default:
  9987. console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding );
  9988. return [ 'Linear', '( value )' ];
  9989. }
  9990. }
  9991. function getShaderErrors( gl, shader, type ) {
  9992. const status = gl.getShaderParameter( shader, 35713 );
  9993. const log = gl.getShaderInfoLog( shader ).trim();
  9994. if ( status && log === '' ) return '';
  9995. // --enable-privileged-webgl-extension
  9996. // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
  9997. const source = gl.getShaderSource( shader );
  9998. return 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\n' + log + addLineNumbers( source );
  9999. }
  10000. function getTexelDecodingFunction( functionName, encoding ) {
  10001. const components = getEncodingComponents( encoding );
  10002. return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
  10003. }
  10004. function getTexelEncodingFunction( functionName, encoding ) {
  10005. const components = getEncodingComponents( encoding );
  10006. return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
  10007. }
  10008. function getToneMappingFunction( functionName, toneMapping ) {
  10009. let toneMappingName;
  10010. switch ( toneMapping ) {
  10011. case LinearToneMapping:
  10012. toneMappingName = 'Linear';
  10013. break;
  10014. case ReinhardToneMapping:
  10015. toneMappingName = 'Reinhard';
  10016. break;
  10017. case CineonToneMapping:
  10018. toneMappingName = 'OptimizedCineon';
  10019. break;
  10020. case ACESFilmicToneMapping:
  10021. toneMappingName = 'ACESFilmic';
  10022. break;
  10023. case CustomToneMapping:
  10024. toneMappingName = 'Custom';
  10025. break;
  10026. default:
  10027. console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
  10028. toneMappingName = 'Linear';
  10029. }
  10030. return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
  10031. }
  10032. function generateExtensions( parameters ) {
  10033. const chunks = [
  10034. ( parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',
  10035. ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
  10036. ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',
  10037. ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
  10038. ];
  10039. return chunks.filter( filterEmptyLine ).join( '\n' );
  10040. }
  10041. function generateDefines( defines ) {
  10042. const chunks = [];
  10043. for ( const name in defines ) {
  10044. const value = defines[ name ];
  10045. if ( value === false ) continue;
  10046. chunks.push( '#define ' + name + ' ' + value );
  10047. }
  10048. return chunks.join( '\n' );
  10049. }
  10050. function fetchAttributeLocations( gl, program ) {
  10051. const attributes = {};
  10052. const n = gl.getProgramParameter( program, 35721 );
  10053. for ( let i = 0; i < n; i ++ ) {
  10054. const info = gl.getActiveAttrib( program, i );
  10055. const name = info.name;
  10056. // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
  10057. attributes[ name ] = gl.getAttribLocation( program, name );
  10058. }
  10059. return attributes;
  10060. }
  10061. function filterEmptyLine( string ) {
  10062. return string !== '';
  10063. }
  10064. function replaceLightNums( string, parameters ) {
  10065. return string
  10066. .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
  10067. .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
  10068. .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
  10069. .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
  10070. .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
  10071. .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
  10072. .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
  10073. .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
  10074. }
  10075. function replaceClippingPlaneNums( string, parameters ) {
  10076. return string
  10077. .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
  10078. .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
  10079. }
  10080. // Resolve Includes
  10081. const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
  10082. function resolveIncludes( string ) {
  10083. return string.replace( includePattern, includeReplacer );
  10084. }
  10085. function includeReplacer( match, include ) {
  10086. const string = ShaderChunk[ include ];
  10087. if ( string === undefined ) {
  10088. throw new Error( 'Can not resolve #include <' + include + '>' );
  10089. }
  10090. return resolveIncludes( string );
  10091. }
  10092. // Unroll Loops
  10093. const deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
  10094. 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;
  10095. function unrollLoops( string ) {
  10096. return string
  10097. .replace( unrollLoopPattern, loopReplacer )
  10098. .replace( deprecatedUnrollLoopPattern, deprecatedLoopReplacer );
  10099. }
  10100. function deprecatedLoopReplacer( match, start, end, snippet ) {
  10101. console.warn( 'WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.' );
  10102. return loopReplacer( match, start, end, snippet );
  10103. }
  10104. function loopReplacer( match, start, end, snippet ) {
  10105. let string = '';
  10106. for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) {
  10107. string += snippet
  10108. .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' )
  10109. .replace( /UNROLLED_LOOP_INDEX/g, i );
  10110. }
  10111. return string;
  10112. }
  10113. //
  10114. function generatePrecision( parameters ) {
  10115. let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;';
  10116. if ( parameters.precision === 'highp' ) {
  10117. precisionstring += '\n#define HIGH_PRECISION';
  10118. } else if ( parameters.precision === 'mediump' ) {
  10119. precisionstring += '\n#define MEDIUM_PRECISION';
  10120. } else if ( parameters.precision === 'lowp' ) {
  10121. precisionstring += '\n#define LOW_PRECISION';
  10122. }
  10123. return precisionstring;
  10124. }
  10125. function generateShadowMapTypeDefine( parameters ) {
  10126. let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
  10127. if ( parameters.shadowMapType === PCFShadowMap ) {
  10128. shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
  10129. } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
  10130. shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
  10131. } else if ( parameters.shadowMapType === VSMShadowMap ) {
  10132. shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
  10133. }
  10134. return shadowMapTypeDefine;
  10135. }
  10136. function generateEnvMapTypeDefine( parameters ) {
  10137. let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
  10138. if ( parameters.envMap ) {
  10139. switch ( parameters.envMapMode ) {
  10140. case CubeReflectionMapping:
  10141. case CubeRefractionMapping:
  10142. envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
  10143. break;
  10144. case CubeUVReflectionMapping:
  10145. case CubeUVRefractionMapping:
  10146. envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
  10147. break;
  10148. }
  10149. }
  10150. return envMapTypeDefine;
  10151. }
  10152. function generateEnvMapModeDefine( parameters ) {
  10153. let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
  10154. if ( parameters.envMap ) {
  10155. switch ( parameters.envMapMode ) {
  10156. case CubeRefractionMapping:
  10157. case CubeUVRefractionMapping:
  10158. envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
  10159. break;
  10160. }
  10161. }
  10162. return envMapModeDefine;
  10163. }
  10164. function generateEnvMapBlendingDefine( parameters ) {
  10165. let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
  10166. if ( parameters.envMap ) {
  10167. switch ( parameters.combine ) {
  10168. case MultiplyOperation:
  10169. envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
  10170. break;
  10171. case MixOperation:
  10172. envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
  10173. break;
  10174. case AddOperation:
  10175. envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
  10176. break;
  10177. }
  10178. }
  10179. return envMapBlendingDefine;
  10180. }
  10181. function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
  10182. const gl = renderer.getContext();
  10183. const defines = parameters.defines;
  10184. let vertexShader = parameters.vertexShader;
  10185. let fragmentShader = parameters.fragmentShader;
  10186. const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
  10187. const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
  10188. const envMapModeDefine = generateEnvMapModeDefine( parameters );
  10189. const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
  10190. const gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
  10191. const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );
  10192. const customDefines = generateDefines( defines );
  10193. const program = gl.createProgram();
  10194. let prefixVertex, prefixFragment;
  10195. let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
  10196. if ( parameters.isRawShaderMaterial ) {
  10197. prefixVertex = [
  10198. customDefines
  10199. ].filter( filterEmptyLine ).join( '\n' );
  10200. if ( prefixVertex.length > 0 ) {
  10201. prefixVertex += '\n';
  10202. }
  10203. prefixFragment = [
  10204. customExtensions,
  10205. customDefines
  10206. ].filter( filterEmptyLine ).join( '\n' );
  10207. if ( prefixFragment.length > 0 ) {
  10208. prefixFragment += '\n';
  10209. }
  10210. } else {
  10211. prefixVertex = [
  10212. generatePrecision( parameters ),
  10213. '#define SHADER_NAME ' + parameters.shaderName,
  10214. customDefines,
  10215. parameters.instancing ? '#define USE_INSTANCING' : '',
  10216. parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
  10217. parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
  10218. '#define GAMMA_FACTOR ' + gammaFactorDefine,
  10219. '#define MAX_BONES ' + parameters.maxBones,
  10220. ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
  10221. ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
  10222. parameters.map ? '#define USE_MAP' : '',
  10223. parameters.envMap ? '#define USE_ENVMAP' : '',
  10224. parameters.envMap ? '#define ' + envMapModeDefine : '',
  10225. parameters.lightMap ? '#define USE_LIGHTMAP' : '',
  10226. parameters.aoMap ? '#define USE_AOMAP' : '',
  10227. parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
  10228. parameters.bumpMap ? '#define USE_BUMPMAP' : '',
  10229. parameters.normalMap ? '#define USE_NORMALMAP' : '',
  10230. ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
  10231. ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
  10232. parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
  10233. parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
  10234. parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
  10235. parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
  10236. parameters.specularMap ? '#define USE_SPECULARMAP' : '',
  10237. parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
  10238. parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
  10239. parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
  10240. parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
  10241. parameters.vertexTangents ? '#define USE_TANGENT' : '',
  10242. parameters.vertexColors ? '#define USE_COLOR' : '',
  10243. parameters.vertexUvs ? '#define USE_UV' : '',
  10244. parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
  10245. parameters.flatShading ? '#define FLAT_SHADED' : '',
  10246. parameters.skinning ? '#define USE_SKINNING' : '',
  10247. parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
  10248. parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
  10249. parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
  10250. parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
  10251. parameters.flipSided ? '#define FLIP_SIDED' : '',
  10252. parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
  10253. parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
  10254. parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
  10255. parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
  10256. ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
  10257. 'uniform mat4 modelMatrix;',
  10258. 'uniform mat4 modelViewMatrix;',
  10259. 'uniform mat4 projectionMatrix;',
  10260. 'uniform mat4 viewMatrix;',
  10261. 'uniform mat3 normalMatrix;',
  10262. 'uniform vec3 cameraPosition;',
  10263. 'uniform bool isOrthographic;',
  10264. '#ifdef USE_INSTANCING',
  10265. ' attribute mat4 instanceMatrix;',
  10266. '#endif',
  10267. '#ifdef USE_INSTANCING_COLOR',
  10268. ' attribute vec3 instanceColor;',
  10269. '#endif',
  10270. 'attribute vec3 position;',
  10271. 'attribute vec3 normal;',
  10272. 'attribute vec2 uv;',
  10273. '#ifdef USE_TANGENT',
  10274. ' attribute vec4 tangent;',
  10275. '#endif',
  10276. '#ifdef USE_COLOR',
  10277. ' attribute vec3 color;',
  10278. '#endif',
  10279. '#ifdef USE_MORPHTARGETS',
  10280. ' attribute vec3 morphTarget0;',
  10281. ' attribute vec3 morphTarget1;',
  10282. ' attribute vec3 morphTarget2;',
  10283. ' attribute vec3 morphTarget3;',
  10284. ' #ifdef USE_MORPHNORMALS',
  10285. ' attribute vec3 morphNormal0;',
  10286. ' attribute vec3 morphNormal1;',
  10287. ' attribute vec3 morphNormal2;',
  10288. ' attribute vec3 morphNormal3;',
  10289. ' #else',
  10290. ' attribute vec3 morphTarget4;',
  10291. ' attribute vec3 morphTarget5;',
  10292. ' attribute vec3 morphTarget6;',
  10293. ' attribute vec3 morphTarget7;',
  10294. ' #endif',
  10295. '#endif',
  10296. '#ifdef USE_SKINNING',
  10297. ' attribute vec4 skinIndex;',
  10298. ' attribute vec4 skinWeight;',
  10299. '#endif',
  10300. '\n'
  10301. ].filter( filterEmptyLine ).join( '\n' );
  10302. prefixFragment = [
  10303. customExtensions,
  10304. generatePrecision( parameters ),
  10305. '#define SHADER_NAME ' + parameters.shaderName,
  10306. customDefines,
  10307. parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer
  10308. '#define GAMMA_FACTOR ' + gammaFactorDefine,
  10309. ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
  10310. ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
  10311. parameters.map ? '#define USE_MAP' : '',
  10312. parameters.matcap ? '#define USE_MATCAP' : '',
  10313. parameters.envMap ? '#define USE_ENVMAP' : '',
  10314. parameters.envMap ? '#define ' + envMapTypeDefine : '',
  10315. parameters.envMap ? '#define ' + envMapModeDefine : '',
  10316. parameters.envMap ? '#define ' + envMapBlendingDefine : '',
  10317. parameters.lightMap ? '#define USE_LIGHTMAP' : '',
  10318. parameters.aoMap ? '#define USE_AOMAP' : '',
  10319. parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
  10320. parameters.bumpMap ? '#define USE_BUMPMAP' : '',
  10321. parameters.normalMap ? '#define USE_NORMALMAP' : '',
  10322. ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
  10323. ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
  10324. parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
  10325. parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
  10326. parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
  10327. parameters.specularMap ? '#define USE_SPECULARMAP' : '',
  10328. parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
  10329. parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
  10330. parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
  10331. parameters.sheen ? '#define USE_SHEEN' : '',
  10332. parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
  10333. parameters.vertexTangents ? '#define USE_TANGENT' : '',
  10334. parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
  10335. parameters.vertexUvs ? '#define USE_UV' : '',
  10336. parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
  10337. parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
  10338. parameters.flatShading ? '#define FLAT_SHADED' : '',
  10339. parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
  10340. parameters.flipSided ? '#define FLIP_SIDED' : '',
  10341. parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
  10342. parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
  10343. parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
  10344. parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
  10345. parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
  10346. ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
  10347. ( ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ) ? '#define TEXTURE_LOD_EXT' : '',
  10348. 'uniform mat4 viewMatrix;',
  10349. 'uniform vec3 cameraPosition;',
  10350. 'uniform bool isOrthographic;',
  10351. ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
  10352. ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
  10353. ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
  10354. parameters.dithering ? '#define DITHERING' : '',
  10355. ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below
  10356. parameters.map ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
  10357. parameters.matcap ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
  10358. parameters.envMap ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
  10359. parameters.emissiveMap ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
  10360. parameters.lightMap ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',
  10361. getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ),
  10362. parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
  10363. '\n'
  10364. ].filter( filterEmptyLine ).join( '\n' );
  10365. }
  10366. vertexShader = resolveIncludes( vertexShader );
  10367. vertexShader = replaceLightNums( vertexShader, parameters );
  10368. vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
  10369. fragmentShader = resolveIncludes( fragmentShader );
  10370. fragmentShader = replaceLightNums( fragmentShader, parameters );
  10371. fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
  10372. vertexShader = unrollLoops( vertexShader );
  10373. fragmentShader = unrollLoops( fragmentShader );
  10374. if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !== true ) {
  10375. // GLSL 3.0 conversion for built-in materials and ShaderMaterial
  10376. versionString = '#version 300 es\n';
  10377. prefixVertex = [
  10378. '#define attribute in',
  10379. '#define varying out',
  10380. '#define texture2D texture'
  10381. ].join( '\n' ) + '\n' + prefixVertex;
  10382. prefixFragment = [
  10383. '#define varying in',
  10384. ( parameters.glslVersion === GLSL3 ) ? '' : 'out highp vec4 pc_fragColor;',
  10385. ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor',
  10386. '#define gl_FragDepthEXT gl_FragDepth',
  10387. '#define texture2D texture',
  10388. '#define textureCube texture',
  10389. '#define texture2DProj textureProj',
  10390. '#define texture2DLodEXT textureLod',
  10391. '#define texture2DProjLodEXT textureProjLod',
  10392. '#define textureCubeLodEXT textureLod',
  10393. '#define texture2DGradEXT textureGrad',
  10394. '#define texture2DProjGradEXT textureProjGrad',
  10395. '#define textureCubeGradEXT textureGrad'
  10396. ].join( '\n' ) + '\n' + prefixFragment;
  10397. }
  10398. const vertexGlsl = versionString + prefixVertex + vertexShader;
  10399. const fragmentGlsl = versionString + prefixFragment + fragmentShader;
  10400. // console.log( '*VERTEX*', vertexGlsl );
  10401. // console.log( '*FRAGMENT*', fragmentGlsl );
  10402. const glVertexShader = WebGLShader( gl, 35633, vertexGlsl );
  10403. const glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );
  10404. gl.attachShader( program, glVertexShader );
  10405. gl.attachShader( program, glFragmentShader );
  10406. // Force a particular attribute to index 0.
  10407. if ( parameters.index0AttributeName !== undefined ) {
  10408. gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
  10409. } else if ( parameters.morphTargets === true ) {
  10410. // programs with morphTargets displace position out of attribute 0
  10411. gl.bindAttribLocation( program, 0, 'position' );
  10412. }
  10413. gl.linkProgram( program );
  10414. // check for link errors
  10415. if ( renderer.debug.checkShaderErrors ) {
  10416. const programLog = gl.getProgramInfoLog( program ).trim();
  10417. const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
  10418. const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
  10419. let runnable = true;
  10420. let haveDiagnostics = true;
  10421. if ( gl.getProgramParameter( program, 35714 ) === false ) {
  10422. runnable = false;
  10423. const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
  10424. const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
  10425. console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), '35715', gl.getProgramParameter( program, 35715 ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );
  10426. //add:
  10427. if(fragmentErrors){
  10428. console.log(fragmentGlsl.split("\n").map((a, i) => `${i + 1}`.padEnd(5) + a).join("\n") );
  10429. }else {
  10430. console.log(vertexGlsl.split("\n").map((a, i) => `${i + 1}`.padEnd(5) + a).join("\n") );
  10431. }
  10432. } else if ( programLog !== '' ) {
  10433. console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
  10434. } else if ( vertexLog === '' || fragmentLog === '' ) {
  10435. haveDiagnostics = false;
  10436. }
  10437. if ( haveDiagnostics ) {
  10438. this.diagnostics = {
  10439. runnable: runnable,
  10440. programLog: programLog,
  10441. vertexShader: {
  10442. log: vertexLog,
  10443. prefix: prefixVertex
  10444. },
  10445. fragmentShader: {
  10446. log: fragmentLog,
  10447. prefix: prefixFragment
  10448. }
  10449. };
  10450. }
  10451. }
  10452. // Clean up
  10453. // Crashes in iOS9 and iOS10. #18402
  10454. // gl.detachShader( program, glVertexShader );
  10455. // gl.detachShader( program, glFragmentShader );
  10456. gl.deleteShader( glVertexShader );
  10457. gl.deleteShader( glFragmentShader );
  10458. // set up caching for uniform locations
  10459. let cachedUniforms;
  10460. this.getUniforms = function () {
  10461. if ( cachedUniforms === undefined ) {
  10462. cachedUniforms = new WebGLUniforms( gl, program );
  10463. }
  10464. return cachedUniforms;
  10465. };
  10466. // set up caching for attribute locations
  10467. let cachedAttributes;
  10468. this.getAttributes = function () {
  10469. if ( cachedAttributes === undefined ) {
  10470. cachedAttributes = fetchAttributeLocations( gl, program );
  10471. }
  10472. return cachedAttributes;
  10473. };
  10474. // free resource
  10475. this.destroy = function () {
  10476. bindingStates.releaseStatesOfProgram( this );
  10477. gl.deleteProgram( program );
  10478. this.program = undefined;
  10479. };
  10480. //
  10481. this.name = parameters.shaderName;
  10482. this.id = programIdCount ++;
  10483. this.cacheKey = cacheKey;
  10484. this.usedTimes = 1;
  10485. this.program = program;
  10486. this.vertexShader = glVertexShader;
  10487. this.fragmentShader = glFragmentShader;
  10488. return this;
  10489. }
  10490. function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingStates, clipping ) {
  10491. const programs = [];
  10492. const isWebGL2 = capabilities.isWebGL2;
  10493. const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
  10494. const floatVertexTextures = capabilities.floatVertexTextures;
  10495. const maxVertexUniforms = capabilities.maxVertexUniforms;
  10496. const vertexTextures = capabilities.vertexTextures;
  10497. let precision = capabilities.precision;
  10498. const shaderIDs = {
  10499. MeshDepthMaterial: 'depth',
  10500. MeshDistanceMaterial: 'distanceRGBA',
  10501. MeshNormalMaterial: 'normal',
  10502. MeshBasicMaterial: 'basic',
  10503. MeshLambertMaterial: 'lambert',
  10504. MeshPhongMaterial: 'phong',
  10505. MeshToonMaterial: 'toon',
  10506. MeshStandardMaterial: 'physical',
  10507. MeshPhysicalMaterial: 'physical',
  10508. MeshMatcapMaterial: 'matcap',
  10509. LineBasicMaterial: 'basic',
  10510. LineDashedMaterial: 'dashed',
  10511. PointsMaterial: 'points',
  10512. ShadowMaterial: 'shadow',
  10513. SpriteMaterial: 'sprite'
  10514. };
  10515. const parameterNames = [
  10516. 'precision', 'isWebGL2', 'supportsVertexTextures', 'outputEncoding', 'instancing', 'instancingColor',
  10517. 'map', 'mapEncoding', 'matcap', 'matcapEncoding', 'envMap', 'envMapMode', 'envMapEncoding', 'envMapCubeUV',
  10518. 'lightMap', 'lightMapEncoding', 'aoMap', 'emissiveMap', 'emissiveMapEncoding', 'bumpMap', 'normalMap', 'objectSpaceNormalMap', 'tangentSpaceNormalMap', 'clearcoatMap', 'clearcoatRoughnessMap', 'clearcoatNormalMap', 'displacementMap', 'specularMap',
  10519. 'roughnessMap', 'metalnessMap', 'gradientMap',
  10520. 'alphaMap', 'combine', 'vertexColors', 'vertexTangents', 'vertexUvs', 'uvsVertexOnly', 'fog', 'useFog', 'fogExp2',
  10521. 'flatShading', 'sizeAttenuation', 'logarithmicDepthBuffer', 'skinning',
  10522. 'maxBones', 'useVertexTexture', 'morphTargets', 'morphNormals',
  10523. 'maxMorphTargets', 'maxMorphNormals', 'premultipliedAlpha',
  10524. 'numDirLights', 'numPointLights', 'numSpotLights', 'numHemiLights', 'numRectAreaLights',
  10525. 'numDirLightShadows', 'numPointLightShadows', 'numSpotLightShadows',
  10526. 'shadowMapEnabled', 'shadowMapType', 'toneMapping', 'physicallyCorrectLights',
  10527. 'alphaTest', 'doubleSided', 'flipSided', 'numClippingPlanes', 'numClipIntersection', 'depthPacking', 'dithering',
  10528. 'sheen', 'transmissionMap'
  10529. ];
  10530. function getMaxBones( object ) {
  10531. const skeleton = object.skeleton;
  10532. const bones = skeleton.bones;
  10533. if ( floatVertexTextures ) {
  10534. return 1024;
  10535. } else {
  10536. // default for when object is not specified
  10537. // ( for example when prebuilding shader to be used with multiple objects )
  10538. //
  10539. // - leave some extra space for other uniforms
  10540. // - limit here is ANGLE's 254 max uniform vectors
  10541. // (up to 54 should be safe)
  10542. const nVertexUniforms = maxVertexUniforms;
  10543. const nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
  10544. const maxBones = Math.min( nVertexMatrices, bones.length );
  10545. if ( maxBones < bones.length ) {
  10546. console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
  10547. return 0;
  10548. }
  10549. return maxBones;
  10550. }
  10551. }
  10552. function getTextureEncodingFromMap( map ) {
  10553. let encoding;
  10554. if ( map && map.isTexture ) {
  10555. encoding = map.encoding;
  10556. } else if ( map && map.isWebGLRenderTarget ) {
  10557. console.warn( 'THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.' );
  10558. encoding = map.texture.encoding;
  10559. } else {
  10560. encoding = LinearEncoding;
  10561. }
  10562. return encoding;
  10563. }
  10564. function getParameters( material, lights, shadows, scene, object ) {
  10565. const fog = scene.fog;
  10566. const environment = material.isMeshStandardMaterial ? scene.environment : null;
  10567. const envMap = cubemaps.get( material.envMap || environment );
  10568. const shaderID = shaderIDs[ material.type ];
  10569. // heuristics to create shader parameters according to lights in the scene
  10570. // (not to blow over maxLights budget)
  10571. const maxBones = object.isSkinnedMesh ? getMaxBones( object ) : 0;
  10572. if ( material.precision !== null ) {
  10573. precision = capabilities.getMaxPrecision( material.precision );
  10574. if ( precision !== material.precision ) {
  10575. console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
  10576. }
  10577. }
  10578. let vertexShader, fragmentShader;
  10579. if ( shaderID ) {
  10580. const shader = ShaderLib[ shaderID ];
  10581. vertexShader = shader.vertexShader;
  10582. fragmentShader = shader.fragmentShader;
  10583. } else {
  10584. vertexShader = material.vertexShader;
  10585. fragmentShader = material.fragmentShader;
  10586. }
  10587. const currentRenderTarget = renderer.getRenderTarget();
  10588. const parameters = {
  10589. isWebGL2: isWebGL2,
  10590. shaderID: shaderID,
  10591. shaderName: material.type,
  10592. vertexShader: vertexShader,
  10593. fragmentShader: fragmentShader,
  10594. defines: material.defines,
  10595. isRawShaderMaterial: material.isRawShaderMaterial === true,
  10596. glslVersion: material.glslVersion,
  10597. precision: precision,
  10598. instancing: object.isInstancedMesh === true,
  10599. instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
  10600. supportsVertexTextures: vertexTextures,
  10601. outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,
  10602. map: !! material.map,
  10603. mapEncoding: getTextureEncodingFromMap( material.map ),
  10604. matcap: !! material.matcap,
  10605. matcapEncoding: getTextureEncodingFromMap( material.matcap ),
  10606. envMap: !! envMap,
  10607. envMapMode: envMap && envMap.mapping,
  10608. envMapEncoding: getTextureEncodingFromMap( envMap ),
  10609. envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),
  10610. lightMap: !! material.lightMap,
  10611. lightMapEncoding: getTextureEncodingFromMap( material.lightMap ),
  10612. aoMap: !! material.aoMap,
  10613. emissiveMap: !! material.emissiveMap,
  10614. emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),
  10615. bumpMap: !! material.bumpMap,
  10616. normalMap: !! material.normalMap,
  10617. objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
  10618. tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
  10619. clearcoatMap: !! material.clearcoatMap,
  10620. clearcoatRoughnessMap: !! material.clearcoatRoughnessMap,
  10621. clearcoatNormalMap: !! material.clearcoatNormalMap,
  10622. displacementMap: !! material.displacementMap,
  10623. roughnessMap: !! material.roughnessMap,
  10624. metalnessMap: !! material.metalnessMap,
  10625. specularMap: !! material.specularMap,
  10626. alphaMap: !! material.alphaMap,
  10627. gradientMap: !! material.gradientMap,
  10628. sheen: !! material.sheen,
  10629. transmissionMap: !! material.transmissionMap,
  10630. combine: material.combine,
  10631. vertexTangents: ( material.normalMap && material.vertexTangents ),
  10632. vertexColors: material.vertexColors,
  10633. vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap || !! material.transmissionMap,
  10634. uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmissionMap ) && !! material.displacementMap,
  10635. fog: !! fog,
  10636. useFog: material.fog,
  10637. fogExp2: ( fog && fog.isFogExp2 ),
  10638. flatShading: material.flatShading,
  10639. sizeAttenuation: material.sizeAttenuation,
  10640. logarithmicDepthBuffer: logarithmicDepthBuffer,
  10641. skinning: material.skinning && maxBones > 0,
  10642. maxBones: maxBones,
  10643. useVertexTexture: floatVertexTextures,
  10644. morphTargets: material.morphTargets,
  10645. morphNormals: material.morphNormals,
  10646. maxMorphTargets: renderer.maxMorphTargets,
  10647. maxMorphNormals: renderer.maxMorphNormals,
  10648. numDirLights: lights.directional.length,
  10649. numPointLights: lights.point.length,
  10650. numSpotLights: lights.spot.length,
  10651. numRectAreaLights: lights.rectArea.length,
  10652. numHemiLights: lights.hemi.length,
  10653. numDirLightShadows: lights.directionalShadowMap.length,
  10654. numPointLightShadows: lights.pointShadowMap.length,
  10655. numSpotLightShadows: lights.spotShadowMap.length,
  10656. numClippingPlanes: clipping.numPlanes,
  10657. numClipIntersection: clipping.numIntersection,
  10658. dithering: material.dithering,
  10659. shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
  10660. shadowMapType: renderer.shadowMap.type,
  10661. toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
  10662. physicallyCorrectLights: renderer.physicallyCorrectLights,
  10663. premultipliedAlpha: material.premultipliedAlpha,
  10664. alphaTest: material.alphaTest,
  10665. doubleSided: material.side === DoubleSide,
  10666. flipSided: material.side === BackSide,
  10667. depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,
  10668. index0AttributeName: material.index0AttributeName,
  10669. extensionDerivatives: material.extensions && material.extensions.derivatives,
  10670. extensionFragDepth: material.extensions && material.extensions.fragDepth,
  10671. extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
  10672. extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
  10673. rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ),
  10674. rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ),
  10675. rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ),
  10676. customProgramCacheKey: material.customProgramCacheKey()
  10677. };
  10678. return parameters;
  10679. }
  10680. function getProgramCacheKey( parameters ) {
  10681. const array = [];
  10682. if ( parameters.shaderID ) {
  10683. array.push( parameters.shaderID );
  10684. } else {
  10685. array.push( parameters.fragmentShader );
  10686. array.push( parameters.vertexShader );
  10687. }
  10688. if ( parameters.defines !== undefined ) {
  10689. for ( const name in parameters.defines ) {
  10690. array.push( name );
  10691. array.push( parameters.defines[ name ] );
  10692. }
  10693. }
  10694. if ( parameters.isRawShaderMaterial === false ) {
  10695. for ( let i = 0; i < parameterNames.length; i ++ ) {
  10696. array.push( parameters[ parameterNames[ i ] ] );
  10697. }
  10698. array.push( renderer.outputEncoding );
  10699. array.push( renderer.gammaFactor );
  10700. }
  10701. array.push( parameters.customProgramCacheKey );
  10702. return array.join();
  10703. }
  10704. function getUniforms( material ) {
  10705. const shaderID = shaderIDs[ material.type ];
  10706. let uniforms;
  10707. if ( shaderID ) {
  10708. const shader = ShaderLib[ shaderID ];
  10709. uniforms = UniformsUtils.clone( shader.uniforms );
  10710. } else {
  10711. uniforms = material.uniforms;
  10712. }
  10713. return uniforms;
  10714. }
  10715. function acquireProgram( parameters, cacheKey ) {
  10716. let program;
  10717. // Check if code has been already compiled
  10718. for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
  10719. const preexistingProgram = programs[ p ];
  10720. if ( preexistingProgram.cacheKey === cacheKey ) {
  10721. program = preexistingProgram;
  10722. ++ program.usedTimes;
  10723. break;
  10724. }
  10725. }
  10726. if ( program === undefined ) {
  10727. program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
  10728. programs.push( program );
  10729. }
  10730. return program;
  10731. }
  10732. function releaseProgram( program ) {
  10733. if ( -- program.usedTimes === 0 ) {
  10734. // Remove from unordered set
  10735. const i = programs.indexOf( program );
  10736. programs[ i ] = programs[ programs.length - 1 ];
  10737. programs.pop();
  10738. // Free WebGL resources
  10739. program.destroy();
  10740. }
  10741. }
  10742. return {
  10743. getParameters: getParameters,
  10744. getProgramCacheKey: getProgramCacheKey,
  10745. getUniforms: getUniforms,
  10746. acquireProgram: acquireProgram,
  10747. releaseProgram: releaseProgram,
  10748. // Exposed for resource monitoring & error feedback via renderer.info:
  10749. programs: programs
  10750. };
  10751. }
  10752. function WebGLProperties() {
  10753. let properties = new WeakMap();
  10754. function get( object ) {
  10755. let map = properties.get( object );
  10756. if ( map === undefined ) {
  10757. map = {};
  10758. properties.set( object, map );
  10759. }
  10760. return map;
  10761. }
  10762. function remove( object ) {
  10763. properties.delete( object );
  10764. }
  10765. function update( object, key, value ) {
  10766. properties.get( object )[ key ] = value;
  10767. }
  10768. function dispose() {
  10769. properties = new WeakMap();
  10770. }
  10771. return {
  10772. get: get,
  10773. remove: remove,
  10774. update: update,
  10775. dispose: dispose
  10776. };
  10777. }
  10778. function painterSortStable( a, b ) {
  10779. if ( a.groupOrder !== b.groupOrder ) {
  10780. return a.groupOrder - b.groupOrder;
  10781. } else if ( a.renderOrder !== b.renderOrder ) {
  10782. return a.renderOrder - b.renderOrder;
  10783. } else if ( a.program !== b.program ) {
  10784. return a.program.id - b.program.id;
  10785. } else if ( a.material.id !== b.material.id ) {
  10786. return a.material.id - b.material.id;
  10787. } else if ( a.z !== b.z ) {
  10788. return a.z - b.z;
  10789. } else {
  10790. return a.id - b.id;
  10791. }
  10792. }
  10793. function reversePainterSortStable( a, b ) {
  10794. if ( a.groupOrder !== b.groupOrder ) {
  10795. return a.groupOrder - b.groupOrder;
  10796. } else if ( a.renderOrder !== b.renderOrder ) {
  10797. return a.renderOrder - b.renderOrder;
  10798. } else if ( a.z !== b.z ) {
  10799. return b.z - a.z;
  10800. } else {
  10801. return a.id - b.id;
  10802. }
  10803. }
  10804. function WebGLRenderList( properties ) {
  10805. const renderItems = [];
  10806. let renderItemsIndex = 0;
  10807. const opaque = [];
  10808. const transparent = [];
  10809. const defaultProgram = { id: - 1 };
  10810. function init() {
  10811. renderItemsIndex = 0;
  10812. opaque.length = 0;
  10813. transparent.length = 0;
  10814. }
  10815. function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
  10816. let renderItem = renderItems[ renderItemsIndex ];
  10817. const materialProperties = properties.get( material );
  10818. if ( renderItem === undefined ) {
  10819. renderItem = {
  10820. id: object.id,
  10821. object: object,
  10822. geometry: geometry,
  10823. material: material,
  10824. program: materialProperties.program || defaultProgram,
  10825. groupOrder: groupOrder,
  10826. renderOrder: object.renderOrder,
  10827. z: z,
  10828. group: group
  10829. };
  10830. renderItems[ renderItemsIndex ] = renderItem;
  10831. } else {
  10832. renderItem.id = object.id;
  10833. renderItem.object = object;
  10834. renderItem.geometry = geometry;
  10835. renderItem.material = material;
  10836. renderItem.program = materialProperties.program || defaultProgram;
  10837. renderItem.groupOrder = groupOrder;
  10838. renderItem.renderOrder = object.renderOrder;
  10839. renderItem.z = z;
  10840. renderItem.group = group;
  10841. }
  10842. renderItemsIndex ++;
  10843. return renderItem;
  10844. }
  10845. function push( object, geometry, material, groupOrder, z, group ) {
  10846. const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
  10847. ( material.transparent === true ? transparent : opaque ).push( renderItem );
  10848. }
  10849. function unshift( object, geometry, material, groupOrder, z, group ) {
  10850. const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
  10851. ( material.transparent === true ? transparent : opaque ).unshift( renderItem );
  10852. }
  10853. function sort( customOpaqueSort, customTransparentSort ) {
  10854. if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
  10855. if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
  10856. }
  10857. function finish() {
  10858. // Clear references from inactive renderItems in the list
  10859. for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
  10860. const renderItem = renderItems[ i ];
  10861. if ( renderItem.id === null ) break;
  10862. renderItem.id = null;
  10863. renderItem.object = null;
  10864. renderItem.geometry = null;
  10865. renderItem.material = null;
  10866. renderItem.program = null;
  10867. renderItem.group = null;
  10868. }
  10869. }
  10870. return {
  10871. opaque: opaque,
  10872. transparent: transparent,
  10873. init: init,
  10874. push: push,
  10875. unshift: unshift,
  10876. finish: finish,
  10877. sort: sort
  10878. };
  10879. }
  10880. function WebGLRenderLists( properties ) {
  10881. let lists = new WeakMap();
  10882. function get( scene, camera ) {
  10883. const cameras = lists.get( scene );
  10884. let list;
  10885. if ( cameras === undefined ) {
  10886. list = new WebGLRenderList( properties );
  10887. lists.set( scene, new WeakMap() );
  10888. lists.get( scene ).set( camera, list );
  10889. } else {
  10890. list = cameras.get( camera );
  10891. if ( list === undefined ) {
  10892. list = new WebGLRenderList( properties );
  10893. cameras.set( camera, list );
  10894. }
  10895. }
  10896. return list;
  10897. }
  10898. function dispose() {
  10899. lists = new WeakMap();
  10900. }
  10901. return {
  10902. get: get,
  10903. dispose: dispose
  10904. };
  10905. }
  10906. function UniformsCache() {
  10907. const lights = {};
  10908. return {
  10909. get: function ( light ) {
  10910. if ( lights[ light.id ] !== undefined ) {
  10911. return lights[ light.id ];
  10912. }
  10913. let uniforms;
  10914. switch ( light.type ) {
  10915. case 'DirectionalLight':
  10916. uniforms = {
  10917. direction: new Vector3(),
  10918. color: new Color()
  10919. };
  10920. break;
  10921. case 'SpotLight':
  10922. uniforms = {
  10923. position: new Vector3(),
  10924. direction: new Vector3(),
  10925. color: new Color(),
  10926. distance: 0,
  10927. coneCos: 0,
  10928. penumbraCos: 0,
  10929. decay: 0
  10930. };
  10931. break;
  10932. case 'PointLight':
  10933. uniforms = {
  10934. position: new Vector3(),
  10935. color: new Color(),
  10936. distance: 0,
  10937. decay: 0
  10938. };
  10939. break;
  10940. case 'HemisphereLight':
  10941. uniforms = {
  10942. direction: new Vector3(),
  10943. skyColor: new Color(),
  10944. groundColor: new Color()
  10945. };
  10946. break;
  10947. case 'RectAreaLight':
  10948. uniforms = {
  10949. color: new Color(),
  10950. position: new Vector3(),
  10951. halfWidth: new Vector3(),
  10952. halfHeight: new Vector3()
  10953. };
  10954. break;
  10955. }
  10956. lights[ light.id ] = uniforms;
  10957. return uniforms;
  10958. }
  10959. };
  10960. }
  10961. function ShadowUniformsCache() {
  10962. const lights = {};
  10963. return {
  10964. get: function ( light ) {
  10965. if ( lights[ light.id ] !== undefined ) {
  10966. return lights[ light.id ];
  10967. }
  10968. let uniforms;
  10969. switch ( light.type ) {
  10970. case 'DirectionalLight':
  10971. uniforms = {
  10972. shadowBias: 0,
  10973. shadowNormalBias: 0,
  10974. shadowRadius: 1,
  10975. shadowMapSize: new Vector2()
  10976. };
  10977. break;
  10978. case 'SpotLight':
  10979. uniforms = {
  10980. shadowBias: 0,
  10981. shadowNormalBias: 0,
  10982. shadowRadius: 1,
  10983. shadowMapSize: new Vector2()
  10984. };
  10985. break;
  10986. case 'PointLight':
  10987. uniforms = {
  10988. shadowBias: 0,
  10989. shadowNormalBias: 0,
  10990. shadowRadius: 1,
  10991. shadowMapSize: new Vector2(),
  10992. shadowCameraNear: 1,
  10993. shadowCameraFar: 1000
  10994. };
  10995. break;
  10996. // TODO (abelnation): set RectAreaLight shadow uniforms
  10997. }
  10998. lights[ light.id ] = uniforms;
  10999. return uniforms;
  11000. }
  11001. };
  11002. }
  11003. let nextVersion = 0;
  11004. function shadowCastingLightsFirst( lightA, lightB ) {
  11005. return ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );
  11006. }
  11007. function WebGLLights( extensions, capabilities ) {
  11008. const cache = new UniformsCache();
  11009. const shadowCache = ShadowUniformsCache();
  11010. const state = {
  11011. version: 0,
  11012. hash: {
  11013. directionalLength: - 1,
  11014. pointLength: - 1,
  11015. spotLength: - 1,
  11016. rectAreaLength: - 1,
  11017. hemiLength: - 1,
  11018. numDirectionalShadows: - 1,
  11019. numPointShadows: - 1,
  11020. numSpotShadows: - 1
  11021. },
  11022. ambient: [ 0, 0, 0 ],
  11023. probe: [],
  11024. directional: [],
  11025. directionalShadow: [],
  11026. directionalShadowMap: [],
  11027. directionalShadowMatrix: [],
  11028. spot: [],
  11029. spotShadow: [],
  11030. spotShadowMap: [],
  11031. spotShadowMatrix: [],
  11032. rectArea: [],
  11033. rectAreaLTC1: null,
  11034. rectAreaLTC2: null,
  11035. point: [],
  11036. pointShadow: [],
  11037. pointShadowMap: [],
  11038. pointShadowMatrix: [],
  11039. hemi: []
  11040. };
  11041. for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
  11042. const vector3 = new Vector3();
  11043. const matrix4 = new Matrix4();
  11044. const matrix42 = new Matrix4();
  11045. function setup( lights ) {
  11046. let r = 0, g = 0, b = 0;
  11047. for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
  11048. let directionalLength = 0;
  11049. let pointLength = 0;
  11050. let spotLength = 0;
  11051. let rectAreaLength = 0;
  11052. let hemiLength = 0;
  11053. let numDirectionalShadows = 0;
  11054. let numPointShadows = 0;
  11055. let numSpotShadows = 0;
  11056. lights.sort( shadowCastingLightsFirst );
  11057. for ( let i = 0, l = lights.length; i < l; i ++ ) {
  11058. const light = lights[ i ];
  11059. const color = light.color;
  11060. const intensity = light.intensity;
  11061. const distance = light.distance;
  11062. const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
  11063. if ( light.isAmbientLight ) {
  11064. r += color.r * intensity;
  11065. g += color.g * intensity;
  11066. b += color.b * intensity;
  11067. } else if ( light.isLightProbe ) {
  11068. for ( let j = 0; j < 9; j ++ ) {
  11069. state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
  11070. }
  11071. } else if ( light.isDirectionalLight ) {
  11072. const uniforms = cache.get( light );
  11073. uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
  11074. if ( light.castShadow ) {
  11075. const shadow = light.shadow;
  11076. const shadowUniforms = shadowCache.get( light );
  11077. shadowUniforms.shadowBias = shadow.bias;
  11078. shadowUniforms.shadowNormalBias = shadow.normalBias;
  11079. shadowUniforms.shadowRadius = shadow.radius;
  11080. shadowUniforms.shadowMapSize = shadow.mapSize;
  11081. state.directionalShadow[ directionalLength ] = shadowUniforms;
  11082. state.directionalShadowMap[ directionalLength ] = shadowMap;
  11083. state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
  11084. numDirectionalShadows ++;
  11085. }
  11086. state.directional[ directionalLength ] = uniforms;
  11087. directionalLength ++;
  11088. } else if ( light.isSpotLight ) {
  11089. const uniforms = cache.get( light );
  11090. uniforms.position.setFromMatrixPosition( light.matrixWorld );
  11091. uniforms.color.copy( color ).multiplyScalar( intensity );
  11092. uniforms.distance = distance;
  11093. uniforms.coneCos = Math.cos( light.angle );
  11094. uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
  11095. uniforms.decay = light.decay;
  11096. if ( light.castShadow ) {
  11097. const shadow = light.shadow;
  11098. const shadowUniforms = shadowCache.get( light );
  11099. shadowUniforms.shadowBias = shadow.bias;
  11100. shadowUniforms.shadowNormalBias = shadow.normalBias;
  11101. shadowUniforms.shadowRadius = shadow.radius;
  11102. shadowUniforms.shadowMapSize = shadow.mapSize;
  11103. state.spotShadow[ spotLength ] = shadowUniforms;
  11104. state.spotShadowMap[ spotLength ] = shadowMap;
  11105. state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
  11106. numSpotShadows ++;
  11107. }
  11108. state.spot[ spotLength ] = uniforms;
  11109. spotLength ++;
  11110. } else if ( light.isRectAreaLight ) {
  11111. const uniforms = cache.get( light );
  11112. // (a) intensity is the total visible light emitted
  11113. //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
  11114. // (b) intensity is the brightness of the light
  11115. uniforms.color.copy( color ).multiplyScalar( intensity );
  11116. uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
  11117. uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
  11118. state.rectArea[ rectAreaLength ] = uniforms;
  11119. rectAreaLength ++;
  11120. } else if ( light.isPointLight ) {
  11121. const uniforms = cache.get( light );
  11122. uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
  11123. uniforms.distance = light.distance;
  11124. uniforms.decay = light.decay;
  11125. if ( light.castShadow ) {
  11126. const shadow = light.shadow;
  11127. const shadowUniforms = shadowCache.get( light );
  11128. shadowUniforms.shadowBias = shadow.bias;
  11129. shadowUniforms.shadowNormalBias = shadow.normalBias;
  11130. shadowUniforms.shadowRadius = shadow.radius;
  11131. shadowUniforms.shadowMapSize = shadow.mapSize;
  11132. shadowUniforms.shadowCameraNear = shadow.camera.near;
  11133. shadowUniforms.shadowCameraFar = shadow.camera.far;
  11134. state.pointShadow[ pointLength ] = shadowUniforms;
  11135. state.pointShadowMap[ pointLength ] = shadowMap;
  11136. state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
  11137. numPointShadows ++;
  11138. }
  11139. state.point[ pointLength ] = uniforms;
  11140. pointLength ++;
  11141. } else if ( light.isHemisphereLight ) {
  11142. const uniforms = cache.get( light );
  11143. uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
  11144. uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
  11145. state.hemi[ hemiLength ] = uniforms;
  11146. hemiLength ++;
  11147. }
  11148. }
  11149. if ( rectAreaLength > 0 ) {
  11150. if ( capabilities.isWebGL2 ) {
  11151. // WebGL 2
  11152. state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
  11153. state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
  11154. } else {
  11155. // WebGL 1
  11156. if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
  11157. state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
  11158. state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
  11159. } else if ( extensions.has( 'OES_texture_half_float_linear' ) === true ) {
  11160. state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
  11161. state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
  11162. } else {
  11163. console.error( 'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' );
  11164. }
  11165. }
  11166. }
  11167. state.ambient[ 0 ] = r;
  11168. state.ambient[ 1 ] = g;
  11169. state.ambient[ 2 ] = b;
  11170. const hash = state.hash;
  11171. if ( hash.directionalLength !== directionalLength ||
  11172. hash.pointLength !== pointLength ||
  11173. hash.spotLength !== spotLength ||
  11174. hash.rectAreaLength !== rectAreaLength ||
  11175. hash.hemiLength !== hemiLength ||
  11176. hash.numDirectionalShadows !== numDirectionalShadows ||
  11177. hash.numPointShadows !== numPointShadows ||
  11178. hash.numSpotShadows !== numSpotShadows ) {
  11179. state.directional.length = directionalLength;
  11180. state.spot.length = spotLength;
  11181. state.rectArea.length = rectAreaLength;
  11182. state.point.length = pointLength;
  11183. state.hemi.length = hemiLength;
  11184. state.directionalShadow.length = numDirectionalShadows;
  11185. state.directionalShadowMap.length = numDirectionalShadows;
  11186. state.pointShadow.length = numPointShadows;
  11187. state.pointShadowMap.length = numPointShadows;
  11188. state.spotShadow.length = numSpotShadows;
  11189. state.spotShadowMap.length = numSpotShadows;
  11190. state.directionalShadowMatrix.length = numDirectionalShadows;
  11191. state.pointShadowMatrix.length = numPointShadows;
  11192. state.spotShadowMatrix.length = numSpotShadows;
  11193. hash.directionalLength = directionalLength;
  11194. hash.pointLength = pointLength;
  11195. hash.spotLength = spotLength;
  11196. hash.rectAreaLength = rectAreaLength;
  11197. hash.hemiLength = hemiLength;
  11198. hash.numDirectionalShadows = numDirectionalShadows;
  11199. hash.numPointShadows = numPointShadows;
  11200. hash.numSpotShadows = numSpotShadows;
  11201. state.version = nextVersion ++;
  11202. }
  11203. }
  11204. function setupView( lights, camera ) {
  11205. let directionalLength = 0;
  11206. let pointLength = 0;
  11207. let spotLength = 0;
  11208. let rectAreaLength = 0;
  11209. let hemiLength = 0;
  11210. const viewMatrix = camera.matrixWorldInverse;
  11211. for ( let i = 0, l = lights.length; i < l; i ++ ) {
  11212. const light = lights[ i ];
  11213. if ( light.isDirectionalLight ) {
  11214. const uniforms = state.directional[ directionalLength ];
  11215. uniforms.direction.setFromMatrixPosition( light.matrixWorld );
  11216. vector3.setFromMatrixPosition( light.target.matrixWorld );
  11217. uniforms.direction.sub( vector3 );
  11218. uniforms.direction.transformDirection( viewMatrix );
  11219. directionalLength ++;
  11220. } else if ( light.isSpotLight ) {
  11221. const uniforms = state.spot[ spotLength ];
  11222. uniforms.position.setFromMatrixPosition( light.matrixWorld );
  11223. uniforms.position.applyMatrix4( viewMatrix );
  11224. uniforms.direction.setFromMatrixPosition( light.matrixWorld );
  11225. vector3.setFromMatrixPosition( light.target.matrixWorld );
  11226. uniforms.direction.sub( vector3 );
  11227. uniforms.direction.transformDirection( viewMatrix );
  11228. spotLength ++;
  11229. } else if ( light.isRectAreaLight ) {
  11230. const uniforms = state.rectArea[ rectAreaLength ];
  11231. uniforms.position.setFromMatrixPosition( light.matrixWorld );
  11232. uniforms.position.applyMatrix4( viewMatrix );
  11233. // extract local rotation of light to derive width/height half vectors
  11234. matrix42.identity();
  11235. matrix4.copy( light.matrixWorld );
  11236. matrix4.premultiply( viewMatrix );
  11237. matrix42.extractRotation( matrix4 );
  11238. uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
  11239. uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
  11240. uniforms.halfWidth.applyMatrix4( matrix42 );
  11241. uniforms.halfHeight.applyMatrix4( matrix42 );
  11242. rectAreaLength ++;
  11243. } else if ( light.isPointLight ) {
  11244. const uniforms = state.point[ pointLength ];
  11245. uniforms.position.setFromMatrixPosition( light.matrixWorld );
  11246. uniforms.position.applyMatrix4( viewMatrix );
  11247. pointLength ++;
  11248. } else if ( light.isHemisphereLight ) {
  11249. const uniforms = state.hemi[ hemiLength ];
  11250. uniforms.direction.setFromMatrixPosition( light.matrixWorld );
  11251. uniforms.direction.transformDirection( viewMatrix );
  11252. uniforms.direction.normalize();
  11253. hemiLength ++;
  11254. }
  11255. }
  11256. }
  11257. return {
  11258. setup: setup,
  11259. setupView: setupView,
  11260. state: state
  11261. };
  11262. }
  11263. function WebGLRenderState( extensions, capabilities ) {
  11264. const lights = new WebGLLights( extensions, capabilities );
  11265. const lightsArray = [];
  11266. const shadowsArray = [];
  11267. function init() {
  11268. lightsArray.length = 0;
  11269. shadowsArray.length = 0;
  11270. }
  11271. function pushLight( light ) {
  11272. lightsArray.push( light );
  11273. }
  11274. function pushShadow( shadowLight ) {
  11275. shadowsArray.push( shadowLight );
  11276. }
  11277. function setupLights() {
  11278. lights.setup( lightsArray );
  11279. }
  11280. function setupLightsView( camera ) {
  11281. lights.setupView( lightsArray, camera );
  11282. }
  11283. const state = {
  11284. lightsArray: lightsArray,
  11285. shadowsArray: shadowsArray,
  11286. lights: lights
  11287. };
  11288. return {
  11289. init: init,
  11290. state: state,
  11291. setupLights: setupLights,
  11292. setupLightsView: setupLightsView,
  11293. pushLight: pushLight,
  11294. pushShadow: pushShadow
  11295. };
  11296. }
  11297. function WebGLRenderStates( extensions, capabilities ) {
  11298. let renderStates = new WeakMap();
  11299. function get( scene, renderCallDepth = 0 ) {
  11300. let renderState;
  11301. if ( renderStates.has( scene ) === false ) {
  11302. renderState = new WebGLRenderState( extensions, capabilities );
  11303. renderStates.set( scene, [] );
  11304. renderStates.get( scene ).push( renderState );
  11305. } else {
  11306. if ( renderCallDepth >= renderStates.get( scene ).length ) {
  11307. renderState = new WebGLRenderState( extensions, capabilities );
  11308. renderStates.get( scene ).push( renderState );
  11309. } else {
  11310. renderState = renderStates.get( scene )[ renderCallDepth ];
  11311. }
  11312. }
  11313. return renderState;
  11314. }
  11315. function dispose() {
  11316. renderStates = new WeakMap();
  11317. }
  11318. return {
  11319. get: get,
  11320. dispose: dispose
  11321. };
  11322. }
  11323. /**
  11324. * parameters = {
  11325. *
  11326. * opacity: <float>,
  11327. *
  11328. * map: new THREE.Texture( <Image> ),
  11329. *
  11330. * alphaMap: new THREE.Texture( <Image> ),
  11331. *
  11332. * displacementMap: new THREE.Texture( <Image> ),
  11333. * displacementScale: <float>,
  11334. * displacementBias: <float>,
  11335. *
  11336. * wireframe: <boolean>,
  11337. * wireframeLinewidth: <float>
  11338. * }
  11339. */
  11340. function MeshDepthMaterial( parameters ) {
  11341. Material.call( this );
  11342. this.type = 'MeshDepthMaterial';
  11343. this.depthPacking = BasicDepthPacking;
  11344. this.skinning = false;
  11345. this.morphTargets = false;
  11346. this.map = null;
  11347. this.alphaMap = null;
  11348. this.displacementMap = null;
  11349. this.displacementScale = 1;
  11350. this.displacementBias = 0;
  11351. this.wireframe = false;
  11352. this.wireframeLinewidth = 1;
  11353. this.fog = false;
  11354. this.setValues( parameters );
  11355. }
  11356. MeshDepthMaterial.prototype = Object.create( Material.prototype );
  11357. MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
  11358. MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
  11359. MeshDepthMaterial.prototype.copy = function ( source ) {
  11360. Material.prototype.copy.call( this, source );
  11361. this.depthPacking = source.depthPacking;
  11362. this.skinning = source.skinning;
  11363. this.morphTargets = source.morphTargets;
  11364. this.map = source.map;
  11365. this.alphaMap = source.alphaMap;
  11366. this.displacementMap = source.displacementMap;
  11367. this.displacementScale = source.displacementScale;
  11368. this.displacementBias = source.displacementBias;
  11369. this.wireframe = source.wireframe;
  11370. this.wireframeLinewidth = source.wireframeLinewidth;
  11371. return this;
  11372. };
  11373. /**
  11374. * parameters = {
  11375. *
  11376. * referencePosition: <float>,
  11377. * nearDistance: <float>,
  11378. * farDistance: <float>,
  11379. *
  11380. * skinning: <bool>,
  11381. * morphTargets: <bool>,
  11382. *
  11383. * map: new THREE.Texture( <Image> ),
  11384. *
  11385. * alphaMap: new THREE.Texture( <Image> ),
  11386. *
  11387. * displacementMap: new THREE.Texture( <Image> ),
  11388. * displacementScale: <float>,
  11389. * displacementBias: <float>
  11390. *
  11391. * }
  11392. */
  11393. function MeshDistanceMaterial( parameters ) {
  11394. Material.call( this );
  11395. this.type = 'MeshDistanceMaterial';
  11396. this.referencePosition = new Vector3();
  11397. this.nearDistance = 1;
  11398. this.farDistance = 1000;
  11399. this.skinning = false;
  11400. this.morphTargets = false;
  11401. this.map = null;
  11402. this.alphaMap = null;
  11403. this.displacementMap = null;
  11404. this.displacementScale = 1;
  11405. this.displacementBias = 0;
  11406. this.fog = false;
  11407. this.setValues( parameters );
  11408. }
  11409. MeshDistanceMaterial.prototype = Object.create( Material.prototype );
  11410. MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
  11411. MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
  11412. MeshDistanceMaterial.prototype.copy = function ( source ) {
  11413. Material.prototype.copy.call( this, source );
  11414. this.referencePosition.copy( source.referencePosition );
  11415. this.nearDistance = source.nearDistance;
  11416. this.farDistance = source.farDistance;
  11417. this.skinning = source.skinning;
  11418. this.morphTargets = source.morphTargets;
  11419. this.map = source.map;
  11420. this.alphaMap = source.alphaMap;
  11421. this.displacementMap = source.displacementMap;
  11422. this.displacementScale = source.displacementScale;
  11423. this.displacementBias = source.displacementBias;
  11424. return this;
  11425. };
  11426. var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 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, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
  11427. var vsm_vert = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
  11428. function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
  11429. let _frustum = new Frustum();
  11430. const _shadowMapSize = new Vector2(),
  11431. _viewportSize = new Vector2(),
  11432. _viewport = new Vector4(),
  11433. _depthMaterials = [],
  11434. _distanceMaterials = [],
  11435. _materialCache = {};
  11436. const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
  11437. const shadowMaterialVertical = new ShaderMaterial( {
  11438. defines: {
  11439. SAMPLE_RATE: 2.0 / 8.0,
  11440. HALF_SAMPLE_RATE: 1.0 / 8.0
  11441. },
  11442. uniforms: {
  11443. shadow_pass: { value: null },
  11444. resolution: { value: new Vector2() },
  11445. radius: { value: 4.0 }
  11446. },
  11447. vertexShader: vsm_vert,
  11448. fragmentShader: vsm_frag
  11449. } );
  11450. const shadowMaterialHorizontal = shadowMaterialVertical.clone();
  11451. shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
  11452. const fullScreenTri = new BufferGeometry();
  11453. fullScreenTri.setAttribute(
  11454. 'position',
  11455. new BufferAttribute(
  11456. new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
  11457. 3
  11458. )
  11459. );
  11460. const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
  11461. const scope = this;
  11462. this.enabled = false;
  11463. this.autoUpdate = true;
  11464. this.needsUpdate = false;
  11465. this.type = PCFShadowMap;
  11466. this.render = function ( lights, scene, camera ) {
  11467. if ( scope.enabled === false ) return;
  11468. if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
  11469. if ( lights.length === 0 ) return;
  11470. const currentRenderTarget = _renderer.getRenderTarget();
  11471. const activeCubeFace = _renderer.getActiveCubeFace();
  11472. const activeMipmapLevel = _renderer.getActiveMipmapLevel();
  11473. const _state = _renderer.state;
  11474. // Set GL state for depth map.
  11475. _state.setBlending( NoBlending );
  11476. _state.buffers.color.setClear( 1, 1, 1, 1 );
  11477. _state.buffers.depth.setTest( true );
  11478. _state.setScissorTest( false );
  11479. // render depth map
  11480. for ( let i = 0, il = lights.length; i < il; i ++ ) {
  11481. const light = lights[ i ];
  11482. const shadow = light.shadow;
  11483. if ( shadow === undefined ) {
  11484. console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
  11485. continue;
  11486. }
  11487. if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
  11488. _shadowMapSize.copy( shadow.mapSize );
  11489. const shadowFrameExtents = shadow.getFrameExtents();
  11490. _shadowMapSize.multiply( shadowFrameExtents );
  11491. _viewportSize.copy( shadow.mapSize );
  11492. if ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {
  11493. if ( _shadowMapSize.x > maxTextureSize ) {
  11494. _viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );
  11495. _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
  11496. shadow.mapSize.x = _viewportSize.x;
  11497. }
  11498. if ( _shadowMapSize.y > maxTextureSize ) {
  11499. _viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );
  11500. _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
  11501. shadow.mapSize.y = _viewportSize.y;
  11502. }
  11503. }
  11504. if ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
  11505. const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
  11506. shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
  11507. shadow.map.texture.name = light.name + '.shadowMap';
  11508. shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
  11509. shadow.camera.updateProjectionMatrix();
  11510. }
  11511. if ( shadow.map === null ) {
  11512. const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
  11513. shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
  11514. shadow.map.texture.name = light.name + '.shadowMap';
  11515. shadow.camera.updateProjectionMatrix();
  11516. }
  11517. _renderer.setRenderTarget( shadow.map );
  11518. _renderer.clear();
  11519. const viewportCount = shadow.getViewportCount();
  11520. for ( let vp = 0; vp < viewportCount; vp ++ ) {
  11521. const viewport = shadow.getViewport( vp );
  11522. _viewport.set(
  11523. _viewportSize.x * viewport.x,
  11524. _viewportSize.y * viewport.y,
  11525. _viewportSize.x * viewport.z,
  11526. _viewportSize.y * viewport.w
  11527. );
  11528. _state.viewport( _viewport );
  11529. shadow.updateMatrices( light, vp );
  11530. _frustum = shadow.getFrustum();
  11531. renderObject( scene, camera, shadow.camera, light, this.type );
  11532. }
  11533. // do blur pass for VSM
  11534. if ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
  11535. VSMPass( shadow, camera );
  11536. }
  11537. shadow.needsUpdate = false;
  11538. }
  11539. scope.needsUpdate = false;
  11540. _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
  11541. };
  11542. function VSMPass( shadow, camera ) {
  11543. const geometry = _objects.update( fullScreenMesh );
  11544. // vertical pass
  11545. shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
  11546. shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
  11547. shadowMaterialVertical.uniforms.radius.value = shadow.radius;
  11548. _renderer.setRenderTarget( shadow.mapPass );
  11549. _renderer.clear();
  11550. _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
  11551. // horizontal pass
  11552. shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
  11553. shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
  11554. shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
  11555. _renderer.setRenderTarget( shadow.map );
  11556. _renderer.clear();
  11557. _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
  11558. }
  11559. function getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {
  11560. const index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
  11561. let material = _depthMaterials[ index ];
  11562. if ( material === undefined ) {
  11563. material = new MeshDepthMaterial( {
  11564. depthPacking: RGBADepthPacking,
  11565. morphTargets: useMorphing,
  11566. skinning: useSkinning
  11567. } );
  11568. _depthMaterials[ index ] = material;
  11569. }
  11570. return material;
  11571. }
  11572. function getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {
  11573. const index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
  11574. let material = _distanceMaterials[ index ];
  11575. if ( material === undefined ) {
  11576. material = new MeshDistanceMaterial( {
  11577. morphTargets: useMorphing,
  11578. skinning: useSkinning
  11579. } );
  11580. _distanceMaterials[ index ] = material;
  11581. }
  11582. return material;
  11583. }
  11584. function getDepthMaterial( object, geometry, material, light, shadowCameraNear, shadowCameraFar, type ) {
  11585. let result = null;
  11586. let getMaterialVariant = getDepthMaterialVariant;
  11587. let customMaterial = object.customDepthMaterial;
  11588. if ( light.isPointLight === true ) {
  11589. getMaterialVariant = getDistanceMaterialVariant;
  11590. customMaterial = object.customDistanceMaterial;
  11591. }
  11592. if ( customMaterial === undefined ) {
  11593. let useMorphing = false;
  11594. if ( material.morphTargets === true ) {
  11595. useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
  11596. }
  11597. let useSkinning = false;
  11598. if ( object.isSkinnedMesh === true ) {
  11599. if ( material.skinning === true ) {
  11600. useSkinning = true;
  11601. } else {
  11602. console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
  11603. }
  11604. }
  11605. const useInstancing = object.isInstancedMesh === true;
  11606. result = getMaterialVariant( useMorphing, useSkinning, useInstancing );
  11607. } else {
  11608. result = customMaterial;
  11609. }
  11610. if ( _renderer.localClippingEnabled &&
  11611. material.clipShadows === true &&
  11612. material.clippingPlanes.length !== 0 ) {
  11613. // in this case we need a unique material instance reflecting the
  11614. // appropriate state
  11615. const keyA = result.uuid, keyB = material.uuid;
  11616. let materialsForVariant = _materialCache[ keyA ];
  11617. if ( materialsForVariant === undefined ) {
  11618. materialsForVariant = {};
  11619. _materialCache[ keyA ] = materialsForVariant;
  11620. }
  11621. let cachedMaterial = materialsForVariant[ keyB ];
  11622. if ( cachedMaterial === undefined ) {
  11623. cachedMaterial = result.clone();
  11624. materialsForVariant[ keyB ] = cachedMaterial;
  11625. }
  11626. result = cachedMaterial;
  11627. }
  11628. result.visible = material.visible;
  11629. result.wireframe = material.wireframe;
  11630. if ( type === VSMShadowMap ) {
  11631. result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
  11632. } else {
  11633. result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
  11634. }
  11635. result.clipShadows = material.clipShadows;
  11636. result.clippingPlanes = material.clippingPlanes;
  11637. result.clipIntersection = material.clipIntersection;
  11638. result.wireframeLinewidth = material.wireframeLinewidth;
  11639. result.linewidth = material.linewidth;
  11640. if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
  11641. result.referencePosition.setFromMatrixPosition( light.matrixWorld );
  11642. result.nearDistance = shadowCameraNear;
  11643. result.farDistance = shadowCameraFar;
  11644. }
  11645. return result;
  11646. }
  11647. function renderObject( object, camera, shadowCamera, light, type ) {
  11648. if ( object.visible === false ) return;
  11649. const visible = object.layers.test( camera.layers );
  11650. if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
  11651. if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
  11652. object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
  11653. const geometry = _objects.update( object );
  11654. const material = object.material;
  11655. if ( Array.isArray( material ) ) {
  11656. const groups = geometry.groups;
  11657. for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
  11658. const group = groups[ k ];
  11659. const groupMaterial = material[ group.materialIndex ];
  11660. if ( groupMaterial && groupMaterial.visible ) {
  11661. const depthMaterial = getDepthMaterial( object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
  11662. _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
  11663. }
  11664. }
  11665. } else if ( material.visible ) {
  11666. const depthMaterial = getDepthMaterial( object, geometry, material, light, shadowCamera.near, shadowCamera.far, type );
  11667. _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
  11668. }
  11669. }
  11670. }
  11671. const children = object.children;
  11672. for ( let i = 0, l = children.length; i < l; i ++ ) {
  11673. renderObject( children[ i ], camera, shadowCamera, light, type );
  11674. }
  11675. }
  11676. }
  11677. function WebGLState( gl, extensions, capabilities ) {
  11678. const isWebGL2 = capabilities.isWebGL2;
  11679. function ColorBuffer() {
  11680. let locked = false;
  11681. const color = new Vector4();
  11682. let currentColorMask = null;
  11683. const currentColorClear = new Vector4( 0, 0, 0, 0 );
  11684. return {
  11685. setMask: function ( colorMask ) {
  11686. if ( currentColorMask !== colorMask && ! locked ) {
  11687. gl.colorMask( colorMask, colorMask, colorMask, colorMask );
  11688. currentColorMask = colorMask;
  11689. }
  11690. },
  11691. setLocked: function ( lock ) {
  11692. locked = lock;
  11693. },
  11694. setClear: function ( r, g, b, a, premultipliedAlpha ) {
  11695. if ( premultipliedAlpha === true ) {
  11696. r *= a; g *= a; b *= a;
  11697. }
  11698. color.set( r, g, b, a );
  11699. if ( currentColorClear.equals( color ) === false ) {
  11700. gl.clearColor( r, g, b, a );
  11701. currentColorClear.copy( color );
  11702. }
  11703. },
  11704. reset: function () {
  11705. locked = false;
  11706. currentColorMask = null;
  11707. currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
  11708. }
  11709. };
  11710. }
  11711. function DepthBuffer() {
  11712. let locked = false;
  11713. let currentDepthMask = null;
  11714. let currentDepthFunc = null;
  11715. let currentDepthClear = null;
  11716. return {
  11717. setTest: function ( depthTest ) {
  11718. if ( depthTest ) {
  11719. enable( 2929 );
  11720. } else {
  11721. disable( 2929 );
  11722. }
  11723. },
  11724. setMask: function ( depthMask ) {
  11725. if ( currentDepthMask !== depthMask && ! locked ) {
  11726. gl.depthMask( depthMask );
  11727. currentDepthMask = depthMask;
  11728. }
  11729. },
  11730. setFunc: function ( depthFunc ) {
  11731. if ( currentDepthFunc !== depthFunc ) {
  11732. if ( depthFunc ) {
  11733. switch ( depthFunc ) {
  11734. case NeverDepth:
  11735. gl.depthFunc( 512 );
  11736. break;
  11737. case AlwaysDepth:
  11738. gl.depthFunc( 519 );
  11739. break;
  11740. case LessDepth:
  11741. gl.depthFunc( 513 );
  11742. break;
  11743. case LessEqualDepth:
  11744. gl.depthFunc( 515 );
  11745. break;
  11746. case EqualDepth:
  11747. gl.depthFunc( 514 );
  11748. break;
  11749. case GreaterEqualDepth:
  11750. gl.depthFunc( 518 );
  11751. break;
  11752. case GreaterDepth:
  11753. gl.depthFunc( 516 );
  11754. break;
  11755. case NotEqualDepth:
  11756. gl.depthFunc( 517 );
  11757. break;
  11758. default:
  11759. gl.depthFunc( 515 );
  11760. }
  11761. } else {
  11762. gl.depthFunc( 515 );
  11763. }
  11764. currentDepthFunc = depthFunc;
  11765. }
  11766. },
  11767. setLocked: function ( lock ) {
  11768. locked = lock;
  11769. },
  11770. setClear: function ( depth ) {
  11771. if ( currentDepthClear !== depth ) {
  11772. gl.clearDepth( depth );
  11773. currentDepthClear = depth;
  11774. }
  11775. },
  11776. reset: function () {
  11777. locked = false;
  11778. currentDepthMask = null;
  11779. currentDepthFunc = null;
  11780. currentDepthClear = null;
  11781. }
  11782. };
  11783. }
  11784. function StencilBuffer() {
  11785. let locked = false;
  11786. let currentStencilMask = null;
  11787. let currentStencilFunc = null;
  11788. let currentStencilRef = null;
  11789. let currentStencilFuncMask = null;
  11790. let currentStencilFail = null;
  11791. let currentStencilZFail = null;
  11792. let currentStencilZPass = null;
  11793. let currentStencilClear = null;
  11794. return {
  11795. setTest: function ( stencilTest ) {
  11796. if ( ! locked ) {
  11797. if ( stencilTest ) {
  11798. enable( 2960 );
  11799. } else {
  11800. disable( 2960 );
  11801. }
  11802. }
  11803. },
  11804. setMask: function ( stencilMask ) {
  11805. if ( currentStencilMask !== stencilMask && ! locked ) {
  11806. gl.stencilMask( stencilMask );
  11807. currentStencilMask = stencilMask;
  11808. }
  11809. },
  11810. setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
  11811. if ( currentStencilFunc !== stencilFunc ||
  11812. currentStencilRef !== stencilRef ||
  11813. currentStencilFuncMask !== stencilMask ) {
  11814. gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
  11815. currentStencilFunc = stencilFunc;
  11816. currentStencilRef = stencilRef;
  11817. currentStencilFuncMask = stencilMask;
  11818. }
  11819. },
  11820. setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
  11821. if ( currentStencilFail !== stencilFail ||
  11822. currentStencilZFail !== stencilZFail ||
  11823. currentStencilZPass !== stencilZPass ) {
  11824. gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
  11825. currentStencilFail = stencilFail;
  11826. currentStencilZFail = stencilZFail;
  11827. currentStencilZPass = stencilZPass;
  11828. }
  11829. },
  11830. setLocked: function ( lock ) {
  11831. locked = lock;
  11832. },
  11833. setClear: function ( stencil ) {
  11834. if ( currentStencilClear !== stencil ) {
  11835. gl.clearStencil( stencil );
  11836. currentStencilClear = stencil;
  11837. }
  11838. },
  11839. reset: function () {
  11840. locked = false;
  11841. currentStencilMask = null;
  11842. currentStencilFunc = null;
  11843. currentStencilRef = null;
  11844. currentStencilFuncMask = null;
  11845. currentStencilFail = null;
  11846. currentStencilZFail = null;
  11847. currentStencilZPass = null;
  11848. currentStencilClear = null;
  11849. }
  11850. };
  11851. }
  11852. //
  11853. const colorBuffer = new ColorBuffer();
  11854. const depthBuffer = new DepthBuffer();
  11855. const stencilBuffer = new StencilBuffer();
  11856. let enabledCapabilities = {};
  11857. let currentProgram = null;
  11858. let currentBlendingEnabled = null;
  11859. let currentBlending = null;
  11860. let currentBlendEquation = null;
  11861. let currentBlendSrc = null;
  11862. let currentBlendDst = null;
  11863. let currentBlendEquationAlpha = null;
  11864. let currentBlendSrcAlpha = null;
  11865. let currentBlendDstAlpha = null;
  11866. let currentPremultipledAlpha = false;
  11867. let currentFlipSided = null;
  11868. let currentCullFace = null;
  11869. let currentLineWidth = null;
  11870. let currentPolygonOffsetFactor = null;
  11871. let currentPolygonOffsetUnits = null;
  11872. const maxTextures = gl.getParameter( 35661 );
  11873. let lineWidthAvailable = false;
  11874. let version = 0;
  11875. const glVersion = gl.getParameter( 7938 );
  11876. if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
  11877. version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] );
  11878. lineWidthAvailable = ( version >= 1.0 );
  11879. } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
  11880. version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] );
  11881. lineWidthAvailable = ( version >= 2.0 );
  11882. }
  11883. let currentTextureSlot = null;
  11884. let currentBoundTextures = {};
  11885. const currentScissor = new Vector4();
  11886. const currentViewport = new Vector4();
  11887. function createTexture( type, target, count ) {
  11888. const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
  11889. const texture = gl.createTexture();
  11890. gl.bindTexture( type, texture );
  11891. gl.texParameteri( type, 10241, 9728 );
  11892. gl.texParameteri( type, 10240, 9728 );
  11893. for ( let i = 0; i < count; i ++ ) {
  11894. gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );
  11895. }
  11896. return texture;
  11897. }
  11898. const emptyTextures = {};
  11899. emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );
  11900. emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );
  11901. // init
  11902. colorBuffer.setClear( 0, 0, 0, 1 );
  11903. depthBuffer.setClear( 1 );
  11904. stencilBuffer.setClear( 0 );
  11905. enable( 2929 );
  11906. depthBuffer.setFunc( LessEqualDepth );
  11907. setFlipSided( false );
  11908. setCullFace( CullFaceBack );
  11909. enable( 2884 );
  11910. setBlending( NoBlending );
  11911. //
  11912. function enable( id ) {
  11913. if ( enabledCapabilities[ id ] !== true ) {
  11914. gl.enable( id );
  11915. enabledCapabilities[ id ] = true;
  11916. }
  11917. }
  11918. function disable( id ) {
  11919. if ( enabledCapabilities[ id ] !== false ) {
  11920. gl.disable( id );
  11921. enabledCapabilities[ id ] = false;
  11922. }
  11923. }
  11924. function useProgram( program ) {
  11925. if ( currentProgram !== program ) {
  11926. gl.useProgram( program );
  11927. currentProgram = program;
  11928. return true;
  11929. }
  11930. return false;
  11931. }
  11932. const equationToGL = {
  11933. [ AddEquation ]: 32774,
  11934. [ SubtractEquation ]: 32778,
  11935. [ ReverseSubtractEquation ]: 32779
  11936. };
  11937. if ( isWebGL2 ) {
  11938. equationToGL[ MinEquation ] = 32775;
  11939. equationToGL[ MaxEquation ] = 32776;
  11940. } else {
  11941. const extension = extensions.get( 'EXT_blend_minmax' );
  11942. if ( extension !== null ) {
  11943. equationToGL[ MinEquation ] = extension.MIN_EXT;
  11944. equationToGL[ MaxEquation ] = extension.MAX_EXT;
  11945. }
  11946. }
  11947. const factorToGL = {
  11948. [ ZeroFactor ]: 0,
  11949. [ OneFactor ]: 1,
  11950. [ SrcColorFactor ]: 768,
  11951. [ SrcAlphaFactor ]: 770,
  11952. [ SrcAlphaSaturateFactor ]: 776,
  11953. [ DstColorFactor ]: 774,
  11954. [ DstAlphaFactor ]: 772,
  11955. [ OneMinusSrcColorFactor ]: 769,
  11956. [ OneMinusSrcAlphaFactor ]: 771,
  11957. [ OneMinusDstColorFactor ]: 775,
  11958. [ OneMinusDstAlphaFactor ]: 773
  11959. };
  11960. function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
  11961. if ( blending === NoBlending ) {
  11962. if ( currentBlendingEnabled ) {
  11963. disable( 3042 );
  11964. currentBlendingEnabled = false;
  11965. }
  11966. return;
  11967. }
  11968. if ( ! currentBlendingEnabled ) {
  11969. enable( 3042 );
  11970. currentBlendingEnabled = true;
  11971. }
  11972. if ( blending !== CustomBlending ) {
  11973. if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
  11974. if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
  11975. gl.blendEquation( 32774 );
  11976. currentBlendEquation = AddEquation;
  11977. currentBlendEquationAlpha = AddEquation;
  11978. }
  11979. if ( premultipliedAlpha ) {
  11980. switch ( blending ) {
  11981. case NormalBlending:
  11982. gl.blendFuncSeparate( 1, 771, 1, 771 );
  11983. break;
  11984. case AdditiveBlending:
  11985. gl.blendFunc( 1, 1 );
  11986. break;
  11987. case SubtractiveBlending:
  11988. gl.blendFuncSeparate( 0, 0, 769, 771 );
  11989. break;
  11990. case MultiplyBlending:
  11991. gl.blendFuncSeparate( 0, 768, 0, 770 );
  11992. break;
  11993. default:
  11994. console.error( 'THREE.WebGLState: Invalid blending: ', blending );
  11995. break;
  11996. }
  11997. } else {
  11998. switch ( blending ) {
  11999. case NormalBlending:
  12000. gl.blendFuncSeparate( 770, 771, 1, 771 );
  12001. break;
  12002. case AdditiveBlending:
  12003. gl.blendFunc( 770, 1 );
  12004. break;
  12005. case SubtractiveBlending:
  12006. gl.blendFunc( 0, 769 );
  12007. break;
  12008. case MultiplyBlending:
  12009. gl.blendFunc( 0, 768 );
  12010. break;
  12011. default:
  12012. console.error( 'THREE.WebGLState: Invalid blending: ', blending );
  12013. break;
  12014. }
  12015. }
  12016. currentBlendSrc = null;
  12017. currentBlendDst = null;
  12018. currentBlendSrcAlpha = null;
  12019. currentBlendDstAlpha = null;
  12020. currentBlending = blending;
  12021. currentPremultipledAlpha = premultipliedAlpha;
  12022. }
  12023. return;
  12024. }
  12025. // custom blending
  12026. blendEquationAlpha = blendEquationAlpha || blendEquation;
  12027. blendSrcAlpha = blendSrcAlpha || blendSrc;
  12028. blendDstAlpha = blendDstAlpha || blendDst;
  12029. if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
  12030. gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
  12031. currentBlendEquation = blendEquation;
  12032. currentBlendEquationAlpha = blendEquationAlpha;
  12033. }
  12034. if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
  12035. gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
  12036. currentBlendSrc = blendSrc;
  12037. currentBlendDst = blendDst;
  12038. currentBlendSrcAlpha = blendSrcAlpha;
  12039. currentBlendDstAlpha = blendDstAlpha;
  12040. }
  12041. currentBlending = blending;
  12042. currentPremultipledAlpha = null;
  12043. }
  12044. function setMaterial( material, frontFaceCW ) {
  12045. material.side === DoubleSide
  12046. ? disable( 2884 )
  12047. : enable( 2884 );
  12048. let flipSided = ( material.side === BackSide );
  12049. if ( frontFaceCW ) flipSided = ! flipSided;
  12050. setFlipSided( flipSided );
  12051. ( material.blending === NormalBlending && material.transparent === false )
  12052. ? setBlending( NoBlending )
  12053. : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
  12054. depthBuffer.setFunc( material.depthFunc );
  12055. depthBuffer.setTest( material.depthTest );
  12056. depthBuffer.setMask( material.depthWrite );
  12057. colorBuffer.setMask( material.colorWrite );
  12058. const stencilWrite = material.stencilWrite;
  12059. stencilBuffer.setTest( stencilWrite );
  12060. if ( stencilWrite ) {
  12061. stencilBuffer.setMask( material.stencilWriteMask );
  12062. stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
  12063. stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
  12064. }
  12065. setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
  12066. }
  12067. //
  12068. function setFlipSided( flipSided ) {
  12069. if ( currentFlipSided !== flipSided ) {
  12070. if ( flipSided ) {
  12071. gl.frontFace( 2304 );
  12072. } else {
  12073. gl.frontFace( 2305 );
  12074. }
  12075. currentFlipSided = flipSided;
  12076. }
  12077. }
  12078. function setCullFace( cullFace ) {
  12079. if ( cullFace !== CullFaceNone ) {
  12080. enable( 2884 );
  12081. if ( cullFace !== currentCullFace ) {
  12082. if ( cullFace === CullFaceBack ) {
  12083. gl.cullFace( 1029 );
  12084. } else if ( cullFace === CullFaceFront ) {
  12085. gl.cullFace( 1028 );
  12086. } else {
  12087. gl.cullFace( 1032 );
  12088. }
  12089. }
  12090. } else {
  12091. disable( 2884 );
  12092. }
  12093. currentCullFace = cullFace;
  12094. }
  12095. function setLineWidth( width ) {
  12096. if ( width !== currentLineWidth ) {
  12097. if ( lineWidthAvailable ) gl.lineWidth( width );
  12098. currentLineWidth = width;
  12099. }
  12100. }
  12101. function setPolygonOffset( polygonOffset, factor, units ) {
  12102. if ( polygonOffset ) {
  12103. enable( 32823 );
  12104. if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
  12105. gl.polygonOffset( factor, units );
  12106. currentPolygonOffsetFactor = factor;
  12107. currentPolygonOffsetUnits = units;
  12108. }
  12109. } else {
  12110. disable( 32823 );
  12111. }
  12112. }
  12113. function setScissorTest( scissorTest ) {
  12114. if ( scissorTest ) {
  12115. enable( 3089 );
  12116. } else {
  12117. disable( 3089 );
  12118. }
  12119. }
  12120. // texture
  12121. function activeTexture( webglSlot ) {
  12122. if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1;
  12123. if ( currentTextureSlot !== webglSlot ) {
  12124. gl.activeTexture( webglSlot );
  12125. currentTextureSlot = webglSlot;
  12126. }
  12127. }
  12128. function bindTexture( webglType, webglTexture ) {
  12129. if ( currentTextureSlot === null ) {
  12130. activeTexture();
  12131. }
  12132. let boundTexture = currentBoundTextures[ currentTextureSlot ];
  12133. if ( boundTexture === undefined ) {
  12134. boundTexture = { type: undefined, texture: undefined };
  12135. currentBoundTextures[ currentTextureSlot ] = boundTexture;
  12136. }
  12137. if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
  12138. gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
  12139. boundTexture.type = webglType;
  12140. boundTexture.texture = webglTexture;
  12141. }
  12142. }
  12143. function unbindTexture() {
  12144. const boundTexture = currentBoundTextures[ currentTextureSlot ];
  12145. if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
  12146. gl.bindTexture( boundTexture.type, null );
  12147. boundTexture.type = undefined;
  12148. boundTexture.texture = undefined;
  12149. }
  12150. }
  12151. function compressedTexImage2D() {
  12152. try {
  12153. gl.compressedTexImage2D.apply( gl, arguments );
  12154. } catch ( error ) {
  12155. console.error( 'THREE.WebGLState:', error );
  12156. }
  12157. }
  12158. function texImage2D() {
  12159. try {
  12160. gl.texImage2D.apply( gl, arguments );
  12161. } catch ( error ) {
  12162. console.error( 'THREE.WebGLState:', error );
  12163. }
  12164. }
  12165. function texImage3D() {
  12166. try {
  12167. gl.texImage3D.apply( gl, arguments );
  12168. } catch ( error ) {
  12169. console.error( 'THREE.WebGLState:', error );
  12170. }
  12171. }
  12172. //
  12173. function scissor( scissor ) {
  12174. if ( currentScissor.equals( scissor ) === false ) {
  12175. gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
  12176. currentScissor.copy( scissor );
  12177. }
  12178. }
  12179. function viewport( viewport ) {
  12180. if ( currentViewport.equals( viewport ) === false ) {
  12181. gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
  12182. currentViewport.copy( viewport );
  12183. }
  12184. }
  12185. //
  12186. function reset() {
  12187. enabledCapabilities = {};
  12188. currentTextureSlot = null;
  12189. currentBoundTextures = {};
  12190. currentProgram = null;
  12191. currentBlendingEnabled = null;
  12192. currentBlending = null;
  12193. currentBlendEquation = null;
  12194. currentBlendSrc = null;
  12195. currentBlendDst = null;
  12196. currentBlendEquationAlpha = null;
  12197. currentBlendSrcAlpha = null;
  12198. currentBlendDstAlpha = null;
  12199. currentPremultipledAlpha = false;
  12200. currentFlipSided = null;
  12201. currentCullFace = null;
  12202. currentLineWidth = null;
  12203. currentPolygonOffsetFactor = null;
  12204. currentPolygonOffsetUnits = null;
  12205. colorBuffer.reset();
  12206. depthBuffer.reset();
  12207. stencilBuffer.reset();
  12208. }
  12209. return {
  12210. buffers: {
  12211. color: colorBuffer,
  12212. depth: depthBuffer,
  12213. stencil: stencilBuffer
  12214. },
  12215. enable: enable,
  12216. disable: disable,
  12217. useProgram: useProgram,
  12218. setBlending: setBlending,
  12219. setMaterial: setMaterial,
  12220. setFlipSided: setFlipSided,
  12221. setCullFace: setCullFace,
  12222. setLineWidth: setLineWidth,
  12223. setPolygonOffset: setPolygonOffset,
  12224. setScissorTest: setScissorTest,
  12225. activeTexture: activeTexture,
  12226. bindTexture: bindTexture,
  12227. unbindTexture: unbindTexture,
  12228. compressedTexImage2D: compressedTexImage2D,
  12229. texImage2D: texImage2D,
  12230. texImage3D: texImage3D,
  12231. scissor: scissor,
  12232. viewport: viewport,
  12233. reset: reset
  12234. };
  12235. }
  12236. function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
  12237. const isWebGL2 = capabilities.isWebGL2;
  12238. const maxTextures = capabilities.maxTextures;
  12239. const maxCubemapSize = capabilities.maxCubemapSize;
  12240. const maxTextureSize = capabilities.maxTextureSize;
  12241. const maxSamples = capabilities.maxSamples;
  12242. const _videoTextures = new WeakMap();
  12243. let _canvas;
  12244. // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
  12245. // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
  12246. // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
  12247. let useOffscreenCanvas = false;
  12248. try {
  12249. useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
  12250. && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null;
  12251. } catch ( err ) {
  12252. // Ignore any errors
  12253. }
  12254. function createCanvas( width, height ) {
  12255. // Use OffscreenCanvas when available. Specially needed in web workers
  12256. return useOffscreenCanvas ?
  12257. new OffscreenCanvas( width, height ) :
  12258. document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
  12259. }
  12260. function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
  12261. let scale = 1;
  12262. // handle case if texture exceeds max size
  12263. if ( image.width > maxSize || image.height > maxSize ) {
  12264. scale = maxSize / Math.max( image.width, image.height );
  12265. }
  12266. // only perform resize if necessary
  12267. if ( scale < 1 || needsPowerOfTwo === true ) {
  12268. // only perform resize for certain image types
  12269. if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
  12270. ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
  12271. ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
  12272. const floor = needsPowerOfTwo ? MathUtils$1.floorPowerOfTwo : Math.floor;
  12273. const width = floor( scale * image.width );
  12274. const height = floor( scale * image.height );
  12275. if ( _canvas === undefined ) _canvas = createCanvas( width, height );
  12276. // cube textures can't reuse the same canvas
  12277. const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
  12278. canvas.width = width;
  12279. canvas.height = height;
  12280. const context = canvas.getContext( '2d' );
  12281. context.drawImage( image, 0, 0, width, height );
  12282. console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );
  12283. return canvas;
  12284. } else {
  12285. if ( 'data' in image ) {
  12286. console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
  12287. }
  12288. return image;
  12289. }
  12290. }
  12291. return image;
  12292. }
  12293. function isPowerOfTwo( image ) {
  12294. return MathUtils$1.isPowerOfTwo( image.width ) && MathUtils$1.isPowerOfTwo( image.height );
  12295. }
  12296. function textureNeedsPowerOfTwo( texture ) {
  12297. if ( isWebGL2 ) return false;
  12298. return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
  12299. ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
  12300. }
  12301. function textureNeedsGenerateMipmaps( texture, supportsMips ) {
  12302. return texture.generateMipmaps && supportsMips &&
  12303. texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
  12304. }
  12305. function generateMipmap( target, texture, width, height ) {
  12306. _gl.generateMipmap( target );
  12307. const textureProperties = properties.get( texture );
  12308. // Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
  12309. textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
  12310. }
  12311. function getInternalFormat( internalFormatName, glFormat, glType ) {
  12312. if ( isWebGL2 === false ) return glFormat;
  12313. if ( internalFormatName !== null ) {
  12314. if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
  12315. console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
  12316. }
  12317. let internalFormat = glFormat;
  12318. if ( glFormat === 6403 ) {
  12319. if ( glType === 5126 ) internalFormat = 33326;
  12320. if ( glType === 5131 ) internalFormat = 33325;
  12321. if ( glType === 5121 ) internalFormat = 33321;
  12322. }
  12323. if ( glFormat === 6407 ) {
  12324. if ( glType === 5126 ) internalFormat = 34837;
  12325. if ( glType === 5131 ) internalFormat = 34843;
  12326. if ( glType === 5121 ) internalFormat = 32849;
  12327. }
  12328. if ( glFormat === 6408 ) {
  12329. if ( glType === 5126 ) internalFormat = 34836;
  12330. if ( glType === 5131 ) internalFormat = 34842;
  12331. if ( glType === 5121 ) internalFormat = 32856;
  12332. }
  12333. if ( internalFormat === 33325 || internalFormat === 33326 ||
  12334. internalFormat === 34842 || internalFormat === 34836 ) {
  12335. extensions.get( 'EXT_color_buffer_float' );
  12336. }
  12337. return internalFormat;
  12338. }
  12339. // Fallback filters for non-power-of-2 textures
  12340. function filterFallback( f ) {
  12341. if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {
  12342. return 9728;
  12343. }
  12344. return 9729;
  12345. }
  12346. //
  12347. function onTextureDispose( event ) {
  12348. const texture = event.target;
  12349. texture.removeEventListener( 'dispose', onTextureDispose );
  12350. deallocateTexture( texture );
  12351. if ( texture.isVideoTexture ) {
  12352. _videoTextures.delete( texture );
  12353. }
  12354. info.memory.textures --;
  12355. }
  12356. function onRenderTargetDispose( event ) {
  12357. const renderTarget = event.target;
  12358. renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
  12359. deallocateRenderTarget( renderTarget );
  12360. info.memory.textures --;
  12361. }
  12362. //
  12363. function deallocateTexture( texture ) {
  12364. const textureProperties = properties.get( texture );
  12365. if ( textureProperties.__webglInit === undefined ) return;
  12366. _gl.deleteTexture( textureProperties.__webglTexture );
  12367. properties.remove( texture );
  12368. }
  12369. function deallocateRenderTarget( renderTarget ) {
  12370. const renderTargetProperties = properties.get( renderTarget );
  12371. const textureProperties = properties.get( renderTarget.texture );
  12372. if ( ! renderTarget ) return;
  12373. if ( textureProperties.__webglTexture !== undefined ) {
  12374. _gl.deleteTexture( textureProperties.__webglTexture );
  12375. }
  12376. if ( renderTarget.depthTexture ) {
  12377. renderTarget.depthTexture.dispose();
  12378. }
  12379. if ( renderTarget.isWebGLCubeRenderTarget ) {
  12380. for ( let i = 0; i < 6; i ++ ) {
  12381. _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
  12382. if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
  12383. }
  12384. } else {
  12385. _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
  12386. if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
  12387. if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
  12388. if ( renderTargetProperties.__webglColorRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer );
  12389. if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
  12390. }
  12391. properties.remove( renderTarget.texture );
  12392. properties.remove( renderTarget );
  12393. }
  12394. //
  12395. let textureUnits = 0;
  12396. function resetTextureUnits() {
  12397. textureUnits = 0;
  12398. }
  12399. function allocateTextureUnit() {
  12400. const textureUnit = textureUnits;
  12401. if ( textureUnit >= maxTextures ) {
  12402. console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );
  12403. }
  12404. textureUnits += 1;
  12405. return textureUnit;
  12406. }
  12407. //
  12408. function setTexture2D( texture, slot ) {
  12409. const textureProperties = properties.get( texture );
  12410. if ( texture.isVideoTexture ) updateVideoTexture( texture );
  12411. if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
  12412. const image = texture.image;
  12413. if ( image === undefined ) {
  12414. console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );
  12415. } else if ( image.complete === false ) {
  12416. console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
  12417. } else {
  12418. uploadTexture( textureProperties, texture, slot );
  12419. return;
  12420. }
  12421. }
  12422. state.activeTexture( 33984 + slot );
  12423. state.bindTexture( 3553, textureProperties.__webglTexture );
  12424. }
  12425. function setTexture2DArray( texture, slot ) {
  12426. const textureProperties = properties.get( texture );
  12427. if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
  12428. uploadTexture( textureProperties, texture, slot );
  12429. return;
  12430. }
  12431. state.activeTexture( 33984 + slot );
  12432. state.bindTexture( 35866, textureProperties.__webglTexture );
  12433. }
  12434. function setTexture3D( texture, slot ) {
  12435. const textureProperties = properties.get( texture );
  12436. if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
  12437. uploadTexture( textureProperties, texture, slot );
  12438. return;
  12439. }
  12440. state.activeTexture( 33984 + slot );
  12441. state.bindTexture( 32879, textureProperties.__webglTexture );
  12442. }
  12443. function setTextureCube( texture, slot ) {
  12444. const textureProperties = properties.get( texture );
  12445. if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
  12446. uploadCubeTexture( textureProperties, texture, slot );
  12447. return;
  12448. }
  12449. state.activeTexture( 33984 + slot );
  12450. state.bindTexture( 34067, textureProperties.__webglTexture );
  12451. }
  12452. const wrappingToGL = {
  12453. [ RepeatWrapping ]: 10497,
  12454. [ ClampToEdgeWrapping ]: 33071,
  12455. [ MirroredRepeatWrapping ]: 33648
  12456. };
  12457. const filterToGL = {
  12458. [ NearestFilter ]: 9728,
  12459. [ NearestMipmapNearestFilter ]: 9984,
  12460. [ NearestMipmapLinearFilter ]: 9986,
  12461. [ LinearFilter ]: 9729,
  12462. [ LinearMipmapNearestFilter ]: 9985,
  12463. [ LinearMipmapLinearFilter ]: 9987
  12464. };
  12465. function setTextureParameters( textureType, texture, supportsMips ) {
  12466. if ( supportsMips ) {
  12467. _gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );
  12468. _gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );
  12469. if ( textureType === 32879 || textureType === 35866 ) {
  12470. _gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );
  12471. }
  12472. _gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );
  12473. _gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );
  12474. } else {
  12475. _gl.texParameteri( textureType, 10242, 33071 );
  12476. _gl.texParameteri( textureType, 10243, 33071 );
  12477. if ( textureType === 32879 || textureType === 35866 ) {
  12478. _gl.texParameteri( textureType, 32882, 33071 );
  12479. }
  12480. if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
  12481. console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
  12482. }
  12483. _gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );
  12484. _gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );
  12485. if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
  12486. console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
  12487. }
  12488. }
  12489. const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
  12490. if ( extension ) {
  12491. if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
  12492. if ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
  12493. if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
  12494. _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
  12495. properties.get( texture ).__currentAnisotropy = texture.anisotropy;
  12496. }
  12497. }
  12498. }
  12499. function initTexture( textureProperties, texture ) {
  12500. if ( textureProperties.__webglInit === undefined ) {
  12501. textureProperties.__webglInit = true;
  12502. texture.addEventListener( 'dispose', onTextureDispose );
  12503. textureProperties.__webglTexture = _gl.createTexture();
  12504. info.memory.textures ++;
  12505. }
  12506. }
  12507. function uploadTexture( textureProperties, texture, slot ) {
  12508. let textureType = 3553;
  12509. if ( texture.isDataTexture2DArray ) textureType = 35866;
  12510. if ( texture.isDataTexture3D ) textureType = 32879;
  12511. initTexture( textureProperties, texture );
  12512. state.activeTexture( 33984 + slot );
  12513. state.bindTexture( textureType, textureProperties.__webglTexture );
  12514. _gl.pixelStorei( 37440, texture.flipY );
  12515. _gl.pixelStorei( 37441, texture.premultiplyAlpha );
  12516. _gl.pixelStorei( 3317, texture.unpackAlignment );
  12517. const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;
  12518. const image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
  12519. const supportsMips = isPowerOfTwo( image ) || isWebGL2,
  12520. glFormat = utils.convert( texture.format );
  12521. let glType = utils.convert( texture.type ),
  12522. glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
  12523. setTextureParameters( textureType, texture, supportsMips );
  12524. let mipmap;
  12525. const mipmaps = texture.mipmaps;
  12526. if ( texture.isDepthTexture ) {
  12527. // populate depth texture with dummy data
  12528. glInternalFormat = 6402;
  12529. if ( isWebGL2 ) {
  12530. if ( texture.type === FloatType ) {
  12531. glInternalFormat = 36012;
  12532. } else if ( texture.type === UnsignedIntType ) {
  12533. glInternalFormat = 33190;
  12534. } else if ( texture.type === UnsignedInt248Type$1 ) {
  12535. glInternalFormat = 35056;
  12536. } else {
  12537. glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D
  12538. }
  12539. } else {
  12540. if ( texture.type === FloatType ) {
  12541. console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
  12542. }
  12543. }
  12544. // validation checks for WebGL 1
  12545. if ( texture.format === DepthFormat && glInternalFormat === 6402 ) {
  12546. // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
  12547. // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
  12548. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  12549. if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
  12550. console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
  12551. texture.type = UnsignedShortType;
  12552. glType = utils.convert( texture.type );
  12553. }
  12554. }
  12555. if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) {
  12556. // Depth stencil textures need the DEPTH_STENCIL internal format
  12557. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  12558. glInternalFormat = 34041;
  12559. // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
  12560. // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
  12561. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  12562. if ( texture.type !== UnsignedInt248Type$1 ) {
  12563. console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
  12564. texture.type = UnsignedInt248Type$1;
  12565. glType = utils.convert( texture.type );
  12566. }
  12567. }
  12568. //
  12569. state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
  12570. } else if ( texture.isDataTexture ) {
  12571. // use manually created mipmaps if available
  12572. // if there are no manual mipmaps
  12573. // set 0 level mipmap and then use GL to generate other mipmap levels
  12574. if ( mipmaps.length > 0 && supportsMips ) {
  12575. for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
  12576. mipmap = mipmaps[ i ];
  12577. state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
  12578. }
  12579. texture.generateMipmaps = false;
  12580. textureProperties.__maxMipLevel = mipmaps.length - 1;
  12581. } else {
  12582. state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
  12583. textureProperties.__maxMipLevel = 0;
  12584. }
  12585. } else if ( texture.isCompressedTexture ) {
  12586. for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
  12587. mipmap = mipmaps[ i ];
  12588. if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
  12589. if ( glFormat !== null ) {
  12590. state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
  12591. } else {
  12592. console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
  12593. }
  12594. } else {
  12595. state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
  12596. }
  12597. }
  12598. textureProperties.__maxMipLevel = mipmaps.length - 1;
  12599. } else if ( texture.isDataTexture2DArray ) {
  12600. state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
  12601. textureProperties.__maxMipLevel = 0;
  12602. } else if ( texture.isDataTexture3D ) {
  12603. state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
  12604. textureProperties.__maxMipLevel = 0;
  12605. } else {
  12606. // regular Texture (image, video, canvas)
  12607. // use manually created mipmaps if available
  12608. // if there are no manual mipmaps
  12609. // set 0 level mipmap and then use GL to generate other mipmap levels
  12610. if ( mipmaps.length > 0 && supportsMips ) {
  12611. for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
  12612. mipmap = mipmaps[ i ];
  12613. state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );
  12614. }
  12615. texture.generateMipmaps = false;
  12616. textureProperties.__maxMipLevel = mipmaps.length - 1;
  12617. } else {
  12618. state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );
  12619. textureProperties.__maxMipLevel = 0;
  12620. }
  12621. }
  12622. if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
  12623. generateMipmap( textureType, texture, image.width, image.height );
  12624. }
  12625. textureProperties.__version = texture.version;
  12626. if ( texture.onUpdate ) texture.onUpdate( texture );
  12627. }
  12628. function uploadCubeTexture( textureProperties, texture, slot ) {
  12629. if ( texture.image.length !== 6 ) return;
  12630. initTexture( textureProperties, texture );
  12631. state.activeTexture( 33984 + slot );
  12632. state.bindTexture( 34067, textureProperties.__webglTexture );
  12633. _gl.pixelStorei( 37440, texture.flipY );
  12634. const isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );
  12635. const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
  12636. const cubeImage = [];
  12637. for ( let i = 0; i < 6; i ++ ) {
  12638. if ( ! isCompressed && ! isDataTexture ) {
  12639. cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
  12640. } else {
  12641. cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
  12642. }
  12643. }
  12644. const image = cubeImage[ 0 ],
  12645. supportsMips = isPowerOfTwo( image ) || isWebGL2,
  12646. glFormat = utils.convert( texture.format ),
  12647. glType = utils.convert( texture.type ),
  12648. glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
  12649. setTextureParameters( 34067, texture, supportsMips );
  12650. let mipmaps;
  12651. if ( isCompressed ) {
  12652. for ( let i = 0; i < 6; i ++ ) {
  12653. mipmaps = cubeImage[ i ].mipmaps;
  12654. for ( let j = 0; j < mipmaps.length; j ++ ) {
  12655. const mipmap = mipmaps[ j ];
  12656. if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
  12657. if ( glFormat !== null ) {
  12658. state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
  12659. } else {
  12660. console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
  12661. }
  12662. } else {
  12663. state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
  12664. }
  12665. }
  12666. }
  12667. textureProperties.__maxMipLevel = mipmaps.length - 1;
  12668. } else {
  12669. mipmaps = texture.mipmaps;
  12670. for ( let i = 0; i < 6; i ++ ) {
  12671. if ( isDataTexture ) {
  12672. state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
  12673. for ( let j = 0; j < mipmaps.length; j ++ ) {
  12674. const mipmap = mipmaps[ j ];
  12675. const mipmapImage = mipmap.image[ i ].image;
  12676. state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
  12677. }
  12678. } else {
  12679. state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
  12680. for ( let j = 0; j < mipmaps.length; j ++ ) {
  12681. const mipmap = mipmaps[ j ];
  12682. state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
  12683. }
  12684. }
  12685. }
  12686. textureProperties.__maxMipLevel = mipmaps.length;
  12687. }
  12688. if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
  12689. // We assume images for cube map have the same size.
  12690. generateMipmap( 34067, texture, image.width, image.height );
  12691. }
  12692. textureProperties.__version = texture.version;
  12693. if ( texture.onUpdate ) texture.onUpdate( texture );
  12694. }
  12695. // Render targets
  12696. // Setup storage for target texture and bind it to correct framebuffer
  12697. function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
  12698. const glFormat = utils.convert( renderTarget.texture.format );
  12699. const glType = utils.convert( renderTarget.texture.type );
  12700. const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
  12701. state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
  12702. _gl.bindFramebuffer( 36160, framebuffer );
  12703. _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
  12704. _gl.bindFramebuffer( 36160, null );
  12705. }
  12706. // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
  12707. function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
  12708. _gl.bindRenderbuffer( 36161, renderbuffer );
  12709. if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
  12710. let glInternalFormat = 33189;
  12711. if ( isMultisample ) {
  12712. const depthTexture = renderTarget.depthTexture;
  12713. if ( depthTexture && depthTexture.isDepthTexture ) {
  12714. if ( depthTexture.type === FloatType ) {
  12715. glInternalFormat = 36012;
  12716. } else if ( depthTexture.type === UnsignedIntType ) {
  12717. glInternalFormat = 33190;
  12718. }
  12719. }
  12720. const samples = getRenderTargetSamples( renderTarget );
  12721. _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
  12722. } else {
  12723. _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
  12724. }
  12725. _gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );
  12726. } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
  12727. if ( isMultisample ) {
  12728. const samples = getRenderTargetSamples( renderTarget );
  12729. _gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );
  12730. } else {
  12731. _gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );
  12732. }
  12733. _gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );
  12734. } else {
  12735. const glFormat = utils.convert( renderTarget.texture.format );
  12736. const glType = utils.convert( renderTarget.texture.type );
  12737. const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
  12738. if ( isMultisample ) {
  12739. const samples = getRenderTargetSamples( renderTarget );
  12740. _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
  12741. } else {
  12742. _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
  12743. }
  12744. }
  12745. _gl.bindRenderbuffer( 36161, null );
  12746. }
  12747. // Setup resources for a Depth Texture for a FBO (needs an extension)
  12748. function setupDepthTexture( framebuffer, renderTarget ) {
  12749. const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
  12750. if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
  12751. _gl.bindFramebuffer( 36160, framebuffer );
  12752. if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
  12753. throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
  12754. }
  12755. // upload an empty depth texture with framebuffer size
  12756. if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
  12757. renderTarget.depthTexture.image.width !== renderTarget.width ||
  12758. renderTarget.depthTexture.image.height !== renderTarget.height ) {
  12759. renderTarget.depthTexture.image.width = renderTarget.width;
  12760. renderTarget.depthTexture.image.height = renderTarget.height;
  12761. renderTarget.depthTexture.needsUpdate = true;
  12762. }
  12763. setTexture2D( renderTarget.depthTexture, 0 );
  12764. const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
  12765. if ( renderTarget.depthTexture.format === DepthFormat ) {
  12766. _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );
  12767. } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
  12768. _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );
  12769. } else {
  12770. throw new Error( 'Unknown depthTexture format' );
  12771. }
  12772. }
  12773. // Setup GL resources for a non-texture depth buffer
  12774. function setupDepthRenderbuffer( renderTarget ) {
  12775. const renderTargetProperties = properties.get( renderTarget );
  12776. const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
  12777. if ( renderTarget.depthTexture ) {
  12778. if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
  12779. setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
  12780. } else {
  12781. if ( isCube ) {
  12782. renderTargetProperties.__webglDepthbuffer = [];
  12783. for ( let i = 0; i < 6; i ++ ) {
  12784. _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );
  12785. renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
  12786. setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
  12787. }
  12788. } else {
  12789. _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
  12790. renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
  12791. setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
  12792. }
  12793. }
  12794. _gl.bindFramebuffer( 36160, null );
  12795. }
  12796. // Set up GL resources for the render target
  12797. function setupRenderTarget( renderTarget ) {
  12798. const renderTargetProperties = properties.get( renderTarget );
  12799. const textureProperties = properties.get( renderTarget.texture );
  12800. renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
  12801. textureProperties.__webglTexture = _gl.createTexture();
  12802. info.memory.textures ++;
  12803. const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
  12804. const isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
  12805. const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
  12806. // Handles WebGL2 RGBFormat fallback - #18858
  12807. if ( isWebGL2 && renderTarget.texture.format === RGBFormat && ( renderTarget.texture.type === FloatType || renderTarget.texture.type === HalfFloatType ) ) {
  12808. renderTarget.texture.format = RGBAFormat;
  12809. console.warn( 'THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.' );
  12810. }
  12811. // Setup framebuffer
  12812. if ( isCube ) {
  12813. renderTargetProperties.__webglFramebuffer = [];
  12814. for ( let i = 0; i < 6; i ++ ) {
  12815. renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
  12816. }
  12817. } else {
  12818. renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
  12819. if ( isMultisample ) {
  12820. if ( isWebGL2 ) {
  12821. renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
  12822. renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
  12823. _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );
  12824. const glFormat = utils.convert( renderTarget.texture.format );
  12825. const glType = utils.convert( renderTarget.texture.type );
  12826. const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
  12827. const samples = getRenderTargetSamples( renderTarget );
  12828. _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
  12829. _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
  12830. _gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );
  12831. _gl.bindRenderbuffer( 36161, null );
  12832. if ( renderTarget.depthBuffer ) {
  12833. renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
  12834. setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
  12835. }
  12836. _gl.bindFramebuffer( 36160, null );
  12837. } else {
  12838. console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
  12839. }
  12840. }
  12841. }
  12842. // Setup color buffer
  12843. if ( isCube ) {
  12844. state.bindTexture( 34067, textureProperties.__webglTexture );
  12845. setTextureParameters( 34067, renderTarget.texture, supportsMips );
  12846. for ( let i = 0; i < 6; i ++ ) {
  12847. setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, 36064, 34069 + i );
  12848. }
  12849. if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
  12850. generateMipmap( 34067, renderTarget.texture, renderTarget.width, renderTarget.height );
  12851. }
  12852. state.bindTexture( 34067, null );
  12853. } else {
  12854. state.bindTexture( 3553, textureProperties.__webglTexture );
  12855. setTextureParameters( 3553, renderTarget.texture, supportsMips );
  12856. setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 36064, 3553 );
  12857. if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
  12858. generateMipmap( 3553, renderTarget.texture, renderTarget.width, renderTarget.height );
  12859. }
  12860. state.bindTexture( 3553, null );
  12861. }
  12862. // Setup depth and stencil buffers
  12863. if ( renderTarget.depthBuffer ) {
  12864. setupDepthRenderbuffer( renderTarget );
  12865. }
  12866. }
  12867. function updateRenderTargetMipmap( renderTarget ) {
  12868. const texture = renderTarget.texture;
  12869. const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
  12870. if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
  12871. const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553;
  12872. const webglTexture = properties.get( texture ).__webglTexture;
  12873. state.bindTexture( target, webglTexture );
  12874. generateMipmap( target, texture, renderTarget.width, renderTarget.height );
  12875. state.bindTexture( target, null );
  12876. }
  12877. }
  12878. function updateMultisampleRenderTarget( renderTarget ) {
  12879. if ( renderTarget.isWebGLMultisampleRenderTarget ) {
  12880. if ( isWebGL2 ) {
  12881. const renderTargetProperties = properties.get( renderTarget );
  12882. _gl.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );
  12883. _gl.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );
  12884. const width = renderTarget.width;
  12885. const height = renderTarget.height;
  12886. let mask = 16384;
  12887. if ( renderTarget.depthBuffer ) mask |= 256;
  12888. if ( renderTarget.stencilBuffer ) mask |= 1024;
  12889. _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );
  12890. _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); // see #18905
  12891. } else {
  12892. console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
  12893. }
  12894. }
  12895. }
  12896. function getRenderTargetSamples( renderTarget ) {
  12897. return ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?
  12898. Math.min( maxSamples, renderTarget.samples ) : 0;
  12899. }
  12900. function updateVideoTexture( texture ) {
  12901. const frame = info.render.frame;
  12902. // Check the last frame we updated the VideoTexture
  12903. if ( _videoTextures.get( texture ) !== frame ) {
  12904. _videoTextures.set( texture, frame );
  12905. texture.update();
  12906. }
  12907. }
  12908. // backwards compatibility
  12909. let warnedTexture2D = false;
  12910. let warnedTextureCube = false;
  12911. function safeSetTexture2D( texture, slot ) {
  12912. if ( texture && texture.isWebGLRenderTarget ) {
  12913. if ( warnedTexture2D === false ) {
  12914. console.warn( 'THREE.WebGLTextures.safeSetTexture2D: don\'t use render targets as textures. Use their .texture property instead.' );
  12915. warnedTexture2D = true;
  12916. }
  12917. texture = texture.texture;
  12918. }
  12919. setTexture2D( texture, slot );
  12920. }
  12921. function safeSetTextureCube( texture, slot ) {
  12922. if ( texture && texture.isWebGLCubeRenderTarget ) {
  12923. if ( warnedTextureCube === false ) {
  12924. console.warn( 'THREE.WebGLTextures.safeSetTextureCube: don\'t use cube render targets as textures. Use their .texture property instead.' );
  12925. warnedTextureCube = true;
  12926. }
  12927. texture = texture.texture;
  12928. }
  12929. setTextureCube( texture, slot );
  12930. }
  12931. //
  12932. this.allocateTextureUnit = allocateTextureUnit;
  12933. this.resetTextureUnits = resetTextureUnits;
  12934. this.setTexture2D = setTexture2D;
  12935. this.setTexture2DArray = setTexture2DArray;
  12936. this.setTexture3D = setTexture3D;
  12937. this.setTextureCube = setTextureCube;
  12938. this.setupRenderTarget = setupRenderTarget;
  12939. this.updateRenderTargetMipmap = updateRenderTargetMipmap;
  12940. this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
  12941. this.safeSetTexture2D = safeSetTexture2D;
  12942. this.safeSetTextureCube = safeSetTextureCube;
  12943. }
  12944. function WebGLUtils( gl, extensions, capabilities ) {
  12945. const isWebGL2 = capabilities.isWebGL2;
  12946. function convert( p ) {
  12947. let extension;
  12948. if ( p === UnsignedByteType ) return 5121;
  12949. if ( p === UnsignedShort4444Type ) return 32819;
  12950. if ( p === UnsignedShort5551Type ) return 32820;
  12951. if ( p === UnsignedShort565Type ) return 33635;
  12952. if ( p === ByteType ) return 5120;
  12953. if ( p === ShortType ) return 5122;
  12954. if ( p === UnsignedShortType ) return 5123;
  12955. if ( p === IntType ) return 5124;
  12956. if ( p === UnsignedIntType ) return 5125;
  12957. if ( p === FloatType ) return 5126;
  12958. if ( p === HalfFloatType ) {
  12959. if ( isWebGL2 ) return 5131;
  12960. extension = extensions.get( 'OES_texture_half_float' );
  12961. if ( extension !== null ) {
  12962. return extension.HALF_FLOAT_OES;
  12963. } else {
  12964. return null;
  12965. }
  12966. }
  12967. if ( p === AlphaFormat ) return 6406;
  12968. if ( p === RGBFormat ) return 6407;
  12969. if ( p === RGBAFormat ) return 6408;
  12970. if ( p === LuminanceFormat ) return 6409;
  12971. if ( p === LuminanceAlphaFormat ) return 6410;
  12972. if ( p === DepthFormat ) return 6402;
  12973. if ( p === DepthStencilFormat ) return 34041;
  12974. if ( p === RedFormat ) return 6403;
  12975. // WebGL2 formats.
  12976. if ( p === RedIntegerFormat ) return 36244;
  12977. if ( p === RGFormat ) return 33319;
  12978. if ( p === RGIntegerFormat ) return 33320;
  12979. if ( p === RGBIntegerFormat ) return 36248;
  12980. if ( p === RGBAIntegerFormat ) return 36249;
  12981. if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format$1 ||
  12982. p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format$1 ) {
  12983. extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
  12984. if ( extension !== null ) {
  12985. if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
  12986. if ( p === RGBA_S3TC_DXT1_Format$1 ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
  12987. if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
  12988. if ( p === RGBA_S3TC_DXT5_Format$1 ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
  12989. } else {
  12990. return null;
  12991. }
  12992. }
  12993. if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
  12994. p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
  12995. extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
  12996. if ( extension !== null ) {
  12997. if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  12998. if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  12999. if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  13000. if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  13001. } else {
  13002. return null;
  13003. }
  13004. }
  13005. if ( p === RGB_ETC1_Format ) {
  13006. extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
  13007. if ( extension !== null ) {
  13008. return extension.COMPRESSED_RGB_ETC1_WEBGL;
  13009. } else {
  13010. return null;
  13011. }
  13012. }
  13013. if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
  13014. extension = extensions.get( 'WEBGL_compressed_texture_etc' );
  13015. if ( extension !== null ) {
  13016. if ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2;
  13017. if ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC;
  13018. }
  13019. }
  13020. if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
  13021. p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
  13022. p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
  13023. p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
  13024. p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ||
  13025. p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format ||
  13026. p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format ||
  13027. p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format ||
  13028. p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format ||
  13029. p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) {
  13030. extension = extensions.get( 'WEBGL_compressed_texture_astc' );
  13031. if ( extension !== null ) {
  13032. // TODO Complete?
  13033. return p;
  13034. } else {
  13035. return null;
  13036. }
  13037. }
  13038. if ( p === RGBA_BPTC_Format ) {
  13039. extension = extensions.get( 'EXT_texture_compression_bptc' );
  13040. if ( extension !== null ) {
  13041. // TODO Complete?
  13042. return p;
  13043. } else {
  13044. return null;
  13045. }
  13046. }
  13047. if ( p === UnsignedInt248Type$1 ) {
  13048. if ( isWebGL2 ) return 34042;
  13049. extension = extensions.get( 'WEBGL_depth_texture' );
  13050. if ( extension !== null ) {
  13051. return extension.UNSIGNED_INT_24_8_WEBGL;
  13052. } else {
  13053. return null;
  13054. }
  13055. }
  13056. }
  13057. return { convert: convert };
  13058. }
  13059. function ArrayCamera( array = [] ) {
  13060. PerspectiveCamera.call( this );
  13061. this.cameras = array;
  13062. }
  13063. ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
  13064. constructor: ArrayCamera,
  13065. isArrayCamera: true
  13066. } );
  13067. function Group() {
  13068. Object3D.call( this );
  13069. this.type = 'Group';
  13070. }
  13071. Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
  13072. constructor: Group,
  13073. isGroup: true
  13074. } );
  13075. function WebXRController() {
  13076. this._targetRay = null;
  13077. this._grip = null;
  13078. this._hand = null;
  13079. }
  13080. Object.assign( WebXRController.prototype, {
  13081. constructor: WebXRController,
  13082. getHandSpace: function () {
  13083. if ( this._hand === null ) {
  13084. this._hand = new Group();
  13085. this._hand.matrixAutoUpdate = false;
  13086. this._hand.visible = false;
  13087. this._hand.joints = [];
  13088. this._hand.inputState = { pinching: false };
  13089. if ( window.XRHand ) {
  13090. for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) {
  13091. // The transform of this joint will be updated with the joint pose on each frame
  13092. const joint = new Group();
  13093. joint.matrixAutoUpdate = false;
  13094. joint.visible = false;
  13095. this._hand.joints.push( joint );
  13096. // ??
  13097. this._hand.add( joint );
  13098. }
  13099. }
  13100. }
  13101. return this._hand;
  13102. },
  13103. getTargetRaySpace: function () {
  13104. if ( this._targetRay === null ) {
  13105. this._targetRay = new Group();
  13106. this._targetRay.matrixAutoUpdate = false;
  13107. this._targetRay.visible = false;
  13108. }
  13109. return this._targetRay;
  13110. },
  13111. getGripSpace: function () {
  13112. if ( this._grip === null ) {
  13113. this._grip = new Group();
  13114. this._grip.matrixAutoUpdate = false;
  13115. this._grip.visible = false;
  13116. }
  13117. return this._grip;
  13118. },
  13119. dispatchEvent: function ( event ) {
  13120. if ( this._targetRay !== null ) {
  13121. this._targetRay.dispatchEvent( event );
  13122. }
  13123. if ( this._grip !== null ) {
  13124. this._grip.dispatchEvent( event );
  13125. }
  13126. if ( this._hand !== null ) {
  13127. this._hand.dispatchEvent( event );
  13128. }
  13129. return this;
  13130. },
  13131. disconnect: function ( inputSource ) {
  13132. this.dispatchEvent( { type: 'disconnected', data: inputSource } );
  13133. if ( this._targetRay !== null ) {
  13134. this._targetRay.visible = false;
  13135. }
  13136. if ( this._grip !== null ) {
  13137. this._grip.visible = false;
  13138. }
  13139. if ( this._hand !== null ) {
  13140. this._hand.visible = false;
  13141. }
  13142. return this;
  13143. },
  13144. update: function ( inputSource, frame, referenceSpace ) {
  13145. let inputPose = null;
  13146. let gripPose = null;
  13147. let handPose = null;
  13148. const targetRay = this._targetRay;
  13149. const grip = this._grip;
  13150. const hand = this._hand;
  13151. if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
  13152. if ( hand && inputSource.hand ) {
  13153. handPose = true;
  13154. for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) {
  13155. if ( inputSource.hand[ i ] ) {
  13156. // Update the joints groups with the XRJoint poses
  13157. const jointPose = frame.getJointPose( inputSource.hand[ i ], referenceSpace );
  13158. const joint = hand.joints[ i ];
  13159. if ( jointPose !== null ) {
  13160. joint.matrix.fromArray( jointPose.transform.matrix );
  13161. joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
  13162. joint.jointRadius = jointPose.radius;
  13163. }
  13164. joint.visible = jointPose !== null;
  13165. // Custom events
  13166. // Check pinch
  13167. const indexTip = hand.joints[ window.XRHand.INDEX_PHALANX_TIP ];
  13168. const thumbTip = hand.joints[ window.XRHand.THUMB_PHALANX_TIP ];
  13169. const distance = indexTip.position.distanceTo( thumbTip.position );
  13170. const distanceToPinch = 0.02;
  13171. const threshold = 0.005;
  13172. if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
  13173. hand.inputState.pinching = false;
  13174. this.dispatchEvent( {
  13175. type: 'pinchend',
  13176. handedness: inputSource.handedness,
  13177. target: this
  13178. } );
  13179. } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
  13180. hand.inputState.pinching = true;
  13181. this.dispatchEvent( {
  13182. type: 'pinchstart',
  13183. handedness: inputSource.handedness,
  13184. target: this
  13185. } );
  13186. }
  13187. }
  13188. }
  13189. } else {
  13190. if ( targetRay !== null ) {
  13191. inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
  13192. if ( inputPose !== null ) {
  13193. targetRay.matrix.fromArray( inputPose.transform.matrix );
  13194. targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
  13195. }
  13196. }
  13197. if ( grip !== null && inputSource.gripSpace ) {
  13198. gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
  13199. if ( gripPose !== null ) {
  13200. grip.matrix.fromArray( gripPose.transform.matrix );
  13201. grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
  13202. }
  13203. }
  13204. }
  13205. }
  13206. if ( targetRay !== null ) {
  13207. targetRay.visible = ( inputPose !== null );
  13208. }
  13209. if ( grip !== null ) {
  13210. grip.visible = ( gripPose !== null );
  13211. }
  13212. if ( hand !== null ) {
  13213. hand.visible = ( handPose !== null );
  13214. }
  13215. return this;
  13216. }
  13217. } );
  13218. function WebXRManager( renderer, gl ) {
  13219. const scope = this;
  13220. let session = null;
  13221. let framebufferScaleFactor = 1.0;
  13222. let referenceSpace = null;
  13223. let referenceSpaceType = 'local-floor';
  13224. let pose = null;
  13225. const controllers = [];
  13226. const inputSourcesMap = new Map();
  13227. //
  13228. const cameraL = new PerspectiveCamera();
  13229. cameraL.layers.enable( 1 );
  13230. cameraL.viewport = new Vector4();
  13231. const cameraR = new PerspectiveCamera();
  13232. cameraR.layers.enable( 2 );
  13233. cameraR.viewport = new Vector4();
  13234. const cameras = [ cameraL, cameraR ];
  13235. const cameraVR = new ArrayCamera();
  13236. cameraVR.layers.enable( 1 );
  13237. cameraVR.layers.enable( 2 );
  13238. let _currentDepthNear = null;
  13239. let _currentDepthFar = null;
  13240. //
  13241. this.enabled = false;
  13242. this.isPresenting = false;
  13243. this.getController = function ( index ) {
  13244. let controller = controllers[ index ];
  13245. if ( controller === undefined ) {
  13246. controller = new WebXRController();
  13247. controllers[ index ] = controller;
  13248. }
  13249. return controller.getTargetRaySpace();
  13250. };
  13251. this.getControllerGrip = function ( index ) {
  13252. let controller = controllers[ index ];
  13253. if ( controller === undefined ) {
  13254. controller = new WebXRController();
  13255. controllers[ index ] = controller;
  13256. }
  13257. return controller.getGripSpace();
  13258. };
  13259. this.getHand = function ( index ) {
  13260. let controller = controllers[ index ];
  13261. if ( controller === undefined ) {
  13262. controller = new WebXRController();
  13263. controllers[ index ] = controller;
  13264. }
  13265. return controller.getHandSpace();
  13266. };
  13267. //
  13268. function onSessionEvent( event ) {
  13269. const controller = inputSourcesMap.get( event.inputSource );
  13270. if ( controller ) {
  13271. controller.dispatchEvent( { type: event.type, data: event.inputSource } );
  13272. }
  13273. }
  13274. function onSessionEnd() {
  13275. inputSourcesMap.forEach( function ( controller, inputSource ) {
  13276. controller.disconnect( inputSource );
  13277. } );
  13278. inputSourcesMap.clear();
  13279. //
  13280. renderer.setFramebuffer( null );
  13281. renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830
  13282. animation.stop();
  13283. scope.isPresenting = false;
  13284. scope.dispatchEvent( { type: 'sessionend' } );
  13285. }
  13286. function onRequestReferenceSpace( value ) {
  13287. referenceSpace = value;
  13288. animation.setContext( session );
  13289. animation.start();
  13290. scope.isPresenting = true;
  13291. scope.dispatchEvent( { type: 'sessionstart' } );
  13292. }
  13293. this.setFramebufferScaleFactor = function ( value ) {
  13294. framebufferScaleFactor = value;
  13295. if ( scope.isPresenting === true ) {
  13296. console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
  13297. }
  13298. };
  13299. this.setReferenceSpaceType = function ( value ) {
  13300. referenceSpaceType = value;
  13301. if ( scope.isPresenting === true ) {
  13302. console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
  13303. }
  13304. };
  13305. this.getReferenceSpace = function () {
  13306. return referenceSpace;
  13307. };
  13308. this.getSession = function () {
  13309. return session;
  13310. };
  13311. this.setSession = function ( value ) {
  13312. session = value;
  13313. if ( session !== null ) {
  13314. session.addEventListener( 'select', onSessionEvent );
  13315. session.addEventListener( 'selectstart', onSessionEvent );
  13316. session.addEventListener( 'selectend', onSessionEvent );
  13317. session.addEventListener( 'squeeze', onSessionEvent );
  13318. session.addEventListener( 'squeezestart', onSessionEvent );
  13319. session.addEventListener( 'squeezeend', onSessionEvent );
  13320. session.addEventListener( 'end', onSessionEnd );
  13321. const attributes = gl.getContextAttributes();
  13322. if ( attributes.xrCompatible !== true ) {
  13323. gl.makeXRCompatible();
  13324. }
  13325. const layerInit = {
  13326. antialias: attributes.antialias,
  13327. alpha: attributes.alpha,
  13328. depth: attributes.depth,
  13329. stencil: attributes.stencil,
  13330. framebufferScaleFactor: framebufferScaleFactor
  13331. };
  13332. // eslint-disable-next-line no-undef
  13333. const baseLayer = new XRWebGLLayer( session, gl, layerInit );
  13334. session.updateRenderState( { baseLayer: baseLayer } );
  13335. session.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );
  13336. //
  13337. session.addEventListener( 'inputsourceschange', updateInputSources );
  13338. }
  13339. };
  13340. function updateInputSources( event ) {
  13341. const inputSources = session.inputSources;
  13342. // Assign inputSources to available controllers
  13343. for ( let i = 0; i < controllers.length; i ++ ) {
  13344. inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
  13345. }
  13346. // Notify disconnected
  13347. for ( let i = 0; i < event.removed.length; i ++ ) {
  13348. const inputSource = event.removed[ i ];
  13349. const controller = inputSourcesMap.get( inputSource );
  13350. if ( controller ) {
  13351. controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
  13352. inputSourcesMap.delete( inputSource );
  13353. }
  13354. }
  13355. // Notify connected
  13356. for ( let i = 0; i < event.added.length; i ++ ) {
  13357. const inputSource = event.added[ i ];
  13358. const controller = inputSourcesMap.get( inputSource );
  13359. if ( controller ) {
  13360. controller.dispatchEvent( { type: 'connected', data: inputSource } );
  13361. }
  13362. }
  13363. }
  13364. //
  13365. const cameraLPos = new Vector3();
  13366. const cameraRPos = new Vector3();
  13367. /**
  13368. * Assumes 2 cameras that are parallel and share an X-axis, and that
  13369. * the cameras' projection and world matrices have already been set.
  13370. * And that near and far planes are identical for both cameras.
  13371. * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
  13372. */
  13373. function setProjectionFromUnion( camera, cameraL, cameraR ) {
  13374. cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
  13375. cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
  13376. const ipd = cameraLPos.distanceTo( cameraRPos );
  13377. const projL = cameraL.projectionMatrix.elements;
  13378. const projR = cameraR.projectionMatrix.elements;
  13379. // VR systems will have identical far and near planes, and
  13380. // most likely identical top and bottom frustum extents.
  13381. // Use the left camera for these values.
  13382. const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
  13383. const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
  13384. const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
  13385. const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
  13386. const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
  13387. const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
  13388. const left = near * leftFov;
  13389. const right = near * rightFov;
  13390. // Calculate the new camera's position offset from the
  13391. // left camera. xOffset should be roughly half `ipd`.
  13392. const zOffset = ipd / ( - leftFov + rightFov );
  13393. const xOffset = zOffset * - leftFov;
  13394. // TODO: Better way to apply this offset?
  13395. cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
  13396. camera.translateX( xOffset );
  13397. camera.translateZ( zOffset );
  13398. camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
  13399. camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
  13400. // Find the union of the frustum values of the cameras and scale
  13401. // the values so that the near plane's position does not change in world space,
  13402. // although must now be relative to the new union camera.
  13403. const near2 = near + zOffset;
  13404. const far2 = far + zOffset;
  13405. const left2 = left - xOffset;
  13406. const right2 = right + ( ipd - xOffset );
  13407. const top2 = topFov * far / far2 * near2;
  13408. const bottom2 = bottomFov * far / far2 * near2;
  13409. camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
  13410. }
  13411. function updateCamera( camera, parent ) {
  13412. if ( parent === null ) {
  13413. camera.matrixWorld.copy( camera.matrix );
  13414. } else {
  13415. camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
  13416. }
  13417. camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
  13418. }
  13419. this.getCamera = function ( camera ) {
  13420. cameraVR.near = cameraR.near = cameraL.near = camera.near;
  13421. cameraVR.far = cameraR.far = cameraL.far = camera.far;
  13422. if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
  13423. // Note that the new renderState won't apply until the next frame. See #18320
  13424. session.updateRenderState( {
  13425. depthNear: cameraVR.near,
  13426. depthFar: cameraVR.far
  13427. } );
  13428. _currentDepthNear = cameraVR.near;
  13429. _currentDepthFar = cameraVR.far;
  13430. }
  13431. const parent = camera.parent;
  13432. const cameras = cameraVR.cameras;
  13433. updateCamera( cameraVR, parent );
  13434. for ( let i = 0; i < cameras.length; i ++ ) {
  13435. updateCamera( cameras[ i ], parent );
  13436. }
  13437. // update camera and its children
  13438. camera.matrixWorld.copy( cameraVR.matrixWorld );
  13439. const children = camera.children;
  13440. for ( let i = 0, l = children.length; i < l; i ++ ) {
  13441. children[ i ].updateMatrixWorld( true );
  13442. }
  13443. // update projection matrix for proper view frustum culling
  13444. if ( cameras.length === 2 ) {
  13445. setProjectionFromUnion( cameraVR, cameraL, cameraR );
  13446. } else {
  13447. // assume single camera setup (AR)
  13448. cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
  13449. }
  13450. return cameraVR;
  13451. };
  13452. // Animation Loop
  13453. let onAnimationFrameCallback = null;
  13454. function onAnimationFrame( time, frame ) {
  13455. pose = frame.getViewerPose( referenceSpace );
  13456. if ( pose !== null ) {
  13457. const views = pose.views;
  13458. const baseLayer = session.renderState.baseLayer;
  13459. renderer.setFramebuffer( baseLayer.framebuffer );
  13460. let cameraVRNeedsUpdate = false;
  13461. // check if it's necessary to rebuild cameraVR's camera list
  13462. if ( views.length !== cameraVR.cameras.length ) {
  13463. cameraVR.cameras.length = 0;
  13464. cameraVRNeedsUpdate = true;
  13465. }
  13466. for ( let i = 0; i < views.length; i ++ ) {
  13467. const view = views[ i ];
  13468. const viewport = baseLayer.getViewport( view );
  13469. const camera = cameras[ i ];
  13470. camera.matrix.fromArray( view.transform.matrix );
  13471. camera.projectionMatrix.fromArray( view.projectionMatrix );
  13472. camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
  13473. if ( i === 0 ) {
  13474. cameraVR.matrix.copy( camera.matrix );
  13475. }
  13476. if ( cameraVRNeedsUpdate === true ) {
  13477. cameraVR.cameras.push( camera );
  13478. }
  13479. }
  13480. }
  13481. //
  13482. const inputSources = session.inputSources;
  13483. for ( let i = 0; i < controllers.length; i ++ ) {
  13484. const controller = controllers[ i ];
  13485. const inputSource = inputSources[ i ];
  13486. controller.update( inputSource, frame, referenceSpace );
  13487. }
  13488. if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
  13489. }
  13490. const animation = new WebGLAnimation();
  13491. animation.setAnimationLoop( onAnimationFrame );
  13492. this.setAnimationLoop = function ( callback ) {
  13493. onAnimationFrameCallback = callback;
  13494. };
  13495. this.dispose = function () {};
  13496. }
  13497. Object.assign( WebXRManager.prototype, EventDispatcher.prototype );
  13498. function WebGLMaterials( properties ) {
  13499. function refreshFogUniforms( uniforms, fog ) {
  13500. uniforms.fogColor.value.copy( fog.color );
  13501. if ( fog.isFog ) {
  13502. uniforms.fogNear.value = fog.near;
  13503. uniforms.fogFar.value = fog.far;
  13504. } else if ( fog.isFogExp2 ) {
  13505. uniforms.fogDensity.value = fog.density;
  13506. }
  13507. }
  13508. function refreshMaterialUniforms( uniforms, material, pixelRatio, height ) {
  13509. if ( material.isMeshBasicMaterial ) {
  13510. refreshUniformsCommon( uniforms, material );
  13511. } else if ( material.isMeshLambertMaterial ) {
  13512. refreshUniformsCommon( uniforms, material );
  13513. refreshUniformsLambert( uniforms, material );
  13514. } else if ( material.isMeshToonMaterial ) {
  13515. refreshUniformsCommon( uniforms, material );
  13516. refreshUniformsToon( uniforms, material );
  13517. } else if ( material.isMeshPhongMaterial ) {
  13518. refreshUniformsCommon( uniforms, material );
  13519. refreshUniformsPhong( uniforms, material );
  13520. } else if ( material.isMeshStandardMaterial ) {
  13521. refreshUniformsCommon( uniforms, material );
  13522. if ( material.isMeshPhysicalMaterial ) {
  13523. refreshUniformsPhysical( uniforms, material );
  13524. } else {
  13525. refreshUniformsStandard( uniforms, material );
  13526. }
  13527. } else if ( material.isMeshMatcapMaterial ) {
  13528. refreshUniformsCommon( uniforms, material );
  13529. refreshUniformsMatcap( uniforms, material );
  13530. } else if ( material.isMeshDepthMaterial ) {
  13531. refreshUniformsCommon( uniforms, material );
  13532. refreshUniformsDepth( uniforms, material );
  13533. } else if ( material.isMeshDistanceMaterial ) {
  13534. refreshUniformsCommon( uniforms, material );
  13535. refreshUniformsDistance( uniforms, material );
  13536. } else if ( material.isMeshNormalMaterial ) {
  13537. refreshUniformsCommon( uniforms, material );
  13538. refreshUniformsNormal( uniforms, material );
  13539. } else if ( material.isLineBasicMaterial ) {
  13540. refreshUniformsLine( uniforms, material );
  13541. if ( material.isLineDashedMaterial ) {
  13542. refreshUniformsDash( uniforms, material );
  13543. }
  13544. } else if ( material.isPointsMaterial ) {
  13545. refreshUniformsPoints( uniforms, material, pixelRatio, height );
  13546. } else if ( material.isSpriteMaterial ) {
  13547. refreshUniformsSprites( uniforms, material );
  13548. } else if ( material.isShadowMaterial ) {
  13549. uniforms.color.value.copy( material.color );
  13550. uniforms.opacity.value = material.opacity;
  13551. } else if ( material.isShaderMaterial ) {
  13552. material.uniformsNeedUpdate = false; // #15581
  13553. }
  13554. }
  13555. function refreshUniformsCommon( uniforms, material ) {
  13556. uniforms.opacity.value = material.opacity;
  13557. if ( material.color ) {
  13558. uniforms.diffuse.value.copy( material.color );
  13559. }
  13560. if ( material.emissive ) {
  13561. uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
  13562. }
  13563. if ( material.map ) {
  13564. uniforms.map.value = material.map;
  13565. }
  13566. if ( material.alphaMap ) {
  13567. uniforms.alphaMap.value = material.alphaMap;
  13568. }
  13569. if ( material.specularMap ) {
  13570. uniforms.specularMap.value = material.specularMap;
  13571. }
  13572. const envMap = properties.get( material ).envMap;
  13573. if ( envMap ) {
  13574. uniforms.envMap.value = envMap;
  13575. uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap._needsFlipEnvMap ) ? - 1 : 1;
  13576. uniforms.reflectivity.value = material.reflectivity;
  13577. uniforms.refractionRatio.value = material.refractionRatio;
  13578. const maxMipLevel = properties.get( envMap ).__maxMipLevel;
  13579. if ( maxMipLevel !== undefined ) {
  13580. uniforms.maxMipLevel.value = maxMipLevel;
  13581. }
  13582. }
  13583. if ( material.lightMap ) {
  13584. uniforms.lightMap.value = material.lightMap;
  13585. uniforms.lightMapIntensity.value = material.lightMapIntensity;
  13586. }
  13587. if ( material.aoMap ) {
  13588. uniforms.aoMap.value = material.aoMap;
  13589. uniforms.aoMapIntensity.value = material.aoMapIntensity;
  13590. }
  13591. // uv repeat and offset setting priorities
  13592. // 1. color map
  13593. // 2. specular map
  13594. // 3. displacementMap map
  13595. // 4. normal map
  13596. // 5. bump map
  13597. // 6. roughnessMap map
  13598. // 7. metalnessMap map
  13599. // 8. alphaMap map
  13600. // 9. emissiveMap map
  13601. // 10. clearcoat map
  13602. // 11. clearcoat normal map
  13603. // 12. clearcoat roughnessMap map
  13604. let uvScaleMap;
  13605. if ( material.map ) {
  13606. uvScaleMap = material.map;
  13607. } else if ( material.specularMap ) {
  13608. uvScaleMap = material.specularMap;
  13609. } else if ( material.displacementMap ) {
  13610. uvScaleMap = material.displacementMap;
  13611. } else if ( material.normalMap ) {
  13612. uvScaleMap = material.normalMap;
  13613. } else if ( material.bumpMap ) {
  13614. uvScaleMap = material.bumpMap;
  13615. } else if ( material.roughnessMap ) {
  13616. uvScaleMap = material.roughnessMap;
  13617. } else if ( material.metalnessMap ) {
  13618. uvScaleMap = material.metalnessMap;
  13619. } else if ( material.alphaMap ) {
  13620. uvScaleMap = material.alphaMap;
  13621. } else if ( material.emissiveMap ) {
  13622. uvScaleMap = material.emissiveMap;
  13623. } else if ( material.clearcoatMap ) {
  13624. uvScaleMap = material.clearcoatMap;
  13625. } else if ( material.clearcoatNormalMap ) {
  13626. uvScaleMap = material.clearcoatNormalMap;
  13627. } else if ( material.clearcoatRoughnessMap ) {
  13628. uvScaleMap = material.clearcoatRoughnessMap;
  13629. }
  13630. if ( uvScaleMap !== undefined ) {
  13631. // backwards compatibility
  13632. if ( uvScaleMap.isWebGLRenderTarget ) {
  13633. uvScaleMap = uvScaleMap.texture;
  13634. }
  13635. if ( uvScaleMap.matrixAutoUpdate === true ) {
  13636. uvScaleMap.updateMatrix();
  13637. }
  13638. uniforms.uvTransform.value.copy( uvScaleMap.matrix );
  13639. }
  13640. // uv repeat and offset setting priorities for uv2
  13641. // 1. ao map
  13642. // 2. light map
  13643. let uv2ScaleMap;
  13644. if ( material.aoMap ) {
  13645. uv2ScaleMap = material.aoMap;
  13646. } else if ( material.lightMap ) {
  13647. uv2ScaleMap = material.lightMap;
  13648. }
  13649. if ( uv2ScaleMap !== undefined ) {
  13650. // backwards compatibility
  13651. if ( uv2ScaleMap.isWebGLRenderTarget ) {
  13652. uv2ScaleMap = uv2ScaleMap.texture;
  13653. }
  13654. if ( uv2ScaleMap.matrixAutoUpdate === true ) {
  13655. uv2ScaleMap.updateMatrix();
  13656. }
  13657. uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );
  13658. }
  13659. }
  13660. function refreshUniformsLine( uniforms, material ) {
  13661. uniforms.diffuse.value.copy( material.color );
  13662. uniforms.opacity.value = material.opacity;
  13663. }
  13664. function refreshUniformsDash( uniforms, material ) {
  13665. uniforms.dashSize.value = material.dashSize;
  13666. uniforms.totalSize.value = material.dashSize + material.gapSize;
  13667. uniforms.scale.value = material.scale;
  13668. }
  13669. function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
  13670. uniforms.diffuse.value.copy( material.color );
  13671. uniforms.opacity.value = material.opacity;
  13672. uniforms.size.value = material.size * pixelRatio;
  13673. uniforms.scale.value = height * 0.5;
  13674. if ( material.map ) {
  13675. uniforms.map.value = material.map;
  13676. }
  13677. if ( material.alphaMap ) {
  13678. uniforms.alphaMap.value = material.alphaMap;
  13679. }
  13680. // uv repeat and offset setting priorities
  13681. // 1. color map
  13682. // 2. alpha map
  13683. let uvScaleMap;
  13684. if ( material.map ) {
  13685. uvScaleMap = material.map;
  13686. } else if ( material.alphaMap ) {
  13687. uvScaleMap = material.alphaMap;
  13688. }
  13689. if ( uvScaleMap !== undefined ) {
  13690. if ( uvScaleMap.matrixAutoUpdate === true ) {
  13691. uvScaleMap.updateMatrix();
  13692. }
  13693. uniforms.uvTransform.value.copy( uvScaleMap.matrix );
  13694. }
  13695. }
  13696. function refreshUniformsSprites( uniforms, material ) {
  13697. uniforms.diffuse.value.copy( material.color );
  13698. uniforms.opacity.value = material.opacity;
  13699. uniforms.rotation.value = material.rotation;
  13700. if ( material.map ) {
  13701. uniforms.map.value = material.map;
  13702. }
  13703. if ( material.alphaMap ) {
  13704. uniforms.alphaMap.value = material.alphaMap;
  13705. }
  13706. // uv repeat and offset setting priorities
  13707. // 1. color map
  13708. // 2. alpha map
  13709. let uvScaleMap;
  13710. if ( material.map ) {
  13711. uvScaleMap = material.map;
  13712. } else if ( material.alphaMap ) {
  13713. uvScaleMap = material.alphaMap;
  13714. }
  13715. if ( uvScaleMap !== undefined ) {
  13716. if ( uvScaleMap.matrixAutoUpdate === true ) {
  13717. uvScaleMap.updateMatrix();
  13718. }
  13719. uniforms.uvTransform.value.copy( uvScaleMap.matrix );
  13720. }
  13721. }
  13722. function refreshUniformsLambert( uniforms, material ) {
  13723. if ( material.emissiveMap ) {
  13724. uniforms.emissiveMap.value = material.emissiveMap;
  13725. }
  13726. }
  13727. function refreshUniformsPhong( uniforms, material ) {
  13728. uniforms.specular.value.copy( material.specular );
  13729. uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
  13730. if ( material.emissiveMap ) {
  13731. uniforms.emissiveMap.value = material.emissiveMap;
  13732. }
  13733. if ( material.bumpMap ) {
  13734. uniforms.bumpMap.value = material.bumpMap;
  13735. uniforms.bumpScale.value = material.bumpScale;
  13736. if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
  13737. }
  13738. if ( material.normalMap ) {
  13739. uniforms.normalMap.value = material.normalMap;
  13740. uniforms.normalScale.value.copy( material.normalScale );
  13741. if ( material.side === BackSide ) uniforms.normalScale.value.negate();
  13742. }
  13743. if ( material.displacementMap ) {
  13744. uniforms.displacementMap.value = material.displacementMap;
  13745. uniforms.displacementScale.value = material.displacementScale;
  13746. uniforms.displacementBias.value = material.displacementBias;
  13747. }
  13748. }
  13749. function refreshUniformsToon( uniforms, material ) {
  13750. if ( material.gradientMap ) {
  13751. uniforms.gradientMap.value = material.gradientMap;
  13752. }
  13753. if ( material.emissiveMap ) {
  13754. uniforms.emissiveMap.value = material.emissiveMap;
  13755. }
  13756. if ( material.bumpMap ) {
  13757. uniforms.bumpMap.value = material.bumpMap;
  13758. uniforms.bumpScale.value = material.bumpScale;
  13759. if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
  13760. }
  13761. if ( material.normalMap ) {
  13762. uniforms.normalMap.value = material.normalMap;
  13763. uniforms.normalScale.value.copy( material.normalScale );
  13764. if ( material.side === BackSide ) uniforms.normalScale.value.negate();
  13765. }
  13766. if ( material.displacementMap ) {
  13767. uniforms.displacementMap.value = material.displacementMap;
  13768. uniforms.displacementScale.value = material.displacementScale;
  13769. uniforms.displacementBias.value = material.displacementBias;
  13770. }
  13771. }
  13772. function refreshUniformsStandard( uniforms, material ) {
  13773. uniforms.roughness.value = material.roughness;
  13774. uniforms.metalness.value = material.metalness;
  13775. if ( material.roughnessMap ) {
  13776. uniforms.roughnessMap.value = material.roughnessMap;
  13777. }
  13778. if ( material.metalnessMap ) {
  13779. uniforms.metalnessMap.value = material.metalnessMap;
  13780. }
  13781. if ( material.emissiveMap ) {
  13782. uniforms.emissiveMap.value = material.emissiveMap;
  13783. }
  13784. if ( material.bumpMap ) {
  13785. uniforms.bumpMap.value = material.bumpMap;
  13786. uniforms.bumpScale.value = material.bumpScale;
  13787. if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
  13788. }
  13789. if ( material.normalMap ) {
  13790. uniforms.normalMap.value = material.normalMap;
  13791. uniforms.normalScale.value.copy( material.normalScale );
  13792. if ( material.side === BackSide ) uniforms.normalScale.value.negate();
  13793. }
  13794. if ( material.displacementMap ) {
  13795. uniforms.displacementMap.value = material.displacementMap;
  13796. uniforms.displacementScale.value = material.displacementScale;
  13797. uniforms.displacementBias.value = material.displacementBias;
  13798. }
  13799. const envMap = properties.get( material ).envMap;
  13800. if ( envMap ) {
  13801. //uniforms.envMap.value = material.envMap; // part of uniforms common
  13802. uniforms.envMapIntensity.value = material.envMapIntensity;
  13803. }
  13804. }
  13805. function refreshUniformsPhysical( uniforms, material ) {
  13806. refreshUniformsStandard( uniforms, material );
  13807. uniforms.reflectivity.value = material.reflectivity; // also part of uniforms common
  13808. uniforms.clearcoat.value = material.clearcoat;
  13809. uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
  13810. if ( material.sheen ) uniforms.sheen.value.copy( material.sheen );
  13811. if ( material.clearcoatMap ) {
  13812. uniforms.clearcoatMap.value = material.clearcoatMap;
  13813. }
  13814. if ( material.clearcoatRoughnessMap ) {
  13815. uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
  13816. }
  13817. if ( material.clearcoatNormalMap ) {
  13818. uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
  13819. uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
  13820. if ( material.side === BackSide ) {
  13821. uniforms.clearcoatNormalScale.value.negate();
  13822. }
  13823. }
  13824. uniforms.transmission.value = material.transmission;
  13825. if ( material.transmissionMap ) {
  13826. uniforms.transmissionMap.value = material.transmissionMap;
  13827. }
  13828. }
  13829. function refreshUniformsMatcap( uniforms, material ) {
  13830. if ( material.matcap ) {
  13831. uniforms.matcap.value = material.matcap;
  13832. }
  13833. if ( material.bumpMap ) {
  13834. uniforms.bumpMap.value = material.bumpMap;
  13835. uniforms.bumpScale.value = material.bumpScale;
  13836. if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
  13837. }
  13838. if ( material.normalMap ) {
  13839. uniforms.normalMap.value = material.normalMap;
  13840. uniforms.normalScale.value.copy( material.normalScale );
  13841. if ( material.side === BackSide ) uniforms.normalScale.value.negate();
  13842. }
  13843. if ( material.displacementMap ) {
  13844. uniforms.displacementMap.value = material.displacementMap;
  13845. uniforms.displacementScale.value = material.displacementScale;
  13846. uniforms.displacementBias.value = material.displacementBias;
  13847. }
  13848. }
  13849. function refreshUniformsDepth( uniforms, material ) {
  13850. if ( material.displacementMap ) {
  13851. uniforms.displacementMap.value = material.displacementMap;
  13852. uniforms.displacementScale.value = material.displacementScale;
  13853. uniforms.displacementBias.value = material.displacementBias;
  13854. }
  13855. }
  13856. function refreshUniformsDistance( uniforms, material ) {
  13857. if ( material.displacementMap ) {
  13858. uniforms.displacementMap.value = material.displacementMap;
  13859. uniforms.displacementScale.value = material.displacementScale;
  13860. uniforms.displacementBias.value = material.displacementBias;
  13861. }
  13862. uniforms.referencePosition.value.copy( material.referencePosition );
  13863. uniforms.nearDistance.value = material.nearDistance;
  13864. uniforms.farDistance.value = material.farDistance;
  13865. }
  13866. function refreshUniformsNormal( uniforms, material ) {
  13867. if ( material.bumpMap ) {
  13868. uniforms.bumpMap.value = material.bumpMap;
  13869. uniforms.bumpScale.value = material.bumpScale;
  13870. if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
  13871. }
  13872. if ( material.normalMap ) {
  13873. uniforms.normalMap.value = material.normalMap;
  13874. uniforms.normalScale.value.copy( material.normalScale );
  13875. if ( material.side === BackSide ) uniforms.normalScale.value.negate();
  13876. }
  13877. if ( material.displacementMap ) {
  13878. uniforms.displacementMap.value = material.displacementMap;
  13879. uniforms.displacementScale.value = material.displacementScale;
  13880. uniforms.displacementBias.value = material.displacementBias;
  13881. }
  13882. }
  13883. return {
  13884. refreshFogUniforms: refreshFogUniforms,
  13885. refreshMaterialUniforms: refreshMaterialUniforms
  13886. };
  13887. }
  13888. function createCanvasElement() {
  13889. const canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
  13890. canvas.style.display = 'block';
  13891. return canvas;
  13892. }
  13893. function WebGLRenderer( parameters ) {
  13894. parameters = parameters || {};
  13895. const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(),
  13896. _context = parameters.context !== undefined ? parameters.context : null,
  13897. _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
  13898. _depth = parameters.depth !== undefined ? parameters.depth : true,
  13899. _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
  13900. _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
  13901. _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
  13902. _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
  13903. _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',
  13904. _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;
  13905. let currentRenderList = null;
  13906. let currentRenderState = null;
  13907. // render() can be called from within a callback triggered by another render.
  13908. // We track this so that the nested render call gets its state isolated from the parent render call.
  13909. const renderStateStack = [];
  13910. // public properties
  13911. this.domElement = _canvas;
  13912. // Debug configuration container
  13913. this.debug = {
  13914. /**
  13915. * Enables error checking and reporting when shader programs are being compiled
  13916. * @type {boolean}
  13917. */
  13918. checkShaderErrors: true
  13919. };
  13920. // clearing
  13921. this.autoClear = true;
  13922. this.autoClearColor = true;
  13923. this.autoClearDepth = true;
  13924. this.autoClearStencil = true;
  13925. // scene graph
  13926. this.sortObjects = true;
  13927. // user-defined clipping
  13928. this.clippingPlanes = [];
  13929. this.localClippingEnabled = false;
  13930. // physically based shading
  13931. this.gammaFactor = 2.0; // for backwards compatibility
  13932. this.outputEncoding = LinearEncoding;
  13933. // physical lights
  13934. this.physicallyCorrectLights = false;
  13935. // tone mapping
  13936. this.toneMapping = NoToneMapping;
  13937. this.toneMappingExposure = 1.0;
  13938. // morphs
  13939. this.maxMorphTargets = 8;
  13940. this.maxMorphNormals = 4;
  13941. // internal properties
  13942. const _this = this;
  13943. let _isContextLost = false;
  13944. // internal state cache
  13945. let _framebuffer = null;
  13946. let _currentActiveCubeFace = 0;
  13947. let _currentActiveMipmapLevel = 0;
  13948. let _currentRenderTarget = null;
  13949. let _currentFramebuffer = null;
  13950. let _currentMaterialId = - 1;
  13951. let _currentCamera = null;
  13952. const _currentViewport = new Vector4();
  13953. const _currentScissor = new Vector4();
  13954. let _currentScissorTest = null;
  13955. //
  13956. let _width = _canvas.width;
  13957. let _height = _canvas.height;
  13958. let _pixelRatio = 1;
  13959. let _opaqueSort = null;
  13960. let _transparentSort = null;
  13961. const _viewport = new Vector4( 0, 0, _width, _height );
  13962. const _scissor = new Vector4( 0, 0, _width, _height );
  13963. let _scissorTest = false;
  13964. // frustum
  13965. const _frustum = new Frustum();
  13966. // clipping
  13967. let _clippingEnabled = false;
  13968. let _localClippingEnabled = false;
  13969. // camera matrices cache
  13970. const _projScreenMatrix = new Matrix4();
  13971. const _vector3 = new Vector3();
  13972. const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
  13973. function getTargetPixelRatio() {
  13974. return _currentRenderTarget === null ? _pixelRatio : 1;
  13975. }
  13976. // initialize
  13977. let _gl = _context;
  13978. function getContext( contextNames, contextAttributes ) {
  13979. for ( let i = 0; i < contextNames.length; i ++ ) {
  13980. const contextName = contextNames[ i ];
  13981. const context = _canvas.getContext( contextName, contextAttributes );
  13982. if ( context !== null ) return context;
  13983. }
  13984. return null;
  13985. }
  13986. try {
  13987. const contextAttributes = {
  13988. alpha: _alpha,
  13989. depth: _depth,
  13990. stencil: _stencil,
  13991. antialias: _antialias,
  13992. premultipliedAlpha: _premultipliedAlpha,
  13993. preserveDrawingBuffer: _preserveDrawingBuffer,
  13994. powerPreference: _powerPreference,
  13995. failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat
  13996. };
  13997. // event listeners must be registered before WebGL context is created, see #12753
  13998. _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
  13999. _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
  14000. if ( _gl === null ) {
  14001. const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ];
  14002. if ( _this.isWebGL1Renderer === true ) {
  14003. contextNames.shift();
  14004. }
  14005. _gl = getContext( contextNames, contextAttributes );
  14006. if ( _gl === null ) {
  14007. if ( getContext( contextNames ) ) {
  14008. throw new Error( 'Error creating WebGL context with your selected attributes.' );
  14009. } else {
  14010. throw new Error( 'Error creating WebGL context.' );
  14011. }
  14012. }
  14013. }
  14014. // Some experimental-webgl implementations do not have getShaderPrecisionFormat
  14015. if ( _gl.getShaderPrecisionFormat === undefined ) {
  14016. _gl.getShaderPrecisionFormat = function () {
  14017. return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
  14018. };
  14019. }
  14020. } catch ( error ) {
  14021. console.error( 'THREE.WebGLRenderer: ' + error.message );
  14022. throw error;
  14023. }
  14024. let extensions, capabilities, state, info;
  14025. let properties, textures, cubemaps, attributes, geometries, objects;
  14026. let programCache, materials, renderLists, renderStates, clipping;
  14027. let background, morphtargets, bufferRenderer, indexedBufferRenderer;
  14028. let utils, bindingStates;
  14029. function initGLContext() {
  14030. extensions = new WebGLExtensions( _gl );
  14031. capabilities = new WebGLCapabilities( _gl, extensions, parameters );
  14032. if ( capabilities.isWebGL2 === false ) {
  14033. extensions.get( 'WEBGL_depth_texture' );
  14034. extensions.get( 'OES_texture_float' );
  14035. extensions.get( 'OES_texture_half_float' );
  14036. extensions.get( 'OES_texture_half_float_linear' );
  14037. extensions.get( 'OES_standard_derivatives' );
  14038. extensions.get( 'OES_element_index_uint' );
  14039. extensions.get( 'OES_vertex_array_object' );
  14040. extensions.get( 'ANGLE_instanced_arrays' );
  14041. }
  14042. extensions.get( 'OES_texture_float_linear' );
  14043. utils = new WebGLUtils( _gl, extensions, capabilities );
  14044. state = new WebGLState( _gl, extensions, capabilities );
  14045. state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
  14046. state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
  14047. info = new WebGLInfo( _gl );
  14048. properties = new WebGLProperties();
  14049. textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
  14050. cubemaps = new WebGLCubeMaps( _this );
  14051. attributes = new WebGLAttributes( _gl, capabilities );
  14052. bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities );
  14053. geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
  14054. objects = new WebGLObjects( _gl, geometries, attributes, info );
  14055. morphtargets = new WebGLMorphtargets( _gl );
  14056. clipping = new WebGLClipping( properties );
  14057. programCache = new WebGLPrograms( _this, cubemaps, extensions, capabilities, bindingStates, clipping );
  14058. materials = new WebGLMaterials( properties );
  14059. renderLists = new WebGLRenderLists( properties );
  14060. renderStates = new WebGLRenderStates( extensions, capabilities );
  14061. background = new WebGLBackground( _this, cubemaps, state, objects, _premultipliedAlpha );
  14062. bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
  14063. indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
  14064. info.programs = programCache.programs;
  14065. _this.capabilities = capabilities;
  14066. _this.extensions = extensions;
  14067. _this.properties = properties;
  14068. _this.renderLists = renderLists;
  14069. _this.state = state;
  14070. _this.info = info;
  14071. _this._textures = textures;//add
  14072. }
  14073. initGLContext();
  14074. // xr
  14075. const xr = new WebXRManager( _this, _gl );
  14076. this.xr = xr;
  14077. // shadow map
  14078. const shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
  14079. this.shadowMap = shadowMap;
  14080. // API
  14081. this.getContext = function () {
  14082. return _gl;
  14083. };
  14084. this.getContextAttributes = function () {
  14085. return _gl.getContextAttributes();
  14086. };
  14087. this.forceContextLoss = function () {
  14088. const extension = extensions.get( 'WEBGL_lose_context' );
  14089. if ( extension ) extension.loseContext();
  14090. };
  14091. this.forceContextRestore = function () {
  14092. const extension = extensions.get( 'WEBGL_lose_context' );
  14093. if ( extension ) extension.restoreContext();
  14094. };
  14095. this.getPixelRatio = function () {
  14096. return _pixelRatio;
  14097. };
  14098. this.setPixelRatio = function ( value ) {
  14099. if ( value === undefined ) return;
  14100. _pixelRatio = value;
  14101. this.setSize( _width, _height, false );
  14102. };
  14103. this.getSize = function ( target ) {
  14104. if ( target === undefined ) {
  14105. console.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );
  14106. target = new Vector2();
  14107. }
  14108. return target.set( _width, _height );
  14109. };
  14110. this.setSize = function ( width, height, updateStyle ) {
  14111. if ( xr.isPresenting ) {
  14112. console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
  14113. return;
  14114. }
  14115. _width = width;
  14116. _height = height;
  14117. _canvas.width = Math.floor( width * _pixelRatio );
  14118. _canvas.height = Math.floor( height * _pixelRatio );
  14119. if ( updateStyle !== false ) {
  14120. _canvas.style.width = width + 'px';
  14121. _canvas.style.height = height + 'px';
  14122. }
  14123. this.setViewport( 0, 0, width, height );
  14124. };
  14125. this.getDrawingBufferSize = function ( target ) {
  14126. if ( target === undefined ) {
  14127. console.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );
  14128. target = new Vector2();
  14129. }
  14130. return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
  14131. };
  14132. this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
  14133. _width = width;
  14134. _height = height;
  14135. _pixelRatio = pixelRatio;
  14136. _canvas.width = Math.floor( width * pixelRatio );
  14137. _canvas.height = Math.floor( height * pixelRatio );
  14138. this.setViewport( 0, 0, width, height );
  14139. };
  14140. this.getCurrentViewport = function ( target ) {
  14141. if ( target === undefined ) {
  14142. console.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );
  14143. target = new Vector4();
  14144. }
  14145. return target.copy( _currentViewport );
  14146. };
  14147. this.getViewport = function ( target ) {
  14148. return target.copy( _viewport );
  14149. };
  14150. this.setViewport = function ( x, y, width, height ) {
  14151. if ( x.isVector4 ) {
  14152. _viewport.set( x.x, x.y, x.z, x.w );
  14153. } else {
  14154. _viewport.set( x, y, width, height );
  14155. }
  14156. state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
  14157. };
  14158. this.getScissor = function ( target ) {
  14159. return target.copy( _scissor );
  14160. };
  14161. this.setScissor = function ( x, y, width, height ) {
  14162. if ( x.isVector4 ) {
  14163. _scissor.set( x.x, x.y, x.z, x.w );
  14164. } else {
  14165. _scissor.set( x, y, width, height );
  14166. }
  14167. state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
  14168. };
  14169. this.getScissorTest = function () {
  14170. return _scissorTest;
  14171. };
  14172. this.setScissorTest = function ( boolean ) {
  14173. state.setScissorTest( _scissorTest = boolean );
  14174. };
  14175. this.setOpaqueSort = function ( method ) {
  14176. _opaqueSort = method;
  14177. };
  14178. this.setTransparentSort = function ( method ) {
  14179. _transparentSort = method;
  14180. };
  14181. // Clearing
  14182. this.getClearColor = function ( target ) {
  14183. if ( target === undefined ) {
  14184. console.warn( 'WebGLRenderer: .getClearColor() now requires a Color as an argument' );
  14185. target = new Color();
  14186. }
  14187. return target.copy( background.getClearColor() );
  14188. };
  14189. this.setClearColor = function () {
  14190. background.setClearColor.apply( background, arguments );
  14191. };
  14192. this.getClearAlpha = function () {
  14193. return background.getClearAlpha();
  14194. };
  14195. this.setClearAlpha = function () {
  14196. background.setClearAlpha.apply( background, arguments );
  14197. };
  14198. this.clear = function ( color, depth, stencil ) {
  14199. let bits = 0;
  14200. if ( color === undefined || color ) bits |= 16384;
  14201. if ( depth === undefined || depth ) bits |= 256;
  14202. if ( stencil === undefined || stencil ) bits |= 1024;
  14203. _gl.clear( bits );
  14204. };
  14205. this.clearColor = function () {
  14206. this.clear( true, false, false );
  14207. };
  14208. this.clearDepth = function () {
  14209. this.clear( false, true, false );
  14210. };
  14211. this.clearStencil = function () {
  14212. this.clear( false, false, true );
  14213. };
  14214. //
  14215. this.dispose = function () {
  14216. _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
  14217. _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
  14218. renderLists.dispose();
  14219. renderStates.dispose();
  14220. properties.dispose();
  14221. cubemaps.dispose();
  14222. objects.dispose();
  14223. bindingStates.dispose();
  14224. xr.dispose();
  14225. animation.stop();
  14226. };
  14227. // Events
  14228. function onContextLost( event ) {
  14229. event.preventDefault();
  14230. console.log( 'THREE.WebGLRenderer: Context Lost.' );
  14231. _isContextLost = true;
  14232. }
  14233. function onContextRestore( /* event */ ) {
  14234. console.log( 'THREE.WebGLRenderer: Context Restored.' );
  14235. _isContextLost = false;
  14236. initGLContext();
  14237. }
  14238. function onMaterialDispose( event ) {
  14239. const material = event.target;
  14240. material.removeEventListener( 'dispose', onMaterialDispose );
  14241. deallocateMaterial( material );
  14242. }
  14243. // Buffer deallocation
  14244. function deallocateMaterial( material ) {
  14245. releaseMaterialProgramReference( material );
  14246. properties.remove( material );
  14247. }
  14248. function releaseMaterialProgramReference( material ) {
  14249. const programInfo = properties.get( material ).program;
  14250. if ( programInfo !== undefined ) {
  14251. programCache.releaseProgram( programInfo );
  14252. }
  14253. }
  14254. // Buffer rendering
  14255. function renderObjectImmediate( object, program ) {
  14256. object.render( function ( object ) {
  14257. _this.renderBufferImmediate( object, program );
  14258. } );
  14259. }
  14260. this.renderBufferImmediate = function ( object, program ) {
  14261. bindingStates.initAttributes();
  14262. const buffers = properties.get( object );
  14263. if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
  14264. if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
  14265. if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
  14266. if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
  14267. const programAttributes = program.getAttributes();
  14268. if ( object.hasPositions ) {
  14269. _gl.bindBuffer( 34962, buffers.position );
  14270. _gl.bufferData( 34962, object.positionArray, 35048 );
  14271. bindingStates.enableAttribute( programAttributes.position );
  14272. _gl.vertexAttribPointer( programAttributes.position, 3, 5126, false, 0, 0 );
  14273. }
  14274. if ( object.hasNormals ) {
  14275. _gl.bindBuffer( 34962, buffers.normal );
  14276. _gl.bufferData( 34962, object.normalArray, 35048 );
  14277. bindingStates.enableAttribute( programAttributes.normal );
  14278. _gl.vertexAttribPointer( programAttributes.normal, 3, 5126, false, 0, 0 );
  14279. }
  14280. if ( object.hasUvs ) {
  14281. _gl.bindBuffer( 34962, buffers.uv );
  14282. _gl.bufferData( 34962, object.uvArray, 35048 );
  14283. bindingStates.enableAttribute( programAttributes.uv );
  14284. _gl.vertexAttribPointer( programAttributes.uv, 2, 5126, false, 0, 0 );
  14285. }
  14286. if ( object.hasColors ) {
  14287. _gl.bindBuffer( 34962, buffers.color );
  14288. _gl.bufferData( 34962, object.colorArray, 35048 );
  14289. bindingStates.enableAttribute( programAttributes.color );
  14290. _gl.vertexAttribPointer( programAttributes.color, 3, 5126, false, 0, 0 );
  14291. }
  14292. bindingStates.disableUnusedAttributes();
  14293. _gl.drawArrays( 4, 0, object.count );
  14294. object.count = 0;
  14295. };
  14296. this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
  14297. if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
  14298. const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
  14299. const program = setProgram( camera, scene, material, object );
  14300. state.setMaterial( material, frontFaceCW );
  14301. //
  14302. let index = geometry.index;
  14303. const position = geometry.attributes.position;
  14304. //
  14305. if ( index === null ) {
  14306. if ( position === undefined || position.count === 0 ) return;
  14307. } else if ( index.count === 0 ) {
  14308. return;
  14309. }
  14310. //
  14311. let rangeFactor = 1;
  14312. if ( material.wireframe === true ) {
  14313. index = geometries.getWireframeAttribute( geometry );
  14314. rangeFactor = 2;
  14315. }
  14316. if ( material.morphTargets || material.morphNormals ) {
  14317. morphtargets.update( object, geometry, material, program );
  14318. }
  14319. bindingStates.setup( object, material, program, geometry, index );
  14320. let attribute;
  14321. let renderer = bufferRenderer;
  14322. if ( index !== null ) {
  14323. attribute = attributes.get( index );
  14324. renderer = indexedBufferRenderer;
  14325. renderer.setIndex( attribute );
  14326. }
  14327. //
  14328. const dataCount = ( index !== null ) ? index.count : position.count;
  14329. const rangeStart = geometry.drawRange.start * rangeFactor;
  14330. const rangeCount = geometry.drawRange.count * rangeFactor;
  14331. const groupStart = group !== null ? group.start * rangeFactor : 0;
  14332. const groupCount = group !== null ? group.count * rangeFactor : Infinity;
  14333. const drawStart = Math.max( rangeStart, groupStart );
  14334. const drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
  14335. const drawCount = Math.max( 0, drawEnd - drawStart + 1 );
  14336. if ( drawCount === 0 ) return;
  14337. //
  14338. if ( object.isMesh ) {
  14339. if ( material.wireframe === true ) {
  14340. state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
  14341. renderer.setMode( 1 );
  14342. } else {
  14343. renderer.setMode( 4 );
  14344. }
  14345. } else if ( object.isLine ) {
  14346. let lineWidth = material.linewidth;
  14347. if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
  14348. state.setLineWidth( lineWidth * getTargetPixelRatio() );
  14349. if ( object.isLineSegments ) {
  14350. renderer.setMode( 1 );
  14351. } else if ( object.isLineLoop ) {
  14352. renderer.setMode( 2 );
  14353. } else {
  14354. renderer.setMode( 3 );
  14355. }
  14356. } else if ( object.isPoints ) {
  14357. renderer.setMode( 0 );
  14358. } else if ( object.isSprite ) {
  14359. renderer.setMode( 4 );
  14360. }
  14361. if ( object.isInstancedMesh ) {
  14362. renderer.renderInstances( drawStart, drawCount, object.count );
  14363. } else if ( geometry.isInstancedBufferGeometry ) {
  14364. const instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
  14365. renderer.renderInstances( drawStart, drawCount, instanceCount );
  14366. } else {
  14367. renderer.render( drawStart, drawCount );
  14368. }
  14369. };
  14370. // Compile
  14371. this.compile = function ( scene, camera ) {
  14372. currentRenderState = renderStates.get( scene );
  14373. currentRenderState.init();
  14374. scene.traverseVisible( function ( object ) {
  14375. if ( object.isLight && object.layers.test( camera.layers ) ) {
  14376. currentRenderState.pushLight( object );
  14377. if ( object.castShadow ) {
  14378. currentRenderState.pushShadow( object );
  14379. }
  14380. }
  14381. } );
  14382. currentRenderState.setupLights();
  14383. const compiled = new WeakMap();
  14384. scene.traverse( function ( object ) {
  14385. const material = object.material;
  14386. if ( material ) {
  14387. if ( Array.isArray( material ) ) {
  14388. for ( let i = 0; i < material.length; i ++ ) {
  14389. const material2 = material[ i ];
  14390. if ( compiled.has( material2 ) === false ) {
  14391. initMaterial( material2, scene, object );
  14392. compiled.set( material2 );
  14393. }
  14394. }
  14395. } else if ( compiled.has( material ) === false ) {
  14396. initMaterial( material, scene, object );
  14397. compiled.set( material );
  14398. }
  14399. }
  14400. } );
  14401. };
  14402. // Animation Loop
  14403. let onAnimationFrameCallback = null;
  14404. function onAnimationFrame( time ) {
  14405. if ( xr.isPresenting ) return;
  14406. if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
  14407. }
  14408. const animation = new WebGLAnimation();
  14409. animation.setAnimationLoop( onAnimationFrame );
  14410. if ( typeof window !== 'undefined' ) animation.setContext( window );
  14411. this.setAnimationLoop = function ( callback ) {
  14412. onAnimationFrameCallback = callback;
  14413. xr.setAnimationLoop( callback );
  14414. ( callback === null ) ? animation.stop() : animation.start();
  14415. };
  14416. // Rendering
  14417. this.render = function ( scene, camera ) {
  14418. let renderTarget, forceClear;
  14419. if ( arguments[ 2 ] !== undefined ) {
  14420. console.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
  14421. renderTarget = arguments[ 2 ];
  14422. }
  14423. if ( arguments[ 3 ] !== undefined ) {
  14424. console.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );
  14425. forceClear = arguments[ 3 ];
  14426. }
  14427. if ( camera !== undefined && camera.isCamera !== true ) {
  14428. console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
  14429. return;
  14430. }
  14431. if ( _isContextLost === true ) return;
  14432. // reset caching for this frame
  14433. bindingStates.resetDefaultState();
  14434. _currentMaterialId = - 1;
  14435. _currentCamera = null;
  14436. // update scene graph
  14437. if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
  14438. // update camera matrices and frustum
  14439. if ( camera.parent === null ) camera.updateMatrixWorld();
  14440. if ( xr.enabled === true && xr.isPresenting === true ) {
  14441. camera = xr.getCamera( camera );
  14442. }
  14443. //
  14444. if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );
  14445. currentRenderState = renderStates.get( scene, renderStateStack.length );
  14446. currentRenderState.init();
  14447. renderStateStack.push( currentRenderState );
  14448. _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
  14449. _frustum.setFromProjectionMatrix( _projScreenMatrix );
  14450. _localClippingEnabled = this.localClippingEnabled;
  14451. _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
  14452. currentRenderList = renderLists.get( scene, camera );
  14453. currentRenderList.init();
  14454. projectObject( scene, camera, 0, _this.sortObjects );
  14455. currentRenderList.finish();
  14456. if ( _this.sortObjects === true ) {
  14457. currentRenderList.sort( _opaqueSort, _transparentSort );
  14458. }
  14459. //
  14460. if ( _clippingEnabled === true ) clipping.beginShadows();
  14461. const shadowsArray = currentRenderState.state.shadowsArray;
  14462. shadowMap.render( shadowsArray, scene, camera );
  14463. currentRenderState.setupLights();
  14464. currentRenderState.setupLightsView( camera );
  14465. if ( _clippingEnabled === true ) clipping.endShadows();
  14466. //
  14467. if ( this.info.autoReset === true ) this.info.reset();
  14468. if ( renderTarget !== undefined ) {
  14469. this.setRenderTarget( renderTarget );
  14470. }
  14471. //
  14472. background.render( currentRenderList, scene, camera, forceClear );
  14473. // render scene
  14474. const opaqueObjects = currentRenderList.opaque;
  14475. const transparentObjects = currentRenderList.transparent;
  14476. if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
  14477. if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
  14478. //
  14479. if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
  14480. //
  14481. if ( _currentRenderTarget !== null ) {
  14482. // Generate mipmap if we're using any kind of mipmap filtering
  14483. textures.updateRenderTargetMipmap( _currentRenderTarget );
  14484. // resolve multisample renderbuffers to a single-sample texture if necessary
  14485. textures.updateMultisampleRenderTarget( _currentRenderTarget );
  14486. }
  14487. // Ensure depth buffer writing is enabled so it can be cleared on next render
  14488. state.buffers.depth.setTest( true );
  14489. state.buffers.depth.setMask( true );
  14490. state.buffers.color.setMask( true );
  14491. state.setPolygonOffset( false );
  14492. // _gl.finish();
  14493. renderStateStack.pop();
  14494. if ( renderStateStack.length > 0 ) {
  14495. currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
  14496. } else {
  14497. currentRenderState = null;
  14498. }
  14499. currentRenderList = null;
  14500. };
  14501. function projectObject( object, camera, groupOrder, sortObjects ) {
  14502. if ( object.visible === false ) return;
  14503. const visible = object.layers.test( camera.layers );
  14504. if ( visible ) {
  14505. if ( object.isGroup ) {
  14506. groupOrder = object.renderOrder;
  14507. } else if ( object.isLOD ) {
  14508. if ( object.autoUpdate === true ) object.update( camera );
  14509. } else if ( object.isLight ) {
  14510. currentRenderState.pushLight( object );
  14511. if ( object.castShadow ) {
  14512. currentRenderState.pushShadow( object );
  14513. }
  14514. } else if ( object.isSprite ) {
  14515. if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
  14516. if ( sortObjects ) {
  14517. _vector3.setFromMatrixPosition( object.matrixWorld )
  14518. .applyMatrix4( _projScreenMatrix );
  14519. }
  14520. const geometry = objects.update( object );
  14521. const material = object.material;
  14522. if ( material.visible ) {
  14523. currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
  14524. }
  14525. }
  14526. } else if ( object.isImmediateRenderObject ) {
  14527. if ( sortObjects ) {
  14528. _vector3.setFromMatrixPosition( object.matrixWorld )
  14529. .applyMatrix4( _projScreenMatrix );
  14530. }
  14531. currentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );
  14532. } else if ( object.isMesh || object.isLine || object.isPoints ) {
  14533. if ( object.isSkinnedMesh ) {
  14534. // update skeleton only once in a frame
  14535. if ( object.skeleton.frame !== info.render.frame ) {
  14536. object.skeleton.update();
  14537. object.skeleton.frame = info.render.frame;
  14538. }
  14539. }
  14540. if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
  14541. if ( sortObjects ) {
  14542. _vector3.setFromMatrixPosition( object.matrixWorld )
  14543. .applyMatrix4( _projScreenMatrix );
  14544. }
  14545. const geometry = objects.update( object );
  14546. const material = object.material;
  14547. if ( Array.isArray( material ) ) {
  14548. const groups = geometry.groups;
  14549. for ( let i = 0, l = groups.length; i < l; i ++ ) {
  14550. const group = groups[ i ];
  14551. const groupMaterial = material[ group.materialIndex ];
  14552. if ( groupMaterial && groupMaterial.visible ) {
  14553. currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
  14554. }
  14555. }
  14556. } else if ( material.visible ) {
  14557. currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
  14558. }
  14559. }
  14560. }
  14561. }
  14562. const children = object.children;
  14563. for ( let i = 0, l = children.length; i < l; i ++ ) {
  14564. projectObject( children[ i ], camera, groupOrder, sortObjects );
  14565. }
  14566. }
  14567. function renderObjects( renderList, scene, camera ) {
  14568. const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
  14569. for ( let i = 0, l = renderList.length; i < l; i ++ ) {
  14570. const renderItem = renderList[ i ];
  14571. const object = renderItem.object;
  14572. const geometry = renderItem.geometry;
  14573. const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
  14574. const group = renderItem.group;
  14575. if ( camera.isArrayCamera ) {
  14576. const cameras = camera.cameras;
  14577. for ( let j = 0, jl = cameras.length; j < jl; j ++ ) {
  14578. const camera2 = cameras[ j ];
  14579. if ( object.layers.test( camera2.layers ) ) {
  14580. state.viewport( _currentViewport.copy( camera2.viewport ) );
  14581. currentRenderState.setupLightsView( camera2 );
  14582. renderObject( object, scene, camera2, geometry, material, group );
  14583. }
  14584. }
  14585. } else {
  14586. renderObject( object, scene, camera, geometry, material, group );
  14587. }
  14588. }
  14589. }
  14590. function renderObject( object, scene, camera, geometry, material, group ) {
  14591. object.onBeforeRender( _this, scene, camera, geometry, material, group );
  14592. object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
  14593. object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
  14594. if ( object.isImmediateRenderObject ) {
  14595. const program = setProgram( camera, scene, material, object );
  14596. state.setMaterial( material );
  14597. bindingStates.reset();
  14598. renderObjectImmediate( object, program );
  14599. } else {
  14600. _this.renderBufferDirect( camera, scene, geometry, material, object, group );
  14601. }
  14602. object.onAfterRender( _this, scene, camera, geometry, material, group );
  14603. }
  14604. function initMaterial( material, scene, object ) {
  14605. if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
  14606. const materialProperties = properties.get( material );
  14607. const lights = currentRenderState.state.lights;
  14608. const shadowsArray = currentRenderState.state.shadowsArray;
  14609. const lightsStateVersion = lights.state.version;
  14610. const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
  14611. const programCacheKey = programCache.getProgramCacheKey( parameters );
  14612. let program = materialProperties.program;
  14613. let programChange = true;
  14614. if ( program === undefined ) {
  14615. // new material
  14616. material.addEventListener( 'dispose', onMaterialDispose );
  14617. } else if ( program.cacheKey !== programCacheKey ) {
  14618. // changed glsl or parameters
  14619. releaseMaterialProgramReference( material );
  14620. } else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {
  14621. programChange = false;
  14622. } else if ( parameters.shaderID !== undefined ) {
  14623. // same glsl and uniform list, envMap still needs the update here to avoid a frame-late effect
  14624. const environment = material.isMeshStandardMaterial ? scene.environment : null;
  14625. materialProperties.envMap = cubemaps.get( material.envMap || environment );
  14626. return;
  14627. } else {
  14628. // only rebuild uniform list
  14629. programChange = false;
  14630. }
  14631. if ( programChange ) {
  14632. parameters.uniforms = programCache.getUniforms( material );
  14633. material.onBeforeCompile( parameters, _this );
  14634. program = programCache.acquireProgram( parameters, programCacheKey );
  14635. materialProperties.program = program;
  14636. materialProperties.uniforms = parameters.uniforms;
  14637. materialProperties.outputEncoding = parameters.outputEncoding;
  14638. }
  14639. const uniforms = materialProperties.uniforms;
  14640. if ( ! material.isShaderMaterial &&
  14641. ! material.isRawShaderMaterial ||
  14642. material.clipping === true ) {
  14643. materialProperties.numClippingPlanes = clipping.numPlanes;
  14644. materialProperties.numIntersection = clipping.numIntersection;
  14645. uniforms.clippingPlanes = clipping.uniform;
  14646. }
  14647. materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
  14648. materialProperties.fog = scene.fog;
  14649. materialProperties.envMap = cubemaps.get( material.envMap || materialProperties.environment );
  14650. // store the light setup it was created for
  14651. materialProperties.needsLights = materialNeedsLights( material );
  14652. materialProperties.lightsStateVersion = lightsStateVersion;
  14653. if ( materialProperties.needsLights ) {
  14654. // wire up the material to this renderer's lighting state
  14655. uniforms.ambientLightColor.value = lights.state.ambient;
  14656. uniforms.lightProbe.value = lights.state.probe;
  14657. uniforms.directionalLights.value = lights.state.directional;
  14658. uniforms.directionalLightShadows.value = lights.state.directionalShadow;
  14659. uniforms.spotLights.value = lights.state.spot;
  14660. uniforms.spotLightShadows.value = lights.state.spotShadow;
  14661. uniforms.rectAreaLights.value = lights.state.rectArea;
  14662. uniforms.ltc_1.value = lights.state.rectAreaLTC1;
  14663. uniforms.ltc_2.value = lights.state.rectAreaLTC2;
  14664. uniforms.pointLights.value = lights.state.point;
  14665. uniforms.pointLightShadows.value = lights.state.pointShadow;
  14666. uniforms.hemisphereLights.value = lights.state.hemi;
  14667. uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
  14668. uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
  14669. uniforms.spotShadowMap.value = lights.state.spotShadowMap;
  14670. uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
  14671. uniforms.pointShadowMap.value = lights.state.pointShadowMap;
  14672. uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
  14673. // TODO (abelnation): add area lights shadow info to uniforms
  14674. }
  14675. const progUniforms = materialProperties.program.getUniforms();
  14676. const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
  14677. materialProperties.uniformsList = uniformsList;
  14678. }
  14679. function setProgram( camera, scene, material, object ) {
  14680. if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
  14681. textures.resetTextureUnits();
  14682. const fog = scene.fog;
  14683. const environment = material.isMeshStandardMaterial ? scene.environment : null;
  14684. const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;
  14685. const envMap = cubemaps.get( material.envMap || environment );
  14686. const materialProperties = properties.get( material );
  14687. const lights = currentRenderState.state.lights;
  14688. if ( _clippingEnabled === true ) {
  14689. if ( _localClippingEnabled === true || camera !== _currentCamera ) {
  14690. const useCache =
  14691. camera === _currentCamera &&
  14692. material.id === _currentMaterialId;
  14693. // we might want to call this function with some ClippingGroup
  14694. // object instead of the material, once it becomes feasible
  14695. // (#8465, #8379)
  14696. clipping.setState( material, camera, useCache );
  14697. }
  14698. }
  14699. if ( material.version === materialProperties.__version ) {
  14700. if ( material.fog && materialProperties.fog !== fog ) {
  14701. initMaterial( material, scene, object );
  14702. } else if ( materialProperties.environment !== environment ) {
  14703. initMaterial( material, scene, object );
  14704. } else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
  14705. initMaterial( material, scene, object );
  14706. } else if ( materialProperties.numClippingPlanes !== undefined &&
  14707. ( materialProperties.numClippingPlanes !== clipping.numPlanes ||
  14708. materialProperties.numIntersection !== clipping.numIntersection ) ) {
  14709. initMaterial( material, scene, object );
  14710. } else if ( materialProperties.outputEncoding !== encoding ) {
  14711. initMaterial( material, scene, object );
  14712. } else if ( materialProperties.envMap !== envMap ) {
  14713. initMaterial( material, scene, object );
  14714. }
  14715. } else {
  14716. initMaterial( material, scene, object );
  14717. materialProperties.__version = material.version;
  14718. }
  14719. let refreshProgram = false;
  14720. let refreshMaterial = false;
  14721. let refreshLights = false;
  14722. const program = materialProperties.program,
  14723. p_uniforms = program.getUniforms(),
  14724. m_uniforms = materialProperties.uniforms;
  14725. if ( state.useProgram( program.program ) ) {
  14726. refreshProgram = true;
  14727. refreshMaterial = true;
  14728. refreshLights = true;
  14729. }
  14730. if ( material.id !== _currentMaterialId ) {
  14731. _currentMaterialId = material.id;
  14732. refreshMaterial = true;
  14733. }
  14734. if ( refreshProgram || _currentCamera !== camera ) {
  14735. p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
  14736. if ( capabilities.logarithmicDepthBuffer ) {
  14737. p_uniforms.setValue( _gl, 'logDepthBufFC',
  14738. 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
  14739. }
  14740. if ( _currentCamera !== camera ) {
  14741. _currentCamera = camera;
  14742. // lighting uniforms depend on the camera so enforce an update
  14743. // now, in case this material supports lights - or later, when
  14744. // the next material that does gets activated:
  14745. refreshMaterial = true; // set to true on material change
  14746. refreshLights = true; // remains set until update done
  14747. }
  14748. // load material specific uniforms
  14749. // (shader material also gets them for the sake of genericity)
  14750. if ( material.isShaderMaterial ||
  14751. material.isMeshPhongMaterial ||
  14752. material.isMeshToonMaterial ||
  14753. material.isMeshStandardMaterial ||
  14754. material.envMap ) {
  14755. const uCamPos = p_uniforms.map.cameraPosition;
  14756. if ( uCamPos !== undefined ) {
  14757. uCamPos.setValue( _gl,
  14758. _vector3.setFromMatrixPosition( camera.matrixWorld ) );
  14759. }
  14760. }
  14761. if ( material.isMeshPhongMaterial ||
  14762. material.isMeshToonMaterial ||
  14763. material.isMeshLambertMaterial ||
  14764. material.isMeshBasicMaterial ||
  14765. material.isMeshStandardMaterial ||
  14766. material.isShaderMaterial ) {
  14767. p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
  14768. }
  14769. if ( material.isMeshPhongMaterial ||
  14770. material.isMeshToonMaterial ||
  14771. material.isMeshLambertMaterial ||
  14772. material.isMeshBasicMaterial ||
  14773. material.isMeshStandardMaterial ||
  14774. material.isShaderMaterial ||
  14775. material.isShadowMaterial ||
  14776. material.skinning ) {
  14777. p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
  14778. }
  14779. }
  14780. // skinning uniforms must be set even if material didn't change
  14781. // auto-setting of texture unit for bone texture must go before other textures
  14782. // otherwise textures used for skinning can take over texture units reserved for other material textures
  14783. if ( material.skinning ) {
  14784. p_uniforms.setOptional( _gl, object, 'bindMatrix' );
  14785. p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
  14786. const skeleton = object.skeleton;
  14787. if ( skeleton ) {
  14788. const bones = skeleton.bones;
  14789. if ( capabilities.floatVertexTextures ) {
  14790. if ( skeleton.boneTexture === null ) {
  14791. // layout (1 matrix = 4 pixels)
  14792. // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
  14793. // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
  14794. // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
  14795. // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
  14796. // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
  14797. let size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
  14798. size = MathUtils$1.ceilPowerOfTwo( size );
  14799. size = Math.max( size, 4 );
  14800. const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
  14801. boneMatrices.set( skeleton.boneMatrices ); // copy current values
  14802. const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
  14803. skeleton.boneMatrices = boneMatrices;
  14804. skeleton.boneTexture = boneTexture;
  14805. skeleton.boneTextureSize = size;
  14806. }
  14807. p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
  14808. p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
  14809. } else {
  14810. p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
  14811. }
  14812. }
  14813. }
  14814. if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
  14815. materialProperties.receiveShadow = object.receiveShadow;
  14816. p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
  14817. }
  14818. if ( refreshMaterial ) {
  14819. p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
  14820. if ( materialProperties.needsLights ) {
  14821. // the current material requires lighting info
  14822. // note: all lighting uniforms are always set correctly
  14823. // they simply reference the renderer's state for their
  14824. // values
  14825. //
  14826. // use the current material's .needsUpdate flags to set
  14827. // the GL state when required
  14828. markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
  14829. }
  14830. // refresh uniforms common to several materials
  14831. if ( fog && material.fog ) {
  14832. materials.refreshFogUniforms( m_uniforms, fog );
  14833. }
  14834. materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height );
  14835. WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
  14836. }
  14837. if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
  14838. WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
  14839. material.uniformsNeedUpdate = false;
  14840. }
  14841. if ( material.isSpriteMaterial ) {
  14842. p_uniforms.setValue( _gl, 'center', object.center );
  14843. }
  14844. // common matrices
  14845. p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
  14846. p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
  14847. p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
  14848. return program;
  14849. }
  14850. // If uniforms are marked as clean, they don't need to be loaded to the GPU.
  14851. function markUniformsLightsNeedsUpdate( uniforms, value ) {
  14852. uniforms.ambientLightColor.needsUpdate = value;
  14853. uniforms.lightProbe.needsUpdate = value;
  14854. uniforms.directionalLights.needsUpdate = value;
  14855. uniforms.directionalLightShadows.needsUpdate = value;
  14856. uniforms.pointLights.needsUpdate = value;
  14857. uniforms.pointLightShadows.needsUpdate = value;
  14858. uniforms.spotLights.needsUpdate = value;
  14859. uniforms.spotLightShadows.needsUpdate = value;
  14860. uniforms.rectAreaLights.needsUpdate = value;
  14861. uniforms.hemisphereLights.needsUpdate = value;
  14862. }
  14863. function materialNeedsLights( material ) {
  14864. return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
  14865. material.isMeshStandardMaterial || material.isShadowMaterial ||
  14866. ( material.isShaderMaterial && material.lights === true );
  14867. }
  14868. //
  14869. this.setFramebuffer = function ( value ) {
  14870. if ( _framebuffer !== value && _currentRenderTarget === null ) _gl.bindFramebuffer( 36160, value );
  14871. _framebuffer = value;
  14872. };
  14873. this.getActiveCubeFace = function () {
  14874. return _currentActiveCubeFace;
  14875. };
  14876. this.getActiveMipmapLevel = function () {
  14877. return _currentActiveMipmapLevel;
  14878. };
  14879. this.getRenderList = function () {
  14880. return currentRenderList;
  14881. };
  14882. this.setRenderList = function ( renderList ) {
  14883. currentRenderList = renderList;
  14884. };
  14885. this.getRenderTarget = function () {
  14886. return _currentRenderTarget;
  14887. };
  14888. this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
  14889. _currentRenderTarget = renderTarget;
  14890. _currentActiveCubeFace = activeCubeFace;
  14891. _currentActiveMipmapLevel = activeMipmapLevel;
  14892. if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
  14893. textures.setupRenderTarget( renderTarget );
  14894. }
  14895. let framebuffer = _framebuffer;
  14896. let isCube = false;
  14897. if ( renderTarget ) {
  14898. const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
  14899. if ( renderTarget.isWebGLCubeRenderTarget ) {
  14900. framebuffer = __webglFramebuffer[ activeCubeFace ];
  14901. isCube = true;
  14902. } else if ( renderTarget.isWebGLMultisampleRenderTarget ) {
  14903. framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
  14904. } else {
  14905. framebuffer = __webglFramebuffer;
  14906. }
  14907. _currentViewport.copy( renderTarget.viewport );
  14908. _currentScissor.copy( renderTarget.scissor );
  14909. _currentScissorTest = renderTarget.scissorTest;
  14910. } else {
  14911. _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
  14912. _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
  14913. _currentScissorTest = _scissorTest;
  14914. }
  14915. if ( _currentFramebuffer !== framebuffer ) {
  14916. _gl.bindFramebuffer( 36160, framebuffer );
  14917. _currentFramebuffer = framebuffer;
  14918. }
  14919. state.viewport( _currentViewport );
  14920. state.scissor( _currentScissor );
  14921. state.setScissorTest( _currentScissorTest );
  14922. if ( isCube ) {
  14923. const textureProperties = properties.get( renderTarget.texture );
  14924. _gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
  14925. }
  14926. };
  14927. this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
  14928. if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
  14929. console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
  14930. return;
  14931. }
  14932. let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
  14933. if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
  14934. framebuffer = framebuffer[ activeCubeFaceIndex ];
  14935. }
  14936. if ( framebuffer ) {
  14937. let restore = false;
  14938. if ( framebuffer !== _currentFramebuffer ) {
  14939. _gl.bindFramebuffer( 36160, framebuffer );
  14940. restore = true;
  14941. }
  14942. try {
  14943. const texture = renderTarget.texture;
  14944. const textureFormat = texture.format;
  14945. const textureType = texture.type;
  14946. if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {
  14947. console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
  14948. return;
  14949. }
  14950. if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)
  14951. ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
  14952. ! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {
  14953. console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
  14954. return;
  14955. }
  14956. if ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {
  14957. // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
  14958. if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
  14959. _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
  14960. }
  14961. } else {
  14962. console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
  14963. }
  14964. } finally {
  14965. if ( restore ) {
  14966. _gl.bindFramebuffer( 36160, _currentFramebuffer );
  14967. }
  14968. }
  14969. }
  14970. };
  14971. this.copyFramebufferToTexture = function ( position, texture, level = 0 ) {
  14972. const levelScale = Math.pow( 2, - level );
  14973. const width = Math.floor( texture.image.width * levelScale );
  14974. const height = Math.floor( texture.image.height * levelScale );
  14975. const glFormat = utils.convert( texture.format );
  14976. textures.setTexture2D( texture, 0 );
  14977. _gl.copyTexImage2D( 3553, level, glFormat, position.x, position.y, width, height, 0 );
  14978. state.unbindTexture();
  14979. };
  14980. this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) {
  14981. const width = srcTexture.image.width;
  14982. const height = srcTexture.image.height;
  14983. const glFormat = utils.convert( dstTexture.format );
  14984. const glType = utils.convert( dstTexture.type );
  14985. textures.setTexture2D( dstTexture, 0 );
  14986. // As another texture upload may have changed pixelStorei
  14987. // parameters, make sure they are correct for the dstTexture
  14988. _gl.pixelStorei( 37440, dstTexture.flipY );
  14989. _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha );
  14990. _gl.pixelStorei( 3317, dstTexture.unpackAlignment );
  14991. if ( srcTexture.isDataTexture ) {
  14992. _gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
  14993. } else {
  14994. if ( srcTexture.isCompressedTexture ) {
  14995. _gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
  14996. } else {
  14997. _gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image );
  14998. }
  14999. }
  15000. // Generate mipmaps only when copying level 0
  15001. if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 );
  15002. state.unbindTexture();
  15003. };
  15004. this.initTexture = function ( texture ) {
  15005. textures.setTexture2D( texture, 0 );
  15006. state.unbindTexture();
  15007. };
  15008. this.resetState = function () {
  15009. state.reset();
  15010. bindingStates.reset();
  15011. };
  15012. if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
  15013. __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
  15014. }
  15015. }
  15016. function WebGL1Renderer( parameters ) {
  15017. WebGLRenderer.call( this, parameters );
  15018. }
  15019. WebGL1Renderer.prototype = Object.assign( Object.create( WebGLRenderer.prototype ), {
  15020. constructor: WebGL1Renderer,
  15021. isWebGL1Renderer: true
  15022. } );
  15023. class FogExp2 {
  15024. constructor( color, density ) {
  15025. Object.defineProperty( this, 'isFogExp2', { value: true } );
  15026. this.name = '';
  15027. this.color = new Color( color );
  15028. this.density = ( density !== undefined ) ? density : 0.00025;
  15029. }
  15030. clone() {
  15031. return new FogExp2( this.color, this.density );
  15032. }
  15033. toJSON( /* meta */ ) {
  15034. return {
  15035. type: 'FogExp2',
  15036. color: this.color.getHex(),
  15037. density: this.density
  15038. };
  15039. }
  15040. }
  15041. class Fog {
  15042. constructor( color, near, far ) {
  15043. Object.defineProperty( this, 'isFog', { value: true } );
  15044. this.name = '';
  15045. this.color = new Color( color );
  15046. this.near = ( near !== undefined ) ? near : 1;
  15047. this.far = ( far !== undefined ) ? far : 1000;
  15048. }
  15049. clone() {
  15050. return new Fog( this.color, this.near, this.far );
  15051. }
  15052. toJSON( /* meta */ ) {
  15053. return {
  15054. type: 'Fog',
  15055. color: this.color.getHex(),
  15056. near: this.near,
  15057. far: this.far
  15058. };
  15059. }
  15060. }
  15061. class Scene extends Object3D {
  15062. constructor() {
  15063. super();
  15064. Object.defineProperty( this, 'isScene', { value: true } );
  15065. this.type = 'Scene';
  15066. this.background = null;
  15067. this.environment = null;
  15068. this.fog = null;
  15069. this.overrideMaterial = null;
  15070. this.autoUpdate = true; // checked by the renderer
  15071. if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
  15072. __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
  15073. }
  15074. }
  15075. copy( source, recursive ) {
  15076. super.copy( source, recursive );
  15077. if ( source.background !== null ) this.background = source.background.clone();
  15078. if ( source.environment !== null ) this.environment = source.environment.clone();
  15079. if ( source.fog !== null ) this.fog = source.fog.clone();
  15080. if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
  15081. this.autoUpdate = source.autoUpdate;
  15082. this.matrixAutoUpdate = source.matrixAutoUpdate;
  15083. return this;
  15084. }
  15085. toJSON( meta ) {
  15086. const data = super.toJSON( meta );
  15087. if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
  15088. if ( this.environment !== null ) data.object.environment = this.environment.toJSON( meta );
  15089. if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
  15090. return data;
  15091. }
  15092. }
  15093. function InterleavedBuffer( array, stride ) {
  15094. this.array = array;
  15095. this.stride = stride;
  15096. this.count = array !== undefined ? array.length / stride : 0;
  15097. this.usage = StaticDrawUsage;
  15098. this.updateRange = { offset: 0, count: - 1 };
  15099. this.version = 0;
  15100. this.uuid = MathUtils$1.generateUUID();
  15101. }
  15102. Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
  15103. set: function ( value ) {
  15104. if ( value === true ) this.version ++;
  15105. }
  15106. } );
  15107. Object.assign( InterleavedBuffer.prototype, {
  15108. isInterleavedBuffer: true,
  15109. onUploadCallback: function () {},
  15110. setUsage: function ( value ) {
  15111. this.usage = value;
  15112. return this;
  15113. },
  15114. copy: function ( source ) {
  15115. this.array = new source.array.constructor( source.array );
  15116. this.count = source.count;
  15117. this.stride = source.stride;
  15118. this.usage = source.usage;
  15119. return this;
  15120. },
  15121. copyAt: function ( index1, attribute, index2 ) {
  15122. index1 *= this.stride;
  15123. index2 *= attribute.stride;
  15124. for ( let i = 0, l = this.stride; i < l; i ++ ) {
  15125. this.array[ index1 + i ] = attribute.array[ index2 + i ];
  15126. }
  15127. return this;
  15128. },
  15129. set: function ( value, offset = 0 ) {
  15130. this.array.set( value, offset );
  15131. return this;
  15132. },
  15133. clone: function ( data ) {
  15134. if ( data.arrayBuffers === undefined ) {
  15135. data.arrayBuffers = {};
  15136. }
  15137. if ( this.array.buffer._uuid === undefined ) {
  15138. this.array.buffer._uuid = MathUtils$1.generateUUID();
  15139. }
  15140. if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
  15141. data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
  15142. }
  15143. const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
  15144. const ib = new InterleavedBuffer( array, this.stride );
  15145. ib.setUsage( this.usage );
  15146. return ib;
  15147. },
  15148. onUpload: function ( callback ) {
  15149. this.onUploadCallback = callback;
  15150. return this;
  15151. },
  15152. toJSON: function ( data ) {
  15153. if ( data.arrayBuffers === undefined ) {
  15154. data.arrayBuffers = {};
  15155. }
  15156. // generate UUID for array buffer if necessary
  15157. if ( this.array.buffer._uuid === undefined ) {
  15158. this.array.buffer._uuid = MathUtils$1.generateUUID();
  15159. }
  15160. if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
  15161. data.arrayBuffers[ this.array.buffer._uuid ] = Array.prototype.slice.call( new Uint32Array( this.array.buffer ) );
  15162. }
  15163. //
  15164. return {
  15165. uuid: this.uuid,
  15166. buffer: this.array.buffer._uuid,
  15167. type: this.array.constructor.name,
  15168. stride: this.stride
  15169. };
  15170. }
  15171. } );
  15172. const _vector$6 = new Vector3();
  15173. function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
  15174. this.name = '';
  15175. this.data = interleavedBuffer;
  15176. this.itemSize = itemSize;
  15177. this.offset = offset;
  15178. this.normalized = normalized === true;
  15179. }
  15180. Object.defineProperties( InterleavedBufferAttribute.prototype, {
  15181. count: {
  15182. get: function () {
  15183. return this.data.count;
  15184. }
  15185. },
  15186. array: {
  15187. get: function () {
  15188. return this.data.array;
  15189. }
  15190. },
  15191. needsUpdate: {
  15192. set: function ( value ) {
  15193. this.data.needsUpdate = value;
  15194. }
  15195. }
  15196. } );
  15197. Object.assign( InterleavedBufferAttribute.prototype, {
  15198. isInterleavedBufferAttribute: true,
  15199. applyMatrix4: function ( m ) {
  15200. for ( let i = 0, l = this.data.count; i < l; i ++ ) {
  15201. _vector$6.x = this.getX( i );
  15202. _vector$6.y = this.getY( i );
  15203. _vector$6.z = this.getZ( i );
  15204. _vector$6.applyMatrix4( m );
  15205. this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
  15206. }
  15207. return this;
  15208. },
  15209. setX: function ( index, x ) {
  15210. this.data.array[ index * this.data.stride + this.offset ] = x;
  15211. return this;
  15212. },
  15213. setY: function ( index, y ) {
  15214. this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
  15215. return this;
  15216. },
  15217. setZ: function ( index, z ) {
  15218. this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
  15219. return this;
  15220. },
  15221. setW: function ( index, w ) {
  15222. this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
  15223. return this;
  15224. },
  15225. getX: function ( index ) {
  15226. return this.data.array[ index * this.data.stride + this.offset ];
  15227. },
  15228. getY: function ( index ) {
  15229. return this.data.array[ index * this.data.stride + this.offset + 1 ];
  15230. },
  15231. getZ: function ( index ) {
  15232. return this.data.array[ index * this.data.stride + this.offset + 2 ];
  15233. },
  15234. getW: function ( index ) {
  15235. return this.data.array[ index * this.data.stride + this.offset + 3 ];
  15236. },
  15237. setXY: function ( index, x, y ) {
  15238. index = index * this.data.stride + this.offset;
  15239. this.data.array[ index + 0 ] = x;
  15240. this.data.array[ index + 1 ] = y;
  15241. return this;
  15242. },
  15243. setXYZ: function ( index, x, y, z ) {
  15244. index = index * this.data.stride + this.offset;
  15245. this.data.array[ index + 0 ] = x;
  15246. this.data.array[ index + 1 ] = y;
  15247. this.data.array[ index + 2 ] = z;
  15248. return this;
  15249. },
  15250. setXYZW: function ( index, x, y, z, w ) {
  15251. index = index * this.data.stride + this.offset;
  15252. this.data.array[ index + 0 ] = x;
  15253. this.data.array[ index + 1 ] = y;
  15254. this.data.array[ index + 2 ] = z;
  15255. this.data.array[ index + 3 ] = w;
  15256. return this;
  15257. },
  15258. clone: function ( data ) {
  15259. if ( data === undefined ) {
  15260. console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.' );
  15261. const array = [];
  15262. for ( let i = 0; i < this.count; i ++ ) {
  15263. const index = i * this.data.stride + this.offset;
  15264. for ( let j = 0; j < this.itemSize; j ++ ) {
  15265. array.push( this.data.array[ index + j ] );
  15266. }
  15267. }
  15268. return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
  15269. } else {
  15270. if ( data.interleavedBuffers === undefined ) {
  15271. data.interleavedBuffers = {};
  15272. }
  15273. if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
  15274. data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
  15275. }
  15276. return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
  15277. }
  15278. },
  15279. toJSON: function ( data ) {
  15280. if ( data === undefined ) {
  15281. console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.' );
  15282. const array = [];
  15283. for ( let i = 0; i < this.count; i ++ ) {
  15284. const index = i * this.data.stride + this.offset;
  15285. for ( let j = 0; j < this.itemSize; j ++ ) {
  15286. array.push( this.data.array[ index + j ] );
  15287. }
  15288. }
  15289. // deinterleave data and save it as an ordinary buffer attribute for now
  15290. return {
  15291. itemSize: this.itemSize,
  15292. type: this.array.constructor.name,
  15293. array: array,
  15294. normalized: this.normalized
  15295. };
  15296. } else {
  15297. // save as true interlaved attribtue
  15298. if ( data.interleavedBuffers === undefined ) {
  15299. data.interleavedBuffers = {};
  15300. }
  15301. if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
  15302. data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
  15303. }
  15304. return {
  15305. isInterleavedBufferAttribute: true,
  15306. itemSize: this.itemSize,
  15307. data: this.data.uuid,
  15308. offset: this.offset,
  15309. normalized: this.normalized
  15310. };
  15311. }
  15312. }
  15313. } );
  15314. /**
  15315. * parameters = {
  15316. * color: <hex>,
  15317. * map: new THREE.Texture( <Image> ),
  15318. * alphaMap: new THREE.Texture( <Image> ),
  15319. * rotation: <float>,
  15320. * sizeAttenuation: <bool>
  15321. * }
  15322. */
  15323. function SpriteMaterial( parameters ) {
  15324. Material.call( this );
  15325. this.type = 'SpriteMaterial';
  15326. this.color = new Color( 0xffffff );
  15327. this.map = null;
  15328. this.alphaMap = null;
  15329. this.rotation = 0;
  15330. this.sizeAttenuation = true;
  15331. this.transparent = true;
  15332. this.setValues( parameters );
  15333. }
  15334. SpriteMaterial.prototype = Object.create( Material.prototype );
  15335. SpriteMaterial.prototype.constructor = SpriteMaterial;
  15336. SpriteMaterial.prototype.isSpriteMaterial = true;
  15337. SpriteMaterial.prototype.copy = function ( source ) {
  15338. Material.prototype.copy.call( this, source );
  15339. this.color.copy( source.color );
  15340. this.map = source.map;
  15341. this.alphaMap = source.alphaMap;
  15342. this.rotation = source.rotation;
  15343. this.sizeAttenuation = source.sizeAttenuation;
  15344. return this;
  15345. };
  15346. let _geometry;
  15347. const _intersectPoint = new Vector3();
  15348. const _worldScale = new Vector3();
  15349. const _mvPosition = new Vector3();
  15350. const _alignedPosition = new Vector2();
  15351. const _rotatedPosition = new Vector2();
  15352. const _viewWorldMatrix = new Matrix4();
  15353. const _vA$1 = new Vector3();
  15354. const _vB$1 = new Vector3();
  15355. const _vC$1 = new Vector3();
  15356. const _uvA$1 = new Vector2();
  15357. const _uvB$1 = new Vector2();
  15358. const _uvC$1 = new Vector2();
  15359. function Sprite$1( material ) {
  15360. Object3D.call( this );
  15361. this.type = 'Sprite';
  15362. if ( _geometry === undefined ) {
  15363. _geometry = new BufferGeometry();
  15364. const float32Array = new Float32Array( [
  15365. - 0.5, - 0.5, 0, 0, 0,
  15366. 0.5, - 0.5, 0, 1, 0,
  15367. 0.5, 0.5, 0, 1, 1,
  15368. - 0.5, 0.5, 0, 0, 1
  15369. ] );
  15370. const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
  15371. _geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
  15372. _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
  15373. _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
  15374. }
  15375. this.geometry = _geometry;
  15376. this.material = ( material !== undefined ) ? material : new SpriteMaterial();
  15377. this.center = new Vector2( 0.5, 0.5 );
  15378. }
  15379. Sprite$1.prototype = Object.assign( Object.create( Object3D.prototype ), {
  15380. constructor: Sprite$1,
  15381. isSprite: true,
  15382. raycast: function ( raycaster, intersects ) {
  15383. if ( raycaster.camera === null ) {
  15384. console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
  15385. }
  15386. _worldScale.setFromMatrixScale( this.matrixWorld );
  15387. _viewWorldMatrix.copy( raycaster.camera.matrixWorld );
  15388. this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
  15389. _mvPosition.setFromMatrixPosition( this.modelViewMatrix );
  15390. if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
  15391. _worldScale.multiplyScalar( - _mvPosition.z );
  15392. }
  15393. const rotation = this.material.rotation;
  15394. let sin, cos;
  15395. if ( rotation !== 0 ) {
  15396. cos = Math.cos( rotation );
  15397. sin = Math.sin( rotation );
  15398. }
  15399. const center = this.center;
  15400. transformVertex( _vA$1.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
  15401. transformVertex( _vB$1.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
  15402. transformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
  15403. _uvA$1.set( 0, 0 );
  15404. _uvB$1.set( 1, 0 );
  15405. _uvC$1.set( 1, 1 );
  15406. // check first triangle
  15407. let intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );
  15408. if ( intersect === null ) {
  15409. // check second triangle
  15410. transformVertex( _vB$1.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
  15411. _uvB$1.set( 0, 1 );
  15412. intersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );
  15413. if ( intersect === null ) {
  15414. return;
  15415. }
  15416. }
  15417. const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
  15418. if ( distance < raycaster.near || distance > raycaster.far ) return;
  15419. intersects.push( {
  15420. distance: distance,
  15421. point: _intersectPoint.clone(),
  15422. uv: Triangle.getUV( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ),
  15423. face: null,
  15424. object: this
  15425. } );
  15426. },
  15427. copy: function ( source ) {
  15428. Object3D.prototype.copy.call( this, source );
  15429. if ( source.center !== undefined ) this.center.copy( source.center );
  15430. this.material = source.material;
  15431. return this;
  15432. }
  15433. } );
  15434. function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
  15435. // compute position in camera space
  15436. _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
  15437. // to check if rotation is not zero
  15438. if ( sin !== undefined ) {
  15439. _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
  15440. _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
  15441. } else {
  15442. _rotatedPosition.copy( _alignedPosition );
  15443. }
  15444. vertexPosition.copy( mvPosition );
  15445. vertexPosition.x += _rotatedPosition.x;
  15446. vertexPosition.y += _rotatedPosition.y;
  15447. // transform to world space
  15448. vertexPosition.applyMatrix4( _viewWorldMatrix );
  15449. }
  15450. const _v1$4 = new Vector3();
  15451. const _v2$2 = new Vector3();
  15452. function LOD() {
  15453. Object3D.call( this );
  15454. this._currentLevel = 0;
  15455. this.type = 'LOD';
  15456. Object.defineProperties( this, {
  15457. levels: {
  15458. enumerable: true,
  15459. value: []
  15460. }
  15461. } );
  15462. this.autoUpdate = true;
  15463. }
  15464. LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
  15465. constructor: LOD,
  15466. isLOD: true,
  15467. copy: function ( source ) {
  15468. Object3D.prototype.copy.call( this, source, false );
  15469. const levels = source.levels;
  15470. for ( let i = 0, l = levels.length; i < l; i ++ ) {
  15471. const level = levels[ i ];
  15472. this.addLevel( level.object.clone(), level.distance );
  15473. }
  15474. this.autoUpdate = source.autoUpdate;
  15475. return this;
  15476. },
  15477. addLevel: function ( object, distance = 0 ) {
  15478. distance = Math.abs( distance );
  15479. const levels = this.levels;
  15480. let l;
  15481. for ( l = 0; l < levels.length; l ++ ) {
  15482. if ( distance < levels[ l ].distance ) {
  15483. break;
  15484. }
  15485. }
  15486. levels.splice( l, 0, { distance: distance, object: object } );
  15487. this.add( object );
  15488. return this;
  15489. },
  15490. getCurrentLevel: function () {
  15491. return this._currentLevel;
  15492. },
  15493. getObjectForDistance: function ( distance ) {
  15494. const levels = this.levels;
  15495. if ( levels.length > 0 ) {
  15496. let i, l;
  15497. for ( i = 1, l = levels.length; i < l; i ++ ) {
  15498. if ( distance < levels[ i ].distance ) {
  15499. break;
  15500. }
  15501. }
  15502. return levels[ i - 1 ].object;
  15503. }
  15504. return null;
  15505. },
  15506. raycast: function ( raycaster, intersects ) {
  15507. const levels = this.levels;
  15508. if ( levels.length > 0 ) {
  15509. _v1$4.setFromMatrixPosition( this.matrixWorld );
  15510. const distance = raycaster.ray.origin.distanceTo( _v1$4 );
  15511. this.getObjectForDistance( distance ).raycast( raycaster, intersects );
  15512. }
  15513. },
  15514. update: function ( camera ) {
  15515. const levels = this.levels;
  15516. if ( levels.length > 1 ) {
  15517. _v1$4.setFromMatrixPosition( camera.matrixWorld );
  15518. _v2$2.setFromMatrixPosition( this.matrixWorld );
  15519. const distance = _v1$4.distanceTo( _v2$2 ) / camera.zoom;
  15520. levels[ 0 ].object.visible = true;
  15521. let i, l;
  15522. for ( i = 1, l = levels.length; i < l; i ++ ) {
  15523. if ( distance >= levels[ i ].distance ) {
  15524. levels[ i - 1 ].object.visible = false;
  15525. levels[ i ].object.visible = true;
  15526. } else {
  15527. break;
  15528. }
  15529. }
  15530. this._currentLevel = i - 1;
  15531. for ( ; i < l; i ++ ) {
  15532. levels[ i ].object.visible = false;
  15533. }
  15534. }
  15535. },
  15536. toJSON: function ( meta ) {
  15537. const data = Object3D.prototype.toJSON.call( this, meta );
  15538. if ( this.autoUpdate === false ) data.object.autoUpdate = false;
  15539. data.object.levels = [];
  15540. const levels = this.levels;
  15541. for ( let i = 0, l = levels.length; i < l; i ++ ) {
  15542. const level = levels[ i ];
  15543. data.object.levels.push( {
  15544. object: level.object.uuid,
  15545. distance: level.distance
  15546. } );
  15547. }
  15548. return data;
  15549. }
  15550. } );
  15551. const _basePosition = new Vector3();
  15552. const _skinIndex = new Vector4();
  15553. const _skinWeight = new Vector4();
  15554. const _vector$7 = new Vector3();
  15555. const _matrix$1 = new Matrix4();
  15556. function SkinnedMesh( geometry, material ) {
  15557. if ( geometry && geometry.isGeometry ) {
  15558. console.error( 'THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
  15559. }
  15560. Mesh.call( this, geometry, material );
  15561. this.type = 'SkinnedMesh';
  15562. this.bindMode = 'attached';
  15563. this.bindMatrix = new Matrix4();
  15564. this.bindMatrixInverse = new Matrix4();
  15565. }
  15566. SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
  15567. constructor: SkinnedMesh,
  15568. isSkinnedMesh: true,
  15569. copy: function ( source ) {
  15570. Mesh.prototype.copy.call( this, source );
  15571. this.bindMode = source.bindMode;
  15572. this.bindMatrix.copy( source.bindMatrix );
  15573. this.bindMatrixInverse.copy( source.bindMatrixInverse );
  15574. this.skeleton = source.skeleton;
  15575. return this;
  15576. },
  15577. bind: function ( skeleton, bindMatrix ) {
  15578. this.skeleton = skeleton;
  15579. if ( bindMatrix === undefined ) {
  15580. this.updateMatrixWorld( true );
  15581. this.skeleton.calculateInverses();
  15582. bindMatrix = this.matrixWorld;
  15583. }
  15584. this.bindMatrix.copy( bindMatrix );
  15585. this.bindMatrixInverse.copy( bindMatrix ).invert();
  15586. },
  15587. pose: function () {
  15588. this.skeleton.pose();
  15589. },
  15590. normalizeSkinWeights: function () {
  15591. const vector = new Vector4();
  15592. const skinWeight = this.geometry.attributes.skinWeight;
  15593. for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
  15594. vector.x = skinWeight.getX( i );
  15595. vector.y = skinWeight.getY( i );
  15596. vector.z = skinWeight.getZ( i );
  15597. vector.w = skinWeight.getW( i );
  15598. const scale = 1.0 / vector.manhattanLength();
  15599. if ( scale !== Infinity ) {
  15600. vector.multiplyScalar( scale );
  15601. } else {
  15602. vector.set( 1, 0, 0, 0 ); // do something reasonable
  15603. }
  15604. skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
  15605. }
  15606. },
  15607. updateMatrixWorld: function ( force ) {
  15608. Mesh.prototype.updateMatrixWorld.call( this, force );
  15609. if ( this.bindMode === 'attached' ) {
  15610. this.bindMatrixInverse.copy( this.matrixWorld ).invert();
  15611. } else if ( this.bindMode === 'detached' ) {
  15612. this.bindMatrixInverse.copy( this.bindMatrix ).invert();
  15613. } else {
  15614. console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
  15615. }
  15616. },
  15617. boneTransform: function ( index, target ) {
  15618. const skeleton = this.skeleton;
  15619. const geometry = this.geometry;
  15620. _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
  15621. _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
  15622. _basePosition.fromBufferAttribute( geometry.attributes.position, index ).applyMatrix4( this.bindMatrix );
  15623. target.set( 0, 0, 0 );
  15624. for ( let i = 0; i < 4; i ++ ) {
  15625. const weight = _skinWeight.getComponent( i );
  15626. if ( weight !== 0 ) {
  15627. const boneIndex = _skinIndex.getComponent( i );
  15628. _matrix$1.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
  15629. target.addScaledVector( _vector$7.copy( _basePosition ).applyMatrix4( _matrix$1 ), weight );
  15630. }
  15631. }
  15632. return target.applyMatrix4( this.bindMatrixInverse );
  15633. }
  15634. } );
  15635. function Bone() {
  15636. Object3D.call( this );
  15637. this.type = 'Bone';
  15638. }
  15639. Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
  15640. constructor: Bone,
  15641. isBone: true
  15642. } );
  15643. const _offsetMatrix = new Matrix4();
  15644. const _identityMatrix = new Matrix4();
  15645. function Skeleton( bones = [], boneInverses = [] ) {
  15646. this.uuid = MathUtils$1.generateUUID();
  15647. this.bones = bones.slice( 0 );
  15648. this.boneInverses = boneInverses;
  15649. this.boneMatrices = null;
  15650. this.boneTexture = null;
  15651. this.boneTextureSize = 0;
  15652. this.frame = - 1;
  15653. this.init();
  15654. }
  15655. Object.assign( Skeleton.prototype, {
  15656. init: function () {
  15657. const bones = this.bones;
  15658. const boneInverses = this.boneInverses;
  15659. this.boneMatrices = new Float32Array( bones.length * 16 );
  15660. // calculate inverse bone matrices if necessary
  15661. if ( boneInverses.length === 0 ) {
  15662. this.calculateInverses();
  15663. } else {
  15664. // handle special case
  15665. if ( bones.length !== boneInverses.length ) {
  15666. console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' );
  15667. this.boneInverses = [];
  15668. for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
  15669. this.boneInverses.push( new Matrix4() );
  15670. }
  15671. }
  15672. }
  15673. },
  15674. calculateInverses: function () {
  15675. this.boneInverses.length = 0;
  15676. for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
  15677. const inverse = new Matrix4();
  15678. if ( this.bones[ i ] ) {
  15679. inverse.copy( this.bones[ i ].matrixWorld ).invert();
  15680. }
  15681. this.boneInverses.push( inverse );
  15682. }
  15683. },
  15684. pose: function () {
  15685. // recover the bind-time world matrices
  15686. for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
  15687. const bone = this.bones[ i ];
  15688. if ( bone ) {
  15689. bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
  15690. }
  15691. }
  15692. // compute the local matrices, positions, rotations and scales
  15693. for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
  15694. const bone = this.bones[ i ];
  15695. if ( bone ) {
  15696. if ( bone.parent && bone.parent.isBone ) {
  15697. bone.matrix.copy( bone.parent.matrixWorld ).invert();
  15698. bone.matrix.multiply( bone.matrixWorld );
  15699. } else {
  15700. bone.matrix.copy( bone.matrixWorld );
  15701. }
  15702. bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
  15703. }
  15704. }
  15705. },
  15706. update: function () {
  15707. const bones = this.bones;
  15708. const boneInverses = this.boneInverses;
  15709. const boneMatrices = this.boneMatrices;
  15710. const boneTexture = this.boneTexture;
  15711. // flatten bone matrices to array
  15712. for ( let i = 0, il = bones.length; i < il; i ++ ) {
  15713. // compute the offset between the current and the original transform
  15714. const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
  15715. _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
  15716. _offsetMatrix.toArray( boneMatrices, i * 16 );
  15717. }
  15718. if ( boneTexture !== null ) {
  15719. boneTexture.needsUpdate = true;
  15720. }
  15721. },
  15722. clone: function () {
  15723. return new Skeleton( this.bones, this.boneInverses );
  15724. },
  15725. getBoneByName: function ( name ) {
  15726. for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
  15727. const bone = this.bones[ i ];
  15728. if ( bone.name === name ) {
  15729. return bone;
  15730. }
  15731. }
  15732. return undefined;
  15733. },
  15734. dispose: function ( ) {
  15735. if ( this.boneTexture !== null ) {
  15736. this.boneTexture.dispose();
  15737. this.boneTexture = null;
  15738. }
  15739. },
  15740. fromJSON: function ( json, bones ) {
  15741. this.uuid = json.uuid;
  15742. for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
  15743. const uuid = json.bones[ i ];
  15744. let bone = bones[ uuid ];
  15745. if ( bone === undefined ) {
  15746. console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid );
  15747. bone = new Bone();
  15748. }
  15749. this.bones.push( bone );
  15750. this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
  15751. }
  15752. this.init();
  15753. return this;
  15754. },
  15755. toJSON: function () {
  15756. const data = {
  15757. metadata: {
  15758. version: 4.5,
  15759. type: 'Skeleton',
  15760. generator: 'Skeleton.toJSON'
  15761. },
  15762. bones: [],
  15763. boneInverses: []
  15764. };
  15765. data.uuid = this.uuid;
  15766. const bones = this.bones;
  15767. const boneInverses = this.boneInverses;
  15768. for ( let i = 0, l = bones.length; i < l; i ++ ) {
  15769. const bone = bones[ i ];
  15770. data.bones.push( bone.uuid );
  15771. const boneInverse = boneInverses[ i ];
  15772. data.boneInverses.push( boneInverse.toArray() );
  15773. }
  15774. return data;
  15775. }
  15776. } );
  15777. const _instanceLocalMatrix = new Matrix4();
  15778. const _instanceWorldMatrix = new Matrix4();
  15779. const _instanceIntersects = [];
  15780. const _mesh = new Mesh();
  15781. function InstancedMesh( geometry, material, count ) {
  15782. Mesh.call( this, geometry, material );
  15783. this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );
  15784. this.instanceColor = null;
  15785. this.count = count;
  15786. this.frustumCulled = false;
  15787. }
  15788. InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
  15789. constructor: InstancedMesh,
  15790. isInstancedMesh: true,
  15791. copy: function ( source ) {
  15792. Mesh.prototype.copy.call( this, source );
  15793. this.instanceMatrix.copy( source.instanceMatrix );
  15794. this.count = source.count;
  15795. return this;
  15796. },
  15797. getColorAt: function ( index, color ) {
  15798. color.fromArray( this.instanceColor.array, index * 3 );
  15799. },
  15800. getMatrixAt: function ( index, matrix ) {
  15801. matrix.fromArray( this.instanceMatrix.array, index * 16 );
  15802. },
  15803. raycast: function ( raycaster, intersects ) {
  15804. const matrixWorld = this.matrixWorld;
  15805. const raycastTimes = this.count;
  15806. _mesh.geometry = this.geometry;
  15807. _mesh.material = this.material;
  15808. if ( _mesh.material === undefined ) return;
  15809. for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
  15810. // calculate the world matrix for each instance
  15811. this.getMatrixAt( instanceId, _instanceLocalMatrix );
  15812. _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
  15813. // the mesh represents this single instance
  15814. _mesh.matrixWorld = _instanceWorldMatrix;
  15815. _mesh.raycast( raycaster, _instanceIntersects );
  15816. // process the result of raycast
  15817. for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
  15818. const intersect = _instanceIntersects[ i ];
  15819. intersect.instanceId = instanceId;
  15820. intersect.object = this;
  15821. intersects.push( intersect );
  15822. }
  15823. _instanceIntersects.length = 0;
  15824. }
  15825. },
  15826. setColorAt: function ( index, color ) {
  15827. if ( this.instanceColor === null ) {
  15828. this.instanceColor = new BufferAttribute( new Float32Array( this.count * 3 ), 3 );
  15829. }
  15830. color.toArray( this.instanceColor.array, index * 3 );
  15831. },
  15832. setMatrixAt: function ( index, matrix ) {
  15833. matrix.toArray( this.instanceMatrix.array, index * 16 );
  15834. },
  15835. updateMorphTargets: function () {
  15836. },
  15837. dispose: function () {
  15838. this.dispatchEvent( { type: 'dispose' } );
  15839. }
  15840. } );
  15841. /**
  15842. * parameters = {
  15843. * color: <hex>,
  15844. * opacity: <float>,
  15845. *
  15846. * linewidth: <float>,
  15847. * linecap: "round",
  15848. * linejoin: "round"
  15849. * }
  15850. */
  15851. function LineBasicMaterial( parameters ) {
  15852. Material.call( this );
  15853. this.type = 'LineBasicMaterial';
  15854. this.color = new Color( 0xffffff );
  15855. this.linewidth = 1;
  15856. this.linecap = 'round';
  15857. this.linejoin = 'round';
  15858. this.morphTargets = false;
  15859. this.setValues( parameters );
  15860. }
  15861. LineBasicMaterial.prototype = Object.create( Material.prototype );
  15862. LineBasicMaterial.prototype.constructor = LineBasicMaterial;
  15863. LineBasicMaterial.prototype.isLineBasicMaterial = true;
  15864. LineBasicMaterial.prototype.copy = function ( source ) {
  15865. Material.prototype.copy.call( this, source );
  15866. this.color.copy( source.color );
  15867. this.linewidth = source.linewidth;
  15868. this.linecap = source.linecap;
  15869. this.linejoin = source.linejoin;
  15870. this.morphTargets = source.morphTargets;
  15871. return this;
  15872. };
  15873. const _start = new Vector3();
  15874. const _end = new Vector3();
  15875. const _inverseMatrix$1 = new Matrix4();
  15876. const _ray$1 = new Ray();
  15877. const _sphere$2 = new Sphere();
  15878. function Line( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
  15879. Object3D.call( this );
  15880. this.type = 'Line';
  15881. this.geometry = geometry;
  15882. this.material = material;
  15883. this.updateMorphTargets();
  15884. }
  15885. Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
  15886. constructor: Line,
  15887. isLine: true,
  15888. copy: function ( source ) {
  15889. Object3D.prototype.copy.call( this, source );
  15890. this.material = source.material;
  15891. this.geometry = source.geometry;
  15892. return this;
  15893. },
  15894. computeLineDistances: function () {
  15895. const geometry = this.geometry;
  15896. if ( geometry.isBufferGeometry ) {
  15897. // we assume non-indexed geometry
  15898. if ( geometry.index === null ) {
  15899. const positionAttribute = geometry.attributes.position;
  15900. const lineDistances = [ 0 ];
  15901. for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
  15902. _start.fromBufferAttribute( positionAttribute, i - 1 );
  15903. _end.fromBufferAttribute( positionAttribute, i );
  15904. lineDistances[ i ] = lineDistances[ i - 1 ];
  15905. lineDistances[ i ] += _start.distanceTo( _end );
  15906. }
  15907. geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
  15908. } else {
  15909. console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
  15910. }
  15911. } else if ( geometry.isGeometry ) {
  15912. const vertices = geometry.vertices;
  15913. const lineDistances = geometry.lineDistances;
  15914. lineDistances[ 0 ] = 0;
  15915. for ( let i = 1, l = vertices.length; i < l; i ++ ) {
  15916. lineDistances[ i ] = lineDistances[ i - 1 ];
  15917. lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
  15918. }
  15919. }
  15920. return this;
  15921. },
  15922. raycast: function ( raycaster, intersects ) {
  15923. const geometry = this.geometry;
  15924. const matrixWorld = this.matrixWorld;
  15925. const threshold = raycaster.params.Line.threshold;
  15926. // Checking boundingSphere distance to ray
  15927. if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
  15928. _sphere$2.copy( geometry.boundingSphere );
  15929. _sphere$2.applyMatrix4( matrixWorld );
  15930. _sphere$2.radius += threshold;
  15931. if ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) return;
  15932. //
  15933. _inverseMatrix$1.copy( matrixWorld ).invert();
  15934. _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
  15935. const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
  15936. const localThresholdSq = localThreshold * localThreshold;
  15937. const vStart = new Vector3();
  15938. const vEnd = new Vector3();
  15939. const interSegment = new Vector3();
  15940. const interRay = new Vector3();
  15941. const step = this.isLineSegments ? 2 : 1;
  15942. if ( geometry.isBufferGeometry ) {
  15943. const index = geometry.index;
  15944. const attributes = geometry.attributes;
  15945. const positionAttribute = attributes.position;
  15946. if ( index !== null ) {
  15947. const indices = index.array;
  15948. for ( let i = 0, l = indices.length - 1; i < l; i += step ) {
  15949. const a = indices[ i ];
  15950. const b = indices[ i + 1 ];
  15951. vStart.fromBufferAttribute( positionAttribute, a );
  15952. vEnd.fromBufferAttribute( positionAttribute, b );
  15953. const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
  15954. if ( distSq > localThresholdSq ) continue;
  15955. interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
  15956. const distance = raycaster.ray.origin.distanceTo( interRay );
  15957. if ( distance < raycaster.near || distance > raycaster.far ) continue;
  15958. intersects.push( {
  15959. distance: distance,
  15960. // What do we want? intersection point on the ray or on the segment??
  15961. // point: raycaster.ray.at( distance ),
  15962. point: interSegment.clone().applyMatrix4( this.matrixWorld ),
  15963. index: i,
  15964. face: null,
  15965. faceIndex: null,
  15966. object: this
  15967. } );
  15968. }
  15969. } else {
  15970. for ( let i = 0, l = positionAttribute.count - 1; i < l; i += step ) {
  15971. vStart.fromBufferAttribute( positionAttribute, i );
  15972. vEnd.fromBufferAttribute( positionAttribute, i + 1 );
  15973. const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
  15974. if ( distSq > localThresholdSq ) continue;
  15975. interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
  15976. const distance = raycaster.ray.origin.distanceTo( interRay );
  15977. if ( distance < raycaster.near || distance > raycaster.far ) continue;
  15978. intersects.push( {
  15979. distance: distance,
  15980. // What do we want? intersection point on the ray or on the segment??
  15981. // point: raycaster.ray.at( distance ),
  15982. point: interSegment.clone().applyMatrix4( this.matrixWorld ),
  15983. index: i,
  15984. face: null,
  15985. faceIndex: null,
  15986. object: this
  15987. } );
  15988. }
  15989. }
  15990. } else if ( geometry.isGeometry ) {
  15991. const vertices = geometry.vertices;
  15992. const nbVertices = vertices.length;
  15993. for ( let i = 0; i < nbVertices - 1; i += step ) {
  15994. const distSq = _ray$1.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
  15995. if ( distSq > localThresholdSq ) continue;
  15996. interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
  15997. const distance = raycaster.ray.origin.distanceTo( interRay );
  15998. if ( distance < raycaster.near || distance > raycaster.far ) continue;
  15999. intersects.push( {
  16000. distance: distance,
  16001. // What do we want? intersection point on the ray or on the segment??
  16002. // point: raycaster.ray.at( distance ),
  16003. point: interSegment.clone().applyMatrix4( this.matrixWorld ),
  16004. index: i,
  16005. face: null,
  16006. faceIndex: null,
  16007. object: this
  16008. } );
  16009. }
  16010. }
  16011. },
  16012. updateMorphTargets: function () {
  16013. const geometry = this.geometry;
  16014. if ( geometry.isBufferGeometry ) {
  16015. const morphAttributes = geometry.morphAttributes;
  16016. const keys = Object.keys( morphAttributes );
  16017. if ( keys.length > 0 ) {
  16018. const morphAttribute = morphAttributes[ keys[ 0 ] ];
  16019. if ( morphAttribute !== undefined ) {
  16020. this.morphTargetInfluences = [];
  16021. this.morphTargetDictionary = {};
  16022. for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
  16023. const name = morphAttribute[ m ].name || String( m );
  16024. this.morphTargetInfluences.push( 0 );
  16025. this.morphTargetDictionary[ name ] = m;
  16026. }
  16027. }
  16028. }
  16029. } else {
  16030. const morphTargets = geometry.morphTargets;
  16031. if ( morphTargets !== undefined && morphTargets.length > 0 ) {
  16032. console.error( 'THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
  16033. }
  16034. }
  16035. }
  16036. } );
  16037. const _start$1 = new Vector3();
  16038. const _end$1 = new Vector3();
  16039. function LineSegments( geometry, material ) {
  16040. Line.call( this, geometry, material );
  16041. this.type = 'LineSegments';
  16042. }
  16043. LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
  16044. constructor: LineSegments,
  16045. isLineSegments: true,
  16046. computeLineDistances: function () {
  16047. const geometry = this.geometry;
  16048. if ( geometry.isBufferGeometry ) {
  16049. // we assume non-indexed geometry
  16050. if ( geometry.index === null ) {
  16051. const positionAttribute = geometry.attributes.position;
  16052. const lineDistances = [];
  16053. for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
  16054. _start$1.fromBufferAttribute( positionAttribute, i );
  16055. _end$1.fromBufferAttribute( positionAttribute, i + 1 );
  16056. lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
  16057. lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
  16058. }
  16059. geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
  16060. } else {
  16061. console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
  16062. }
  16063. } else if ( geometry.isGeometry ) {
  16064. const vertices = geometry.vertices;
  16065. const lineDistances = geometry.lineDistances;
  16066. for ( let i = 0, l = vertices.length; i < l; i += 2 ) {
  16067. _start$1.copy( vertices[ i ] );
  16068. _end$1.copy( vertices[ i + 1 ] );
  16069. lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
  16070. lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
  16071. }
  16072. }
  16073. return this;
  16074. }
  16075. } );
  16076. function LineLoop( geometry, material ) {
  16077. Line.call( this, geometry, material );
  16078. this.type = 'LineLoop';
  16079. }
  16080. LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
  16081. constructor: LineLoop,
  16082. isLineLoop: true,
  16083. } );
  16084. /**
  16085. * parameters = {
  16086. * color: <hex>,
  16087. * opacity: <float>,
  16088. * map: new THREE.Texture( <Image> ),
  16089. * alphaMap: new THREE.Texture( <Image> ),
  16090. *
  16091. * size: <float>,
  16092. * sizeAttenuation: <bool>
  16093. *
  16094. * morphTargets: <bool>
  16095. * }
  16096. */
  16097. function PointsMaterial( parameters ) {
  16098. Material.call( this );
  16099. this.type = 'PointsMaterial';
  16100. this.color = new Color( 0xffffff );
  16101. this.map = null;
  16102. this.alphaMap = null;
  16103. this.size = 1;
  16104. this.sizeAttenuation = true;
  16105. this.morphTargets = false;
  16106. this.setValues( parameters );
  16107. }
  16108. PointsMaterial.prototype = Object.create( Material.prototype );
  16109. PointsMaterial.prototype.constructor = PointsMaterial;
  16110. PointsMaterial.prototype.isPointsMaterial = true;
  16111. PointsMaterial.prototype.copy = function ( source ) {
  16112. Material.prototype.copy.call( this, source );
  16113. this.color.copy( source.color );
  16114. this.map = source.map;
  16115. this.alphaMap = source.alphaMap;
  16116. this.size = source.size;
  16117. this.sizeAttenuation = source.sizeAttenuation;
  16118. this.morphTargets = source.morphTargets;
  16119. return this;
  16120. };
  16121. const _inverseMatrix$2 = new Matrix4();
  16122. const _ray$2 = new Ray();
  16123. const _sphere$3 = new Sphere();
  16124. const _position$1 = new Vector3();
  16125. function Points( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
  16126. Object3D.call( this );
  16127. this.type = 'Points';
  16128. this.geometry = geometry;
  16129. this.material = material;
  16130. this.updateMorphTargets();
  16131. }
  16132. Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
  16133. constructor: Points,
  16134. isPoints: true,
  16135. copy: function ( source ) {
  16136. Object3D.prototype.copy.call( this, source );
  16137. this.material = source.material;
  16138. this.geometry = source.geometry;
  16139. return this;
  16140. },
  16141. raycast: function ( raycaster, intersects ) {
  16142. const geometry = this.geometry;
  16143. const matrixWorld = this.matrixWorld;
  16144. const threshold = raycaster.params.Points.threshold;
  16145. // Checking boundingSphere distance to ray
  16146. if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
  16147. _sphere$3.copy( geometry.boundingSphere );
  16148. _sphere$3.applyMatrix4( matrixWorld );
  16149. _sphere$3.radius += threshold;
  16150. if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
  16151. //
  16152. _inverseMatrix$2.copy( matrixWorld ).invert();
  16153. _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
  16154. const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
  16155. const localThresholdSq = localThreshold * localThreshold;
  16156. if ( geometry.isBufferGeometry ) {
  16157. const index = geometry.index;
  16158. const attributes = geometry.attributes;
  16159. const positionAttribute = attributes.position;
  16160. if ( index !== null ) {
  16161. const indices = index.array;
  16162. for ( let i = 0, il = indices.length; i < il; i ++ ) {
  16163. const a = indices[ i ];
  16164. _position$1.fromBufferAttribute( positionAttribute, a );
  16165. testPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
  16166. }
  16167. } else {
  16168. for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
  16169. _position$1.fromBufferAttribute( positionAttribute, i );
  16170. testPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
  16171. }
  16172. }
  16173. } else {
  16174. const vertices = geometry.vertices;
  16175. for ( let i = 0, l = vertices.length; i < l; i ++ ) {
  16176. testPoint( vertices[ i ], i, localThresholdSq, matrixWorld, raycaster, intersects, this );
  16177. }
  16178. }
  16179. },
  16180. updateMorphTargets: function () {
  16181. const geometry = this.geometry;
  16182. if ( geometry.isBufferGeometry ) {
  16183. const morphAttributes = geometry.morphAttributes;
  16184. const keys = Object.keys( morphAttributes );
  16185. if ( keys.length > 0 ) {
  16186. const morphAttribute = morphAttributes[ keys[ 0 ] ];
  16187. if ( morphAttribute !== undefined ) {
  16188. this.morphTargetInfluences = [];
  16189. this.morphTargetDictionary = {};
  16190. for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
  16191. const name = morphAttribute[ m ].name || String( m );
  16192. this.morphTargetInfluences.push( 0 );
  16193. this.morphTargetDictionary[ name ] = m;
  16194. }
  16195. }
  16196. }
  16197. } else {
  16198. const morphTargets = geometry.morphTargets;
  16199. if ( morphTargets !== undefined && morphTargets.length > 0 ) {
  16200. console.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
  16201. }
  16202. }
  16203. }
  16204. } );
  16205. function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
  16206. const rayPointDistanceSq = _ray$2.distanceSqToPoint( point );
  16207. if ( rayPointDistanceSq < localThresholdSq ) {
  16208. const intersectPoint = new Vector3();
  16209. _ray$2.closestPointToPoint( point, intersectPoint );
  16210. intersectPoint.applyMatrix4( matrixWorld );
  16211. const distance = raycaster.ray.origin.distanceTo( intersectPoint );
  16212. if ( distance < raycaster.near || distance > raycaster.far ) return;
  16213. intersects.push( {
  16214. distance: distance,
  16215. distanceToRay: Math.sqrt( rayPointDistanceSq ),
  16216. point: intersectPoint,
  16217. index: index,
  16218. face: null,
  16219. object: object
  16220. } );
  16221. }
  16222. }
  16223. function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
  16224. Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
  16225. this.format = format !== undefined ? format : RGBFormat;
  16226. this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
  16227. this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
  16228. this.generateMipmaps = false;
  16229. const scope = this;
  16230. function updateVideo() {
  16231. scope.needsUpdate = true;
  16232. video.requestVideoFrameCallback( updateVideo );
  16233. }
  16234. if ( 'requestVideoFrameCallback' in video ) {
  16235. video.requestVideoFrameCallback( updateVideo );
  16236. }
  16237. }
  16238. VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
  16239. constructor: VideoTexture,
  16240. clone: function () {
  16241. return new this.constructor( this.image ).copy( this );
  16242. },
  16243. isVideoTexture: true,
  16244. update: function () {
  16245. const video = this.image;
  16246. const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
  16247. if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
  16248. this.needsUpdate = true;
  16249. }
  16250. }
  16251. } );
  16252. function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
  16253. Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
  16254. this.image = { width: width, height: height };
  16255. this.mipmaps = mipmaps;
  16256. // no flipping for cube textures
  16257. // (also flipping doesn't work for compressed textures )
  16258. this.flipY = false;
  16259. // can't generate mipmaps for compressed textures
  16260. // mips must be embedded in DDS files
  16261. this.generateMipmaps = false;
  16262. }
  16263. CompressedTexture.prototype = Object.create( Texture.prototype );
  16264. CompressedTexture.prototype.constructor = CompressedTexture;
  16265. CompressedTexture.prototype.isCompressedTexture = true;
  16266. function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
  16267. Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
  16268. this.needsUpdate = true;
  16269. }
  16270. CanvasTexture.prototype = Object.create( Texture.prototype );
  16271. CanvasTexture.prototype.constructor = CanvasTexture;
  16272. CanvasTexture.prototype.isCanvasTexture = true;
  16273. function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
  16274. format = format !== undefined ? format : DepthFormat;
  16275. if ( format !== DepthFormat && format !== DepthStencilFormat ) {
  16276. throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
  16277. }
  16278. if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
  16279. if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type$1;
  16280. Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
  16281. this.image = { width: width, height: height };
  16282. this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
  16283. this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
  16284. this.flipY = false;
  16285. this.generateMipmaps = false;
  16286. }
  16287. DepthTexture.prototype = Object.create( Texture.prototype );
  16288. DepthTexture.prototype.constructor = DepthTexture;
  16289. DepthTexture.prototype.isDepthTexture = true;
  16290. let _geometryId = 0; // Geometry uses even numbers as Id
  16291. const _m1$3 = new Matrix4();
  16292. const _obj$1 = new Object3D();
  16293. const _offset$1 = new Vector3();
  16294. function Geometry() {
  16295. Object.defineProperty( this, 'id', { value: _geometryId += 2 } );
  16296. this.uuid = MathUtils$1.generateUUID();
  16297. this.name = '';
  16298. this.type = 'Geometry';
  16299. this.vertices = [];
  16300. this.colors = [];
  16301. this.faces = [];
  16302. this.faceVertexUvs = [[]];
  16303. this.morphTargets = [];
  16304. this.morphNormals = [];
  16305. this.skinWeights = [];
  16306. this.skinIndices = [];
  16307. this.lineDistances = [];
  16308. this.boundingBox = null;
  16309. this.boundingSphere = null;
  16310. // update flags
  16311. this.elementsNeedUpdate = false;
  16312. this.verticesNeedUpdate = false;
  16313. this.uvsNeedUpdate = false;
  16314. this.normalsNeedUpdate = false;
  16315. this.colorsNeedUpdate = false;
  16316. this.lineDistancesNeedUpdate = false;
  16317. this.groupsNeedUpdate = false;
  16318. }
  16319. Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
  16320. constructor: Geometry,
  16321. isGeometry: true,
  16322. applyMatrix4: function ( matrix ) {
  16323. const normalMatrix = new Matrix3().getNormalMatrix( matrix );
  16324. for ( let i = 0, il = this.vertices.length; i < il; i ++ ) {
  16325. const vertex = this.vertices[ i ];
  16326. vertex.applyMatrix4( matrix );
  16327. }
  16328. for ( let i = 0, il = this.faces.length; i < il; i ++ ) {
  16329. const face = this.faces[ i ];
  16330. face.normal.applyMatrix3( normalMatrix ).normalize();
  16331. for ( let j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
  16332. face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
  16333. }
  16334. }
  16335. if ( this.boundingBox !== null ) {
  16336. this.computeBoundingBox();
  16337. }
  16338. if ( this.boundingSphere !== null ) {
  16339. this.computeBoundingSphere();
  16340. }
  16341. this.verticesNeedUpdate = true;
  16342. this.normalsNeedUpdate = true;
  16343. return this;
  16344. },
  16345. rotateX: function ( angle ) {
  16346. // rotate geometry around world x-axis
  16347. _m1$3.makeRotationX( angle );
  16348. this.applyMatrix4( _m1$3 );
  16349. return this;
  16350. },
  16351. rotateY: function ( angle ) {
  16352. // rotate geometry around world y-axis
  16353. _m1$3.makeRotationY( angle );
  16354. this.applyMatrix4( _m1$3 );
  16355. return this;
  16356. },
  16357. rotateZ: function ( angle ) {
  16358. // rotate geometry around world z-axis
  16359. _m1$3.makeRotationZ( angle );
  16360. this.applyMatrix4( _m1$3 );
  16361. return this;
  16362. },
  16363. translate: function ( x, y, z ) {
  16364. // translate geometry
  16365. _m1$3.makeTranslation( x, y, z );
  16366. this.applyMatrix4( _m1$3 );
  16367. return this;
  16368. },
  16369. scale: function ( x, y, z ) {
  16370. // scale geometry
  16371. _m1$3.makeScale( x, y, z );
  16372. this.applyMatrix4( _m1$3 );
  16373. return this;
  16374. },
  16375. lookAt: function ( vector ) {
  16376. _obj$1.lookAt( vector );
  16377. _obj$1.updateMatrix();
  16378. this.applyMatrix4( _obj$1.matrix );
  16379. return this;
  16380. },
  16381. fromBufferGeometry: function ( geometry ) {
  16382. const scope = this;
  16383. const index = geometry.index !== null ? geometry.index : undefined;
  16384. const attributes = geometry.attributes;
  16385. if ( attributes.position === undefined ) {
  16386. console.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' );
  16387. return this;
  16388. }
  16389. const position = attributes.position;
  16390. const normal = attributes.normal;
  16391. const color = attributes.color;
  16392. const uv = attributes.uv;
  16393. const uv2 = attributes.uv2;
  16394. if ( uv2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
  16395. for ( let i = 0; i < position.count; i ++ ) {
  16396. scope.vertices.push( new Vector3().fromBufferAttribute( position, i ) );
  16397. if ( color !== undefined ) {
  16398. scope.colors.push( new Color().fromBufferAttribute( color, i ) );
  16399. }
  16400. }
  16401. function addFace( a, b, c, materialIndex ) {
  16402. const vertexColors = ( color === undefined ) ? [] : [
  16403. scope.colors[ a ].clone(),
  16404. scope.colors[ b ].clone(),
  16405. scope.colors[ c ].clone()
  16406. ];
  16407. const vertexNormals = ( normal === undefined ) ? [] : [
  16408. new Vector3().fromBufferAttribute( normal, a ),
  16409. new Vector3().fromBufferAttribute( normal, b ),
  16410. new Vector3().fromBufferAttribute( normal, c )
  16411. ];
  16412. const face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
  16413. scope.faces.push( face );
  16414. if ( uv !== undefined ) {
  16415. scope.faceVertexUvs[ 0 ].push( [
  16416. new Vector2().fromBufferAttribute( uv, a ),
  16417. new Vector2().fromBufferAttribute( uv, b ),
  16418. new Vector2().fromBufferAttribute( uv, c )
  16419. ] );
  16420. }
  16421. if ( uv2 !== undefined ) {
  16422. scope.faceVertexUvs[ 1 ].push( [
  16423. new Vector2().fromBufferAttribute( uv2, a ),
  16424. new Vector2().fromBufferAttribute( uv2, b ),
  16425. new Vector2().fromBufferAttribute( uv2, c )
  16426. ] );
  16427. }
  16428. }
  16429. const groups = geometry.groups;
  16430. if ( groups.length > 0 ) {
  16431. for ( let i = 0; i < groups.length; i ++ ) {
  16432. const group = groups[ i ];
  16433. const start = group.start;
  16434. const count = group.count;
  16435. for ( let j = start, jl = start + count; j < jl; j += 3 ) {
  16436. if ( index !== undefined ) {
  16437. addFace( index.getX( j ), index.getX( j + 1 ), index.getX( j + 2 ), group.materialIndex );
  16438. } else {
  16439. addFace( j, j + 1, j + 2, group.materialIndex );
  16440. }
  16441. }
  16442. }
  16443. } else {
  16444. if ( index !== undefined ) {
  16445. for ( let i = 0; i < index.count; i += 3 ) {
  16446. addFace( index.getX( i ), index.getX( i + 1 ), index.getX( i + 2 ) );
  16447. }
  16448. } else {
  16449. for ( let i = 0; i < position.count; i += 3 ) {
  16450. addFace( i, i + 1, i + 2 );
  16451. }
  16452. }
  16453. }
  16454. this.computeFaceNormals();
  16455. if ( geometry.boundingBox !== null ) {
  16456. this.boundingBox = geometry.boundingBox.clone();
  16457. }
  16458. if ( geometry.boundingSphere !== null ) {
  16459. this.boundingSphere = geometry.boundingSphere.clone();
  16460. }
  16461. return this;
  16462. },
  16463. center: function () {
  16464. this.computeBoundingBox();
  16465. this.boundingBox.getCenter( _offset$1 ).negate();
  16466. this.translate( _offset$1.x, _offset$1.y, _offset$1.z );
  16467. return this;
  16468. },
  16469. normalize: function () {
  16470. this.computeBoundingSphere();
  16471. const center = this.boundingSphere.center;
  16472. const radius = this.boundingSphere.radius;
  16473. const s = radius === 0 ? 1 : 1.0 / radius;
  16474. const matrix = new Matrix4();
  16475. matrix.set(
  16476. s, 0, 0, - s * center.x,
  16477. 0, s, 0, - s * center.y,
  16478. 0, 0, s, - s * center.z,
  16479. 0, 0, 0, 1
  16480. );
  16481. this.applyMatrix4( matrix );
  16482. return this;
  16483. },
  16484. computeFaceNormals: function () {
  16485. const cb = new Vector3(), ab = new Vector3();
  16486. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16487. const face = this.faces[ f ];
  16488. const vA = this.vertices[ face.a ];
  16489. const vB = this.vertices[ face.b ];
  16490. const vC = this.vertices[ face.c ];
  16491. cb.subVectors( vC, vB );
  16492. ab.subVectors( vA, vB );
  16493. cb.cross( ab );
  16494. cb.normalize();
  16495. face.normal.copy( cb );
  16496. }
  16497. },
  16498. computeVertexNormals: function ( areaWeighted = true ) {
  16499. const vertices = new Array( this.vertices.length );
  16500. for ( let v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  16501. vertices[ v ] = new Vector3();
  16502. }
  16503. if ( areaWeighted ) {
  16504. // vertex normals weighted by triangle areas
  16505. // http://www.iquilezles.org/www/articles/normals/normals.htm
  16506. const cb = new Vector3(), ab = new Vector3();
  16507. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16508. const face = this.faces[ f ];
  16509. const vA = this.vertices[ face.a ];
  16510. const vB = this.vertices[ face.b ];
  16511. const vC = this.vertices[ face.c ];
  16512. cb.subVectors( vC, vB );
  16513. ab.subVectors( vA, vB );
  16514. cb.cross( ab );
  16515. vertices[ face.a ].add( cb );
  16516. vertices[ face.b ].add( cb );
  16517. vertices[ face.c ].add( cb );
  16518. }
  16519. } else {
  16520. this.computeFaceNormals();
  16521. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16522. const face = this.faces[ f ];
  16523. vertices[ face.a ].add( face.normal );
  16524. vertices[ face.b ].add( face.normal );
  16525. vertices[ face.c ].add( face.normal );
  16526. }
  16527. }
  16528. for ( let v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  16529. vertices[ v ].normalize();
  16530. }
  16531. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16532. const face = this.faces[ f ];
  16533. const vertexNormals = face.vertexNormals;
  16534. if ( vertexNormals.length === 3 ) {
  16535. vertexNormals[ 0 ].copy( vertices[ face.a ] );
  16536. vertexNormals[ 1 ].copy( vertices[ face.b ] );
  16537. vertexNormals[ 2 ].copy( vertices[ face.c ] );
  16538. } else {
  16539. vertexNormals[ 0 ] = vertices[ face.a ].clone();
  16540. vertexNormals[ 1 ] = vertices[ face.b ].clone();
  16541. vertexNormals[ 2 ] = vertices[ face.c ].clone();
  16542. }
  16543. }
  16544. if ( this.faces.length > 0 ) {
  16545. this.normalsNeedUpdate = true;
  16546. }
  16547. },
  16548. computeFlatVertexNormals: function () {
  16549. this.computeFaceNormals();
  16550. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16551. const face = this.faces[ f ];
  16552. const vertexNormals = face.vertexNormals;
  16553. if ( vertexNormals.length === 3 ) {
  16554. vertexNormals[ 0 ].copy( face.normal );
  16555. vertexNormals[ 1 ].copy( face.normal );
  16556. vertexNormals[ 2 ].copy( face.normal );
  16557. } else {
  16558. vertexNormals[ 0 ] = face.normal.clone();
  16559. vertexNormals[ 1 ] = face.normal.clone();
  16560. vertexNormals[ 2 ] = face.normal.clone();
  16561. }
  16562. }
  16563. if ( this.faces.length > 0 ) {
  16564. this.normalsNeedUpdate = true;
  16565. }
  16566. },
  16567. computeMorphNormals: function () {
  16568. // save original normals
  16569. // - create temp variables on first access
  16570. // otherwise just copy (for faster repeated calls)
  16571. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16572. const face = this.faces[ f ];
  16573. if ( ! face.__originalFaceNormal ) {
  16574. face.__originalFaceNormal = face.normal.clone();
  16575. } else {
  16576. face.__originalFaceNormal.copy( face.normal );
  16577. }
  16578. if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
  16579. for ( let i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
  16580. if ( ! face.__originalVertexNormals[ i ] ) {
  16581. face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
  16582. } else {
  16583. face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
  16584. }
  16585. }
  16586. }
  16587. // use temp geometry to compute face and vertex normals for each morph
  16588. const tmpGeo = new Geometry();
  16589. tmpGeo.faces = this.faces;
  16590. for ( let i = 0, il = this.morphTargets.length; i < il; i ++ ) {
  16591. // create on first access
  16592. if ( ! this.morphNormals[ i ] ) {
  16593. this.morphNormals[ i ] = {};
  16594. this.morphNormals[ i ].faceNormals = [];
  16595. this.morphNormals[ i ].vertexNormals = [];
  16596. const dstNormalsFace = this.morphNormals[ i ].faceNormals;
  16597. const dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
  16598. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16599. const faceNormal = new Vector3();
  16600. const vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
  16601. dstNormalsFace.push( faceNormal );
  16602. dstNormalsVertex.push( vertexNormals );
  16603. }
  16604. }
  16605. const morphNormals = this.morphNormals[ i ];
  16606. // set vertices to morph target
  16607. tmpGeo.vertices = this.morphTargets[ i ].vertices;
  16608. // compute morph normals
  16609. tmpGeo.computeFaceNormals();
  16610. tmpGeo.computeVertexNormals();
  16611. // store morph normals
  16612. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16613. const face = this.faces[ f ];
  16614. const faceNormal = morphNormals.faceNormals[ f ];
  16615. const vertexNormals = morphNormals.vertexNormals[ f ];
  16616. faceNormal.copy( face.normal );
  16617. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  16618. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  16619. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  16620. }
  16621. }
  16622. // restore original normals
  16623. for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
  16624. const face = this.faces[ f ];
  16625. face.normal = face.__originalFaceNormal;
  16626. face.vertexNormals = face.__originalVertexNormals;
  16627. }
  16628. },
  16629. computeBoundingBox: function () {
  16630. if ( this.boundingBox === null ) {
  16631. this.boundingBox = new Box3();
  16632. }
  16633. this.boundingBox.setFromPoints( this.vertices );
  16634. },
  16635. computeBoundingSphere: function () {
  16636. if ( this.boundingSphere === null ) {
  16637. this.boundingSphere = new Sphere();
  16638. }
  16639. this.boundingSphere.setFromPoints( this.vertices );
  16640. },
  16641. merge: function ( geometry, matrix, materialIndexOffset = 0 ) {
  16642. if ( ! ( geometry && geometry.isGeometry ) ) {
  16643. console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
  16644. return;
  16645. }
  16646. let normalMatrix;
  16647. const vertexOffset = this.vertices.length,
  16648. vertices1 = this.vertices,
  16649. vertices2 = geometry.vertices,
  16650. faces1 = this.faces,
  16651. faces2 = geometry.faces,
  16652. colors1 = this.colors,
  16653. colors2 = geometry.colors;
  16654. if ( matrix !== undefined ) {
  16655. normalMatrix = new Matrix3().getNormalMatrix( matrix );
  16656. }
  16657. // vertices
  16658. for ( let i = 0, il = vertices2.length; i < il; i ++ ) {
  16659. const vertex = vertices2[ i ];
  16660. const vertexCopy = vertex.clone();
  16661. if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
  16662. vertices1.push( vertexCopy );
  16663. }
  16664. // colors
  16665. for ( let i = 0, il = colors2.length; i < il; i ++ ) {
  16666. colors1.push( colors2[ i ].clone() );
  16667. }
  16668. // faces
  16669. for ( let i = 0, il = faces2.length; i < il; i ++ ) {
  16670. const face = faces2[ i ];
  16671. let normal, color;
  16672. const faceVertexNormals = face.vertexNormals,
  16673. faceVertexColors = face.vertexColors;
  16674. const faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
  16675. faceCopy.normal.copy( face.normal );
  16676. if ( normalMatrix !== undefined ) {
  16677. faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
  16678. }
  16679. for ( let j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  16680. normal = faceVertexNormals[ j ].clone();
  16681. if ( normalMatrix !== undefined ) {
  16682. normal.applyMatrix3( normalMatrix ).normalize();
  16683. }
  16684. faceCopy.vertexNormals.push( normal );
  16685. }
  16686. faceCopy.color.copy( face.color );
  16687. for ( let j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  16688. color = faceVertexColors[ j ];
  16689. faceCopy.vertexColors.push( color.clone() );
  16690. }
  16691. faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
  16692. faces1.push( faceCopy );
  16693. }
  16694. // uvs
  16695. for ( let i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
  16696. const faceVertexUvs2 = geometry.faceVertexUvs[ i ];
  16697. if ( this.faceVertexUvs[ i ] === undefined ) this.faceVertexUvs[ i ] = [];
  16698. for ( let j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {
  16699. const uvs2 = faceVertexUvs2[ j ], uvsCopy = [];
  16700. for ( let k = 0, kl = uvs2.length; k < kl; k ++ ) {
  16701. uvsCopy.push( uvs2[ k ].clone() );
  16702. }
  16703. this.faceVertexUvs[ i ].push( uvsCopy );
  16704. }
  16705. }
  16706. },
  16707. mergeMesh: function ( mesh ) {
  16708. if ( ! ( mesh && mesh.isMesh ) ) {
  16709. console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
  16710. return;
  16711. }
  16712. if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
  16713. this.merge( mesh.geometry, mesh.matrix );
  16714. },
  16715. /*
  16716. * Checks for duplicate vertices with hashmap.
  16717. * Duplicated vertices are removed
  16718. * and faces' vertices are updated.
  16719. */
  16720. mergeVertices: function ( precisionPoints = 4 ) {
  16721. const verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
  16722. const unique = [], changes = [];
  16723. const precision = Math.pow( 10, precisionPoints );
  16724. for ( let i = 0, il = this.vertices.length; i < il; i ++ ) {
  16725. const v = this.vertices[ i ];
  16726. const key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
  16727. if ( verticesMap[ key ] === undefined ) {
  16728. verticesMap[ key ] = i;
  16729. unique.push( this.vertices[ i ] );
  16730. changes[ i ] = unique.length - 1;
  16731. } else {
  16732. //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  16733. changes[ i ] = changes[ verticesMap[ key ] ];
  16734. }
  16735. }
  16736. // if faces are completely degenerate after merging vertices, we
  16737. // have to remove them from the geometry.
  16738. const faceIndicesToRemove = [];
  16739. for ( let i = 0, il = this.faces.length; i < il; i ++ ) {
  16740. const face = this.faces[ i ];
  16741. face.a = changes[ face.a ];
  16742. face.b = changes[ face.b ];
  16743. face.c = changes[ face.c ];
  16744. const indices = [ face.a, face.b, face.c ];
  16745. // if any duplicate vertices are found in a Face3
  16746. // we have to remove the face as nothing can be saved
  16747. for ( let n = 0; n < 3; n ++ ) {
  16748. if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
  16749. faceIndicesToRemove.push( i );
  16750. break;
  16751. }
  16752. }
  16753. }
  16754. for ( let i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
  16755. const idx = faceIndicesToRemove[ i ];
  16756. this.faces.splice( idx, 1 );
  16757. for ( let j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
  16758. this.faceVertexUvs[ j ].splice( idx, 1 );
  16759. }
  16760. }
  16761. // Use unique set of vertices
  16762. const diff = this.vertices.length - unique.length;
  16763. this.vertices = unique;
  16764. return diff;
  16765. },
  16766. setFromPoints: function ( points ) {
  16767. this.vertices = [];
  16768. for ( let i = 0, l = points.length; i < l; i ++ ) {
  16769. const point = points[ i ];
  16770. this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
  16771. }
  16772. return this;
  16773. },
  16774. sortFacesByMaterialIndex: function () {
  16775. const faces = this.faces;
  16776. const length = faces.length;
  16777. // tag faces
  16778. for ( let i = 0; i < length; i ++ ) {
  16779. faces[ i ]._id = i;
  16780. }
  16781. // sort faces
  16782. function materialIndexSort( a, b ) {
  16783. return a.materialIndex - b.materialIndex;
  16784. }
  16785. faces.sort( materialIndexSort );
  16786. // sort uvs
  16787. const uvs1 = this.faceVertexUvs[ 0 ];
  16788. const uvs2 = this.faceVertexUvs[ 1 ];
  16789. let newUvs1, newUvs2;
  16790. if ( uvs1 && uvs1.length === length ) newUvs1 = [];
  16791. if ( uvs2 && uvs2.length === length ) newUvs2 = [];
  16792. for ( let i = 0; i < length; i ++ ) {
  16793. const id = faces[ i ]._id;
  16794. if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
  16795. if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
  16796. }
  16797. if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
  16798. if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
  16799. },
  16800. toJSON: function () {
  16801. const data = {
  16802. metadata: {
  16803. version: 4.5,
  16804. type: 'Geometry',
  16805. generator: 'Geometry.toJSON'
  16806. }
  16807. };
  16808. // standard Geometry serialization
  16809. data.uuid = this.uuid;
  16810. data.type = this.type;
  16811. if ( this.name !== '' ) data.name = this.name;
  16812. if ( this.parameters !== undefined ) {
  16813. const parameters = this.parameters;
  16814. for ( const key in parameters ) {
  16815. if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
  16816. }
  16817. return data;
  16818. }
  16819. const vertices = [];
  16820. for ( let i = 0; i < this.vertices.length; i ++ ) {
  16821. const vertex = this.vertices[ i ];
  16822. vertices.push( vertex.x, vertex.y, vertex.z );
  16823. }
  16824. const faces = [];
  16825. const normals = [];
  16826. const normalsHash = {};
  16827. const colors = [];
  16828. const colorsHash = {};
  16829. const uvs = [];
  16830. const uvsHash = {};
  16831. for ( let i = 0; i < this.faces.length; i ++ ) {
  16832. const face = this.faces[ i ];
  16833. const hasMaterial = true;
  16834. const hasFaceUv = false; // deprecated
  16835. const hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
  16836. const hasFaceNormal = face.normal.length() > 0;
  16837. const hasFaceVertexNormal = face.vertexNormals.length > 0;
  16838. const hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
  16839. const hasFaceVertexColor = face.vertexColors.length > 0;
  16840. let faceType = 0;
  16841. faceType = setBit( faceType, 0, 0 ); // isQuad
  16842. faceType = setBit( faceType, 1, hasMaterial );
  16843. faceType = setBit( faceType, 2, hasFaceUv );
  16844. faceType = setBit( faceType, 3, hasFaceVertexUv );
  16845. faceType = setBit( faceType, 4, hasFaceNormal );
  16846. faceType = setBit( faceType, 5, hasFaceVertexNormal );
  16847. faceType = setBit( faceType, 6, hasFaceColor );
  16848. faceType = setBit( faceType, 7, hasFaceVertexColor );
  16849. faces.push( faceType );
  16850. faces.push( face.a, face.b, face.c );
  16851. faces.push( face.materialIndex );
  16852. if ( hasFaceVertexUv ) {
  16853. const faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
  16854. faces.push(
  16855. getUvIndex( faceVertexUvs[ 0 ] ),
  16856. getUvIndex( faceVertexUvs[ 1 ] ),
  16857. getUvIndex( faceVertexUvs[ 2 ] )
  16858. );
  16859. }
  16860. if ( hasFaceNormal ) {
  16861. faces.push( getNormalIndex( face.normal ) );
  16862. }
  16863. if ( hasFaceVertexNormal ) {
  16864. const vertexNormals = face.vertexNormals;
  16865. faces.push(
  16866. getNormalIndex( vertexNormals[ 0 ] ),
  16867. getNormalIndex( vertexNormals[ 1 ] ),
  16868. getNormalIndex( vertexNormals[ 2 ] )
  16869. );
  16870. }
  16871. if ( hasFaceColor ) {
  16872. faces.push( getColorIndex( face.color ) );
  16873. }
  16874. if ( hasFaceVertexColor ) {
  16875. const vertexColors = face.vertexColors;
  16876. faces.push(
  16877. getColorIndex( vertexColors[ 0 ] ),
  16878. getColorIndex( vertexColors[ 1 ] ),
  16879. getColorIndex( vertexColors[ 2 ] )
  16880. );
  16881. }
  16882. }
  16883. function setBit( value, position, enabled ) {
  16884. return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
  16885. }
  16886. function getNormalIndex( normal ) {
  16887. const hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
  16888. if ( normalsHash[ hash ] !== undefined ) {
  16889. return normalsHash[ hash ];
  16890. }
  16891. normalsHash[ hash ] = normals.length / 3;
  16892. normals.push( normal.x, normal.y, normal.z );
  16893. return normalsHash[ hash ];
  16894. }
  16895. function getColorIndex( color ) {
  16896. const hash = color.r.toString() + color.g.toString() + color.b.toString();
  16897. if ( colorsHash[ hash ] !== undefined ) {
  16898. return colorsHash[ hash ];
  16899. }
  16900. colorsHash[ hash ] = colors.length;
  16901. colors.push( color.getHex() );
  16902. return colorsHash[ hash ];
  16903. }
  16904. function getUvIndex( uv ) {
  16905. const hash = uv.x.toString() + uv.y.toString();
  16906. if ( uvsHash[ hash ] !== undefined ) {
  16907. return uvsHash[ hash ];
  16908. }
  16909. uvsHash[ hash ] = uvs.length / 2;
  16910. uvs.push( uv.x, uv.y );
  16911. return uvsHash[ hash ];
  16912. }
  16913. data.data = {};
  16914. data.data.vertices = vertices;
  16915. data.data.normals = normals;
  16916. if ( colors.length > 0 ) data.data.colors = colors;
  16917. if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
  16918. data.data.faces = faces;
  16919. return data;
  16920. },
  16921. clone: function () {
  16922. /*
  16923. // Handle primitives
  16924. const parameters = this.parameters;
  16925. if ( parameters !== undefined ) {
  16926. const values = [];
  16927. for ( const key in parameters ) {
  16928. values.push( parameters[ key ] );
  16929. }
  16930. const geometry = Object.create( this.constructor.prototype );
  16931. this.constructor.apply( geometry, values );
  16932. return geometry;
  16933. }
  16934. return new this.constructor().copy( this );
  16935. */
  16936. return new Geometry().copy( this );
  16937. },
  16938. copy: function ( source ) {
  16939. // reset
  16940. this.vertices = [];
  16941. this.colors = [];
  16942. this.faces = [];
  16943. this.faceVertexUvs = [[]];
  16944. this.morphTargets = [];
  16945. this.morphNormals = [];
  16946. this.skinWeights = [];
  16947. this.skinIndices = [];
  16948. this.lineDistances = [];
  16949. this.boundingBox = null;
  16950. this.boundingSphere = null;
  16951. // name
  16952. this.name = source.name;
  16953. // vertices
  16954. const vertices = source.vertices;
  16955. for ( let i = 0, il = vertices.length; i < il; i ++ ) {
  16956. this.vertices.push( vertices[ i ].clone() );
  16957. }
  16958. // colors
  16959. const colors = source.colors;
  16960. for ( let i = 0, il = colors.length; i < il; i ++ ) {
  16961. this.colors.push( colors[ i ].clone() );
  16962. }
  16963. // faces
  16964. const faces = source.faces;
  16965. for ( let i = 0, il = faces.length; i < il; i ++ ) {
  16966. this.faces.push( faces[ i ].clone() );
  16967. }
  16968. // face vertex uvs
  16969. for ( let i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
  16970. const faceVertexUvs = source.faceVertexUvs[ i ];
  16971. if ( this.faceVertexUvs[ i ] === undefined ) {
  16972. this.faceVertexUvs[ i ] = [];
  16973. }
  16974. for ( let j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
  16975. const uvs = faceVertexUvs[ j ], uvsCopy = [];
  16976. for ( let k = 0, kl = uvs.length; k < kl; k ++ ) {
  16977. const uv = uvs[ k ];
  16978. uvsCopy.push( uv.clone() );
  16979. }
  16980. this.faceVertexUvs[ i ].push( uvsCopy );
  16981. }
  16982. }
  16983. // morph targets
  16984. const morphTargets = source.morphTargets;
  16985. for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
  16986. const morphTarget = {};
  16987. morphTarget.name = morphTargets[ i ].name;
  16988. // vertices
  16989. if ( morphTargets[ i ].vertices !== undefined ) {
  16990. morphTarget.vertices = [];
  16991. for ( let j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
  16992. morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
  16993. }
  16994. }
  16995. // normals
  16996. if ( morphTargets[ i ].normals !== undefined ) {
  16997. morphTarget.normals = [];
  16998. for ( let j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
  16999. morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
  17000. }
  17001. }
  17002. this.morphTargets.push( morphTarget );
  17003. }
  17004. // morph normals
  17005. const morphNormals = source.morphNormals;
  17006. for ( let i = 0, il = morphNormals.length; i < il; i ++ ) {
  17007. const morphNormal = {};
  17008. // vertex normals
  17009. if ( morphNormals[ i ].vertexNormals !== undefined ) {
  17010. morphNormal.vertexNormals = [];
  17011. for ( let j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
  17012. const srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
  17013. const destVertexNormal = {};
  17014. destVertexNormal.a = srcVertexNormal.a.clone();
  17015. destVertexNormal.b = srcVertexNormal.b.clone();
  17016. destVertexNormal.c = srcVertexNormal.c.clone();
  17017. morphNormal.vertexNormals.push( destVertexNormal );
  17018. }
  17019. }
  17020. // face normals
  17021. if ( morphNormals[ i ].faceNormals !== undefined ) {
  17022. morphNormal.faceNormals = [];
  17023. for ( let j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
  17024. morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
  17025. }
  17026. }
  17027. this.morphNormals.push( morphNormal );
  17028. }
  17029. // skin weights
  17030. const skinWeights = source.skinWeights;
  17031. for ( let i = 0, il = skinWeights.length; i < il; i ++ ) {
  17032. this.skinWeights.push( skinWeights[ i ].clone() );
  17033. }
  17034. // skin indices
  17035. const skinIndices = source.skinIndices;
  17036. for ( let i = 0, il = skinIndices.length; i < il; i ++ ) {
  17037. this.skinIndices.push( skinIndices[ i ].clone() );
  17038. }
  17039. // line distances
  17040. const lineDistances = source.lineDistances;
  17041. for ( let i = 0, il = lineDistances.length; i < il; i ++ ) {
  17042. this.lineDistances.push( lineDistances[ i ] );
  17043. }
  17044. // bounding box
  17045. const boundingBox = source.boundingBox;
  17046. if ( boundingBox !== null ) {
  17047. this.boundingBox = boundingBox.clone();
  17048. }
  17049. // bounding sphere
  17050. const boundingSphere = source.boundingSphere;
  17051. if ( boundingSphere !== null ) {
  17052. this.boundingSphere = boundingSphere.clone();
  17053. }
  17054. // update flags
  17055. this.elementsNeedUpdate = source.elementsNeedUpdate;
  17056. this.verticesNeedUpdate = source.verticesNeedUpdate;
  17057. this.uvsNeedUpdate = source.uvsNeedUpdate;
  17058. this.normalsNeedUpdate = source.normalsNeedUpdate;
  17059. this.colorsNeedUpdate = source.colorsNeedUpdate;
  17060. this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
  17061. this.groupsNeedUpdate = source.groupsNeedUpdate;
  17062. return this;
  17063. },
  17064. dispose: function () {
  17065. this.dispatchEvent( { type: 'dispose' } );
  17066. }
  17067. } );
  17068. class BoxGeometry extends Geometry {
  17069. constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {
  17070. super();
  17071. this.type = 'BoxGeometry';
  17072. this.parameters = {
  17073. width: width,
  17074. height: height,
  17075. depth: depth,
  17076. widthSegments: widthSegments,
  17077. heightSegments: heightSegments,
  17078. depthSegments: depthSegments
  17079. };
  17080. this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
  17081. this.mergeVertices();
  17082. }
  17083. }
  17084. class CircleBufferGeometry extends BufferGeometry {
  17085. constructor( radius = 1, segments = 8, thetaStart = 0, thetaLength = Math.PI * 2 ) {
  17086. super();
  17087. this.type = 'CircleBufferGeometry';
  17088. this.parameters = {
  17089. radius: radius,
  17090. segments: segments,
  17091. thetaStart: thetaStart,
  17092. thetaLength: thetaLength
  17093. };
  17094. segments = Math.max( 3, segments );
  17095. // buffers
  17096. const indices = [];
  17097. const vertices = [];
  17098. const normals = [];
  17099. const uvs = [];
  17100. // helper variables
  17101. const vertex = new Vector3();
  17102. const uv = new Vector2();
  17103. // center point
  17104. vertices.push( 0, 0, 0 );
  17105. normals.push( 0, 0, 1 );
  17106. uvs.push( 0.5, 0.5 );
  17107. for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
  17108. const segment = thetaStart + s / segments * thetaLength;
  17109. // vertex
  17110. vertex.x = radius * Math.cos( segment );
  17111. vertex.y = radius * Math.sin( segment );
  17112. vertices.push( vertex.x, vertex.y, vertex.z );
  17113. // normal
  17114. normals.push( 0, 0, 1 );
  17115. // uvs
  17116. uv.x = ( vertices[ i ] / radius + 1 ) / 2;
  17117. uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
  17118. uvs.push( uv.x, uv.y );
  17119. }
  17120. // indices
  17121. for ( let i = 1; i <= segments; i ++ ) {
  17122. indices.push( i, i + 1, 0 );
  17123. }
  17124. // build geometry
  17125. this.setIndex( indices );
  17126. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  17127. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  17128. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  17129. }
  17130. }
  17131. class CircleGeometry extends Geometry {
  17132. constructor( radius, segments, thetaStart, thetaLength ) {
  17133. super();
  17134. this.type = 'CircleGeometry';
  17135. this.parameters = {
  17136. radius: radius,
  17137. segments: segments,
  17138. thetaStart: thetaStart,
  17139. thetaLength: thetaLength
  17140. };
  17141. this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
  17142. this.mergeVertices();
  17143. }
  17144. }
  17145. class CylinderBufferGeometry extends BufferGeometry {
  17146. constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
  17147. super();
  17148. this.type = 'CylinderBufferGeometry';
  17149. this.parameters = {
  17150. radiusTop: radiusTop,
  17151. radiusBottom: radiusBottom,
  17152. height: height,
  17153. radialSegments: radialSegments,
  17154. heightSegments: heightSegments,
  17155. openEnded: openEnded,
  17156. thetaStart: thetaStart,
  17157. thetaLength: thetaLength
  17158. };
  17159. const scope = this;
  17160. radialSegments = Math.floor( radialSegments );
  17161. heightSegments = Math.floor( heightSegments );
  17162. // buffers
  17163. const indices = [];
  17164. const vertices = [];
  17165. const normals = [];
  17166. const uvs = [];
  17167. // helper variables
  17168. let index = 0;
  17169. const indexArray = [];
  17170. const halfHeight = height / 2;
  17171. let groupStart = 0;
  17172. // generate geometry
  17173. generateTorso();
  17174. if ( openEnded === false ) {
  17175. if ( radiusTop > 0 ) generateCap( true );
  17176. if ( radiusBottom > 0 ) generateCap( false );
  17177. }
  17178. // build geometry
  17179. this.setIndex( indices );
  17180. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  17181. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  17182. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  17183. function generateTorso() {
  17184. const normal = new Vector3();
  17185. const vertex = new Vector3();
  17186. let groupCount = 0;
  17187. // this will be used to calculate the normal
  17188. const slope = ( radiusBottom - radiusTop ) / height;
  17189. // generate vertices, normals and uvs
  17190. for ( let y = 0; y <= heightSegments; y ++ ) {
  17191. const indexRow = [];
  17192. const v = y / heightSegments;
  17193. // calculate the radius of the current row
  17194. const radius = v * ( radiusBottom - radiusTop ) + radiusTop;
  17195. for ( let x = 0; x <= radialSegments; x ++ ) {
  17196. const u = x / radialSegments;
  17197. const theta = u * thetaLength + thetaStart;
  17198. const sinTheta = Math.sin( theta );
  17199. const cosTheta = Math.cos( theta );
  17200. // vertex
  17201. vertex.x = radius * sinTheta;
  17202. vertex.y = - v * height + halfHeight;
  17203. vertex.z = radius * cosTheta;
  17204. vertices.push( vertex.x, vertex.y, vertex.z );
  17205. // normal
  17206. normal.set( sinTheta, slope, cosTheta ).normalize();
  17207. normals.push( normal.x, normal.y, normal.z );
  17208. // uv
  17209. uvs.push( u, 1 - v );
  17210. // save index of vertex in respective row
  17211. indexRow.push( index ++ );
  17212. }
  17213. // now save vertices of the row in our index array
  17214. indexArray.push( indexRow );
  17215. }
  17216. // generate indices
  17217. for ( let x = 0; x < radialSegments; x ++ ) {
  17218. for ( let y = 0; y < heightSegments; y ++ ) {
  17219. // we use the index array to access the correct indices
  17220. const a = indexArray[ y ][ x ];
  17221. const b = indexArray[ y + 1 ][ x ];
  17222. const c = indexArray[ y + 1 ][ x + 1 ];
  17223. const d = indexArray[ y ][ x + 1 ];
  17224. // faces
  17225. indices.push( a, b, d );
  17226. indices.push( b, c, d );
  17227. // update group counter
  17228. groupCount += 6;
  17229. }
  17230. }
  17231. // add a group to the geometry. this will ensure multi material support
  17232. scope.addGroup( groupStart, groupCount, 0 );
  17233. // calculate new start value for groups
  17234. groupStart += groupCount;
  17235. }
  17236. function generateCap( top ) {
  17237. // save the index of the first center vertex
  17238. const centerIndexStart = index;
  17239. const uv = new Vector2();
  17240. const vertex = new Vector3();
  17241. let groupCount = 0;
  17242. const radius = ( top === true ) ? radiusTop : radiusBottom;
  17243. const sign = ( top === true ) ? 1 : - 1;
  17244. // first we generate the center vertex data of the cap.
  17245. // because the geometry needs one set of uvs per face,
  17246. // we must generate a center vertex per face/segment
  17247. for ( let x = 1; x <= radialSegments; x ++ ) {
  17248. // vertex
  17249. vertices.push( 0, halfHeight * sign, 0 );
  17250. // normal
  17251. normals.push( 0, sign, 0 );
  17252. // uv
  17253. uvs.push( 0.5, 0.5 );
  17254. // increase index
  17255. index ++;
  17256. }
  17257. // save the index of the last center vertex
  17258. const centerIndexEnd = index;
  17259. // now we generate the surrounding vertices, normals and uvs
  17260. for ( let x = 0; x <= radialSegments; x ++ ) {
  17261. const u = x / radialSegments;
  17262. const theta = u * thetaLength + thetaStart;
  17263. const cosTheta = Math.cos( theta );
  17264. const sinTheta = Math.sin( theta );
  17265. // vertex
  17266. vertex.x = radius * sinTheta;
  17267. vertex.y = halfHeight * sign;
  17268. vertex.z = radius * cosTheta;
  17269. vertices.push( vertex.x, vertex.y, vertex.z );
  17270. // normal
  17271. normals.push( 0, sign, 0 );
  17272. // uv
  17273. uv.x = ( cosTheta * 0.5 ) + 0.5;
  17274. uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
  17275. uvs.push( uv.x, uv.y );
  17276. // increase index
  17277. index ++;
  17278. }
  17279. // generate indices
  17280. for ( let x = 0; x < radialSegments; x ++ ) {
  17281. const c = centerIndexStart + x;
  17282. const i = centerIndexEnd + x;
  17283. if ( top === true ) {
  17284. // face top
  17285. indices.push( i, i + 1, c );
  17286. } else {
  17287. // face bottom
  17288. indices.push( i + 1, i, c );
  17289. }
  17290. groupCount += 3;
  17291. }
  17292. // add a group to the geometry. this will ensure multi material support
  17293. scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
  17294. // calculate new start value for groups
  17295. groupStart += groupCount;
  17296. }
  17297. }
  17298. }
  17299. class CylinderGeometry extends Geometry {
  17300. constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
  17301. super();
  17302. this.type = 'CylinderGeometry';
  17303. this.parameters = {
  17304. radiusTop: radiusTop,
  17305. radiusBottom: radiusBottom,
  17306. height: height,
  17307. radialSegments: radialSegments,
  17308. heightSegments: heightSegments,
  17309. openEnded: openEnded,
  17310. thetaStart: thetaStart,
  17311. thetaLength: thetaLength
  17312. };
  17313. this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
  17314. this.mergeVertices();
  17315. }
  17316. }
  17317. class ConeGeometry extends CylinderGeometry {
  17318. constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
  17319. super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
  17320. this.type = 'ConeGeometry';
  17321. this.parameters = {
  17322. radius: radius,
  17323. height: height,
  17324. radialSegments: radialSegments,
  17325. heightSegments: heightSegments,
  17326. openEnded: openEnded,
  17327. thetaStart: thetaStart,
  17328. thetaLength: thetaLength
  17329. };
  17330. }
  17331. }
  17332. class ConeBufferGeometry extends CylinderBufferGeometry {
  17333. constructor( radius = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
  17334. super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
  17335. this.type = 'ConeBufferGeometry';
  17336. this.parameters = {
  17337. radius: radius,
  17338. height: height,
  17339. radialSegments: radialSegments,
  17340. heightSegments: heightSegments,
  17341. openEnded: openEnded,
  17342. thetaStart: thetaStart,
  17343. thetaLength: thetaLength
  17344. };
  17345. }
  17346. }
  17347. class PolyhedronBufferGeometry extends BufferGeometry {
  17348. constructor( vertices, indices, radius = 1, detail = 0 ) {
  17349. super();
  17350. this.type = 'PolyhedronBufferGeometry';
  17351. this.parameters = {
  17352. vertices: vertices,
  17353. indices: indices,
  17354. radius: radius,
  17355. detail: detail
  17356. };
  17357. // default buffer data
  17358. const vertexBuffer = [];
  17359. const uvBuffer = [];
  17360. // the subdivision creates the vertex buffer data
  17361. subdivide( detail );
  17362. // all vertices should lie on a conceptual sphere with a given radius
  17363. applyRadius( radius );
  17364. // finally, create the uv data
  17365. generateUVs();
  17366. // build non-indexed geometry
  17367. this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
  17368. this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
  17369. this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
  17370. if ( detail === 0 ) {
  17371. this.computeVertexNormals(); // flat normals
  17372. } else {
  17373. this.normalizeNormals(); // smooth normals
  17374. }
  17375. // helper functions
  17376. function subdivide( detail ) {
  17377. const a = new Vector3();
  17378. const b = new Vector3();
  17379. const c = new Vector3();
  17380. // iterate over all faces and apply a subdivison with the given detail value
  17381. for ( let i = 0; i < indices.length; i += 3 ) {
  17382. // get the vertices of the face
  17383. getVertexByIndex( indices[ i + 0 ], a );
  17384. getVertexByIndex( indices[ i + 1 ], b );
  17385. getVertexByIndex( indices[ i + 2 ], c );
  17386. // perform subdivision
  17387. subdivideFace( a, b, c, detail );
  17388. }
  17389. }
  17390. function subdivideFace( a, b, c, detail ) {
  17391. const cols = detail + 1;
  17392. // we use this multidimensional array as a data structure for creating the subdivision
  17393. const v = [];
  17394. // construct all of the vertices for this subdivision
  17395. for ( let i = 0; i <= cols; i ++ ) {
  17396. v[ i ] = [];
  17397. const aj = a.clone().lerp( c, i / cols );
  17398. const bj = b.clone().lerp( c, i / cols );
  17399. const rows = cols - i;
  17400. for ( let j = 0; j <= rows; j ++ ) {
  17401. if ( j === 0 && i === cols ) {
  17402. v[ i ][ j ] = aj;
  17403. } else {
  17404. v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
  17405. }
  17406. }
  17407. }
  17408. // construct all of the faces
  17409. for ( let i = 0; i < cols; i ++ ) {
  17410. for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
  17411. const k = Math.floor( j / 2 );
  17412. if ( j % 2 === 0 ) {
  17413. pushVertex( v[ i ][ k + 1 ] );
  17414. pushVertex( v[ i + 1 ][ k ] );
  17415. pushVertex( v[ i ][ k ] );
  17416. } else {
  17417. pushVertex( v[ i ][ k + 1 ] );
  17418. pushVertex( v[ i + 1 ][ k + 1 ] );
  17419. pushVertex( v[ i + 1 ][ k ] );
  17420. }
  17421. }
  17422. }
  17423. }
  17424. function applyRadius( radius ) {
  17425. const vertex = new Vector3();
  17426. // iterate over the entire buffer and apply the radius to each vertex
  17427. for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
  17428. vertex.x = vertexBuffer[ i + 0 ];
  17429. vertex.y = vertexBuffer[ i + 1 ];
  17430. vertex.z = vertexBuffer[ i + 2 ];
  17431. vertex.normalize().multiplyScalar( radius );
  17432. vertexBuffer[ i + 0 ] = vertex.x;
  17433. vertexBuffer[ i + 1 ] = vertex.y;
  17434. vertexBuffer[ i + 2 ] = vertex.z;
  17435. }
  17436. }
  17437. function generateUVs() {
  17438. const vertex = new Vector3();
  17439. for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
  17440. vertex.x = vertexBuffer[ i + 0 ];
  17441. vertex.y = vertexBuffer[ i + 1 ];
  17442. vertex.z = vertexBuffer[ i + 2 ];
  17443. const u = azimuth( vertex ) / 2 / Math.PI + 0.5;
  17444. const v = inclination( vertex ) / Math.PI + 0.5;
  17445. uvBuffer.push( u, 1 - v );
  17446. }
  17447. correctUVs();
  17448. correctSeam();
  17449. }
  17450. function correctSeam() {
  17451. // handle case when face straddles the seam, see #3269
  17452. for ( let i = 0; i < uvBuffer.length; i += 6 ) {
  17453. // uv data of a single face
  17454. const x0 = uvBuffer[ i + 0 ];
  17455. const x1 = uvBuffer[ i + 2 ];
  17456. const x2 = uvBuffer[ i + 4 ];
  17457. const max = Math.max( x0, x1, x2 );
  17458. const min = Math.min( x0, x1, x2 );
  17459. // 0.9 is somewhat arbitrary
  17460. if ( max > 0.9 && min < 0.1 ) {
  17461. if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
  17462. if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
  17463. if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
  17464. }
  17465. }
  17466. }
  17467. function pushVertex( vertex ) {
  17468. vertexBuffer.push( vertex.x, vertex.y, vertex.z );
  17469. }
  17470. function getVertexByIndex( index, vertex ) {
  17471. const stride = index * 3;
  17472. vertex.x = vertices[ stride + 0 ];
  17473. vertex.y = vertices[ stride + 1 ];
  17474. vertex.z = vertices[ stride + 2 ];
  17475. }
  17476. function correctUVs() {
  17477. const a = new Vector3();
  17478. const b = new Vector3();
  17479. const c = new Vector3();
  17480. const centroid = new Vector3();
  17481. const uvA = new Vector2();
  17482. const uvB = new Vector2();
  17483. const uvC = new Vector2();
  17484. for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
  17485. a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
  17486. b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
  17487. c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
  17488. uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
  17489. uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
  17490. uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
  17491. centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
  17492. const azi = azimuth( centroid );
  17493. correctUV( uvA, j + 0, a, azi );
  17494. correctUV( uvB, j + 2, b, azi );
  17495. correctUV( uvC, j + 4, c, azi );
  17496. }
  17497. }
  17498. function correctUV( uv, stride, vector, azimuth ) {
  17499. if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
  17500. uvBuffer[ stride ] = uv.x - 1;
  17501. }
  17502. if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
  17503. uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
  17504. }
  17505. }
  17506. // Angle around the Y axis, counter-clockwise when looking from above.
  17507. function azimuth( vector ) {
  17508. return Math.atan2( vector.z, - vector.x );
  17509. }
  17510. // Angle above the XZ plane.
  17511. function inclination( vector ) {
  17512. return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
  17513. }
  17514. }
  17515. }
  17516. class DodecahedronBufferGeometry extends PolyhedronBufferGeometry {
  17517. constructor( radius = 1, detail = 0 ) {
  17518. const t = ( 1 + Math.sqrt( 5 ) ) / 2;
  17519. const r = 1 / t;
  17520. const vertices = [
  17521. // (±1, ±1, ±1)
  17522. - 1, - 1, - 1, - 1, - 1, 1,
  17523. - 1, 1, - 1, - 1, 1, 1,
  17524. 1, - 1, - 1, 1, - 1, 1,
  17525. 1, 1, - 1, 1, 1, 1,
  17526. // (0, ±1/φ, ±φ)
  17527. 0, - r, - t, 0, - r, t,
  17528. 0, r, - t, 0, r, t,
  17529. // (±1/φ, ±φ, 0)
  17530. - r, - t, 0, - r, t, 0,
  17531. r, - t, 0, r, t, 0,
  17532. // (±φ, 0, ±1/φ)
  17533. - t, 0, - r, t, 0, - r,
  17534. - t, 0, r, t, 0, r
  17535. ];
  17536. const indices = [
  17537. 3, 11, 7, 3, 7, 15, 3, 15, 13,
  17538. 7, 19, 17, 7, 17, 6, 7, 6, 15,
  17539. 17, 4, 8, 17, 8, 10, 17, 10, 6,
  17540. 8, 0, 16, 8, 16, 2, 8, 2, 10,
  17541. 0, 12, 1, 0, 1, 18, 0, 18, 16,
  17542. 6, 10, 2, 6, 2, 13, 6, 13, 15,
  17543. 2, 16, 18, 2, 18, 3, 2, 3, 13,
  17544. 18, 1, 9, 18, 9, 11, 18, 11, 3,
  17545. 4, 14, 12, 4, 12, 0, 4, 0, 8,
  17546. 11, 9, 5, 11, 5, 19, 11, 19, 7,
  17547. 19, 5, 14, 19, 14, 4, 19, 4, 17,
  17548. 1, 12, 14, 1, 14, 5, 1, 5, 9
  17549. ];
  17550. super( vertices, indices, radius, detail );
  17551. this.type = 'DodecahedronBufferGeometry';
  17552. this.parameters = {
  17553. radius: radius,
  17554. detail: detail
  17555. };
  17556. }
  17557. }
  17558. class DodecahedronGeometry extends Geometry {
  17559. constructor( radius, detail ) {
  17560. super();
  17561. this.type = 'DodecahedronGeometry';
  17562. this.parameters = {
  17563. radius: radius,
  17564. detail: detail
  17565. };
  17566. this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
  17567. this.mergeVertices();
  17568. }
  17569. }
  17570. const _v0$2 = new Vector3();
  17571. const _v1$5 = new Vector3();
  17572. const _normal$1 = new Vector3();
  17573. const _triangle = new Triangle();
  17574. class EdgesGeometry extends BufferGeometry {
  17575. constructor( geometry, thresholdAngle ) {
  17576. super();
  17577. this.type = 'EdgesGeometry';
  17578. this.parameters = {
  17579. thresholdAngle: thresholdAngle
  17580. };
  17581. thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
  17582. if ( geometry.isGeometry ) {
  17583. geometry = new BufferGeometry().fromGeometry( geometry );
  17584. }
  17585. const precisionPoints = 4;
  17586. const precision = Math.pow( 10, precisionPoints );
  17587. const thresholdDot = Math.cos( MathUtils$1.DEG2RAD * thresholdAngle );
  17588. const indexAttr = geometry.getIndex();
  17589. const positionAttr = geometry.getAttribute( 'position' );
  17590. const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
  17591. const indexArr = [ 0, 0, 0 ];
  17592. const vertKeys = [ 'a', 'b', 'c' ];
  17593. const hashes = new Array( 3 );
  17594. const edgeData = {};
  17595. const vertices = [];
  17596. for ( let i = 0; i < indexCount; i += 3 ) {
  17597. if ( indexAttr ) {
  17598. indexArr[ 0 ] = indexAttr.getX( i );
  17599. indexArr[ 1 ] = indexAttr.getX( i + 1 );
  17600. indexArr[ 2 ] = indexAttr.getX( i + 2 );
  17601. } else {
  17602. indexArr[ 0 ] = i;
  17603. indexArr[ 1 ] = i + 1;
  17604. indexArr[ 2 ] = i + 2;
  17605. }
  17606. const { a, b, c } = _triangle;
  17607. a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
  17608. b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
  17609. c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
  17610. _triangle.getNormal( _normal$1 );
  17611. // create hashes for the edge from the vertices
  17612. hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`;
  17613. hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`;
  17614. hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`;
  17615. // skip degenerate triangles
  17616. if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
  17617. continue;
  17618. }
  17619. // iterate over every edge
  17620. for ( let j = 0; j < 3; j ++ ) {
  17621. // get the first and next vertex making up the edge
  17622. const jNext = ( j + 1 ) % 3;
  17623. const vecHash0 = hashes[ j ];
  17624. const vecHash1 = hashes[ jNext ];
  17625. const v0 = _triangle[ vertKeys[ j ] ];
  17626. const v1 = _triangle[ vertKeys[ jNext ] ];
  17627. const hash = `${ vecHash0 }_${ vecHash1 }`;
  17628. const reverseHash = `${ vecHash1 }_${ vecHash0 }`;
  17629. if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
  17630. // if we found a sibling edge add it into the vertex array if
  17631. // it meets the angle threshold and delete the edge from the map.
  17632. if ( _normal$1.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
  17633. vertices.push( v0.x, v0.y, v0.z );
  17634. vertices.push( v1.x, v1.y, v1.z );
  17635. }
  17636. edgeData[ reverseHash ] = null;
  17637. } else if ( ! ( hash in edgeData ) ) {
  17638. // if we've already got an edge here then skip adding a new one
  17639. edgeData[ hash ] = {
  17640. index0: indexArr[ j ],
  17641. index1: indexArr[ jNext ],
  17642. normal: _normal$1.clone(),
  17643. };
  17644. }
  17645. }
  17646. }
  17647. // iterate over all remaining, unmatched edges and add them to the vertex array
  17648. for ( const key in edgeData ) {
  17649. if ( edgeData[ key ] ) {
  17650. const { index0, index1 } = edgeData[ key ];
  17651. _v0$2.fromBufferAttribute( positionAttr, index0 );
  17652. _v1$5.fromBufferAttribute( positionAttr, index1 );
  17653. vertices.push( _v0$2.x, _v0$2.y, _v0$2.z );
  17654. vertices.push( _v1$5.x, _v1$5.y, _v1$5.z );
  17655. }
  17656. }
  17657. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  17658. }
  17659. }
  17660. /**
  17661. * Port from https://github.com/mapbox/earcut (v2.2.2)
  17662. */
  17663. const Earcut = {
  17664. triangulate: function ( data, holeIndices, dim ) {
  17665. dim = dim || 2;
  17666. const hasHoles = holeIndices && holeIndices.length;
  17667. const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
  17668. let outerNode = linkedList( data, 0, outerLen, dim, true );
  17669. const triangles = [];
  17670. if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
  17671. let minX, minY, maxX, maxY, x, y, invSize;
  17672. if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
  17673. // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
  17674. if ( data.length > 80 * dim ) {
  17675. minX = maxX = data[ 0 ];
  17676. minY = maxY = data[ 1 ];
  17677. for ( let i = dim; i < outerLen; i += dim ) {
  17678. x = data[ i ];
  17679. y = data[ i + 1 ];
  17680. if ( x < minX ) minX = x;
  17681. if ( y < minY ) minY = y;
  17682. if ( x > maxX ) maxX = x;
  17683. if ( y > maxY ) maxY = y;
  17684. }
  17685. // minX, minY and invSize are later used to transform coords into integers for z-order calculation
  17686. invSize = Math.max( maxX - minX, maxY - minY );
  17687. invSize = invSize !== 0 ? 1 / invSize : 0;
  17688. }
  17689. earcutLinked( outerNode, triangles, dim, minX, minY, invSize );
  17690. return triangles;
  17691. }
  17692. };
  17693. // create a circular doubly linked list from polygon points in the specified winding order
  17694. function linkedList( data, start, end, dim, clockwise ) {
  17695. let i, last;
  17696. if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
  17697. for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
  17698. } else {
  17699. for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
  17700. }
  17701. if ( last && equals( last, last.next ) ) {
  17702. removeNode( last );
  17703. last = last.next;
  17704. }
  17705. return last;
  17706. }
  17707. // eliminate colinear or duplicate points
  17708. function filterPoints( start, end ) {
  17709. if ( ! start ) return start;
  17710. if ( ! end ) end = start;
  17711. let p = start,
  17712. again;
  17713. do {
  17714. again = false;
  17715. if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
  17716. removeNode( p );
  17717. p = end = p.prev;
  17718. if ( p === p.next ) break;
  17719. again = true;
  17720. } else {
  17721. p = p.next;
  17722. }
  17723. } while ( again || p !== end );
  17724. return end;
  17725. }
  17726. // main ear slicing loop which triangulates a polygon (given as a linked list)
  17727. function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
  17728. if ( ! ear ) return;
  17729. // interlink polygon nodes in z-order
  17730. if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
  17731. let stop = ear,
  17732. prev, next;
  17733. // iterate through ears, slicing them one by one
  17734. while ( ear.prev !== ear.next ) {
  17735. prev = ear.prev;
  17736. next = ear.next;
  17737. if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
  17738. // cut off the triangle
  17739. triangles.push( prev.i / dim );
  17740. triangles.push( ear.i / dim );
  17741. triangles.push( next.i / dim );
  17742. removeNode( ear );
  17743. // skipping the next vertex leads to less sliver triangles
  17744. ear = next.next;
  17745. stop = next.next;
  17746. continue;
  17747. }
  17748. ear = next;
  17749. // if we looped through the whole remaining polygon and can't find any more ears
  17750. if ( ear === stop ) {
  17751. // try filtering points and slicing again
  17752. if ( ! pass ) {
  17753. earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
  17754. // if this didn't work, try curing all small self-intersections locally
  17755. } else if ( pass === 1 ) {
  17756. ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
  17757. earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
  17758. // as a last resort, try splitting the remaining polygon into two
  17759. } else if ( pass === 2 ) {
  17760. splitEarcut( ear, triangles, dim, minX, minY, invSize );
  17761. }
  17762. break;
  17763. }
  17764. }
  17765. }
  17766. // check whether a polygon node forms a valid ear with adjacent nodes
  17767. function isEar( ear ) {
  17768. const a = ear.prev,
  17769. b = ear,
  17770. c = ear.next;
  17771. if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
  17772. // now make sure we don't have other points inside the potential ear
  17773. let p = ear.next.next;
  17774. while ( p !== ear.prev ) {
  17775. if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
  17776. area( p.prev, p, p.next ) >= 0 ) return false;
  17777. p = p.next;
  17778. }
  17779. return true;
  17780. }
  17781. function isEarHashed( ear, minX, minY, invSize ) {
  17782. const a = ear.prev,
  17783. b = ear,
  17784. c = ear.next;
  17785. if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
  17786. // triangle bbox; min & max are calculated like this for speed
  17787. const minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
  17788. minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
  17789. maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
  17790. maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
  17791. // z-order range for the current triangle bbox;
  17792. const minZ = zOrder( minTX, minTY, minX, minY, invSize ),
  17793. maxZ = zOrder( maxTX, maxTY, minX, minY, invSize );
  17794. let p = ear.prevZ,
  17795. n = ear.nextZ;
  17796. // look for points inside the triangle in both directions
  17797. while ( p && p.z >= minZ && n && n.z <= maxZ ) {
  17798. if ( p !== ear.prev && p !== ear.next &&
  17799. pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
  17800. area( p.prev, p, p.next ) >= 0 ) return false;
  17801. p = p.prevZ;
  17802. if ( n !== ear.prev && n !== ear.next &&
  17803. pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
  17804. area( n.prev, n, n.next ) >= 0 ) return false;
  17805. n = n.nextZ;
  17806. }
  17807. // look for remaining points in decreasing z-order
  17808. while ( p && p.z >= minZ ) {
  17809. if ( p !== ear.prev && p !== ear.next &&
  17810. pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
  17811. area( p.prev, p, p.next ) >= 0 ) return false;
  17812. p = p.prevZ;
  17813. }
  17814. // look for remaining points in increasing z-order
  17815. while ( n && n.z <= maxZ ) {
  17816. if ( n !== ear.prev && n !== ear.next &&
  17817. pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
  17818. area( n.prev, n, n.next ) >= 0 ) return false;
  17819. n = n.nextZ;
  17820. }
  17821. return true;
  17822. }
  17823. // go through all polygon nodes and cure small local self-intersections
  17824. function cureLocalIntersections( start, triangles, dim ) {
  17825. let p = start;
  17826. do {
  17827. const a = p.prev,
  17828. b = p.next.next;
  17829. if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
  17830. triangles.push( a.i / dim );
  17831. triangles.push( p.i / dim );
  17832. triangles.push( b.i / dim );
  17833. // remove two nodes involved
  17834. removeNode( p );
  17835. removeNode( p.next );
  17836. p = start = b;
  17837. }
  17838. p = p.next;
  17839. } while ( p !== start );
  17840. return filterPoints( p );
  17841. }
  17842. // try splitting polygon into two and triangulate them independently
  17843. function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
  17844. // look for a valid diagonal that divides the polygon into two
  17845. let a = start;
  17846. do {
  17847. let b = a.next.next;
  17848. while ( b !== a.prev ) {
  17849. if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
  17850. // split the polygon in two by the diagonal
  17851. let c = splitPolygon( a, b );
  17852. // filter colinear points around the cuts
  17853. a = filterPoints( a, a.next );
  17854. c = filterPoints( c, c.next );
  17855. // run earcut on each half
  17856. earcutLinked( a, triangles, dim, minX, minY, invSize );
  17857. earcutLinked( c, triangles, dim, minX, minY, invSize );
  17858. return;
  17859. }
  17860. b = b.next;
  17861. }
  17862. a = a.next;
  17863. } while ( a !== start );
  17864. }
  17865. // link every hole into the outer loop, producing a single-ring polygon without holes
  17866. function eliminateHoles( data, holeIndices, outerNode, dim ) {
  17867. const queue = [];
  17868. let i, len, start, end, list;
  17869. for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
  17870. start = holeIndices[ i ] * dim;
  17871. end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
  17872. list = linkedList( data, start, end, dim, false );
  17873. if ( list === list.next ) list.steiner = true;
  17874. queue.push( getLeftmost( list ) );
  17875. }
  17876. queue.sort( compareX );
  17877. // process holes from left to right
  17878. for ( i = 0; i < queue.length; i ++ ) {
  17879. eliminateHole( queue[ i ], outerNode );
  17880. outerNode = filterPoints( outerNode, outerNode.next );
  17881. }
  17882. return outerNode;
  17883. }
  17884. function compareX( a, b ) {
  17885. return a.x - b.x;
  17886. }
  17887. // find a bridge between vertices that connects hole with an outer ring and and link it
  17888. function eliminateHole( hole, outerNode ) {
  17889. outerNode = findHoleBridge( hole, outerNode );
  17890. if ( outerNode ) {
  17891. const b = splitPolygon( outerNode, hole );
  17892. // filter collinear points around the cuts
  17893. filterPoints( outerNode, outerNode.next );
  17894. filterPoints( b, b.next );
  17895. }
  17896. }
  17897. // David Eberly's algorithm for finding a bridge between hole and outer polygon
  17898. function findHoleBridge( hole, outerNode ) {
  17899. let p = outerNode;
  17900. const hx = hole.x;
  17901. const hy = hole.y;
  17902. let qx = - Infinity, m;
  17903. // find a segment intersected by a ray from the hole's leftmost point to the left;
  17904. // segment's endpoint with lesser x will be potential connection point
  17905. do {
  17906. if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
  17907. const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
  17908. if ( x <= hx && x > qx ) {
  17909. qx = x;
  17910. if ( x === hx ) {
  17911. if ( hy === p.y ) return p;
  17912. if ( hy === p.next.y ) return p.next;
  17913. }
  17914. m = p.x < p.next.x ? p : p.next;
  17915. }
  17916. }
  17917. p = p.next;
  17918. } while ( p !== outerNode );
  17919. if ( ! m ) return null;
  17920. if ( hx === qx ) return m; // hole touches outer segment; pick leftmost endpoint
  17921. // look for points inside the triangle of hole point, segment intersection and endpoint;
  17922. // if there are no points found, we have a valid connection;
  17923. // otherwise choose the point of the minimum angle with the ray as connection point
  17924. const stop = m,
  17925. mx = m.x,
  17926. my = m.y;
  17927. let tanMin = Infinity, tan;
  17928. p = m;
  17929. do {
  17930. if ( hx >= p.x && p.x >= mx && hx !== p.x &&
  17931. pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
  17932. tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
  17933. if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) {
  17934. m = p;
  17935. tanMin = tan;
  17936. }
  17937. }
  17938. p = p.next;
  17939. } while ( p !== stop );
  17940. return m;
  17941. }
  17942. // whether sector in vertex m contains sector in vertex p in the same coordinates
  17943. function sectorContainsSector( m, p ) {
  17944. return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0;
  17945. }
  17946. // interlink polygon nodes in z-order
  17947. function indexCurve( start, minX, minY, invSize ) {
  17948. let p = start;
  17949. do {
  17950. if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
  17951. p.prevZ = p.prev;
  17952. p.nextZ = p.next;
  17953. p = p.next;
  17954. } while ( p !== start );
  17955. p.prevZ.nextZ = null;
  17956. p.prevZ = null;
  17957. sortLinked( p );
  17958. }
  17959. // Simon Tatham's linked list merge sort algorithm
  17960. // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
  17961. function sortLinked( list ) {
  17962. let i, p, q, e, tail, numMerges, pSize, qSize,
  17963. inSize = 1;
  17964. do {
  17965. p = list;
  17966. list = null;
  17967. tail = null;
  17968. numMerges = 0;
  17969. while ( p ) {
  17970. numMerges ++;
  17971. q = p;
  17972. pSize = 0;
  17973. for ( i = 0; i < inSize; i ++ ) {
  17974. pSize ++;
  17975. q = q.nextZ;
  17976. if ( ! q ) break;
  17977. }
  17978. qSize = inSize;
  17979. while ( pSize > 0 || ( qSize > 0 && q ) ) {
  17980. if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
  17981. e = p;
  17982. p = p.nextZ;
  17983. pSize --;
  17984. } else {
  17985. e = q;
  17986. q = q.nextZ;
  17987. qSize --;
  17988. }
  17989. if ( tail ) tail.nextZ = e;
  17990. else list = e;
  17991. e.prevZ = tail;
  17992. tail = e;
  17993. }
  17994. p = q;
  17995. }
  17996. tail.nextZ = null;
  17997. inSize *= 2;
  17998. } while ( numMerges > 1 );
  17999. return list;
  18000. }
  18001. // z-order of a point given coords and inverse of the longer side of data bbox
  18002. function zOrder( x, y, minX, minY, invSize ) {
  18003. // coords are transformed into non-negative 15-bit integer range
  18004. x = 32767 * ( x - minX ) * invSize;
  18005. y = 32767 * ( y - minY ) * invSize;
  18006. x = ( x | ( x << 8 ) ) & 0x00FF00FF;
  18007. x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
  18008. x = ( x | ( x << 2 ) ) & 0x33333333;
  18009. x = ( x | ( x << 1 ) ) & 0x55555555;
  18010. y = ( y | ( y << 8 ) ) & 0x00FF00FF;
  18011. y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
  18012. y = ( y | ( y << 2 ) ) & 0x33333333;
  18013. y = ( y | ( y << 1 ) ) & 0x55555555;
  18014. return x | ( y << 1 );
  18015. }
  18016. // find the leftmost node of a polygon ring
  18017. function getLeftmost( start ) {
  18018. let p = start,
  18019. leftmost = start;
  18020. do {
  18021. if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
  18022. p = p.next;
  18023. } while ( p !== start );
  18024. return leftmost;
  18025. }
  18026. // check if a point lies within a convex triangle
  18027. function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
  18028. return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
  18029. ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
  18030. ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
  18031. }
  18032. // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
  18033. function isValidDiagonal( a, b ) {
  18034. return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges
  18035. ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible
  18036. ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors
  18037. equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case
  18038. }
  18039. // signed area of a triangle
  18040. function area( p, q, r ) {
  18041. return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
  18042. }
  18043. // check if two points are equal
  18044. function equals( p1, p2 ) {
  18045. return p1.x === p2.x && p1.y === p2.y;
  18046. }
  18047. // check if two segments intersect
  18048. function intersects( p1, q1, p2, q2 ) {
  18049. const o1 = sign( area( p1, q1, p2 ) );
  18050. const o2 = sign( area( p1, q1, q2 ) );
  18051. const o3 = sign( area( p2, q2, p1 ) );
  18052. const o4 = sign( area( p2, q2, q1 ) );
  18053. if ( o1 !== o2 && o3 !== o4 ) return true; // general case
  18054. if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
  18055. if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
  18056. if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
  18057. if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
  18058. return false;
  18059. }
  18060. // for collinear points p, q, r, check if point q lies on segment pr
  18061. function onSegment( p, q, r ) {
  18062. 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 );
  18063. }
  18064. function sign( num ) {
  18065. return num > 0 ? 1 : num < 0 ? - 1 : 0;
  18066. }
  18067. // check if a polygon diagonal intersects any polygon segments
  18068. function intersectsPolygon( a, b ) {
  18069. let p = a;
  18070. do {
  18071. if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
  18072. intersects( p, p.next, a, b ) ) return true;
  18073. p = p.next;
  18074. } while ( p !== a );
  18075. return false;
  18076. }
  18077. // check if a polygon diagonal is locally inside the polygon
  18078. function locallyInside( a, b ) {
  18079. return area( a.prev, a, a.next ) < 0 ?
  18080. area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
  18081. area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
  18082. }
  18083. // check if the middle point of a polygon diagonal is inside the polygon
  18084. function middleInside( a, b ) {
  18085. let p = a,
  18086. inside = false;
  18087. const px = ( a.x + b.x ) / 2,
  18088. py = ( a.y + b.y ) / 2;
  18089. do {
  18090. if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
  18091. ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
  18092. inside = ! inside;
  18093. p = p.next;
  18094. } while ( p !== a );
  18095. return inside;
  18096. }
  18097. // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
  18098. // if one belongs to the outer ring and another to a hole, it merges it into a single ring
  18099. function splitPolygon( a, b ) {
  18100. const a2 = new Node( a.i, a.x, a.y ),
  18101. b2 = new Node( b.i, b.x, b.y ),
  18102. an = a.next,
  18103. bp = b.prev;
  18104. a.next = b;
  18105. b.prev = a;
  18106. a2.next = an;
  18107. an.prev = a2;
  18108. b2.next = a2;
  18109. a2.prev = b2;
  18110. bp.next = b2;
  18111. b2.prev = bp;
  18112. return b2;
  18113. }
  18114. // create a node and optionally link it with previous one (in a circular doubly linked list)
  18115. function insertNode( i, x, y, last ) {
  18116. const p = new Node( i, x, y );
  18117. if ( ! last ) {
  18118. p.prev = p;
  18119. p.next = p;
  18120. } else {
  18121. p.next = last.next;
  18122. p.prev = last;
  18123. last.next.prev = p;
  18124. last.next = p;
  18125. }
  18126. return p;
  18127. }
  18128. function removeNode( p ) {
  18129. p.next.prev = p.prev;
  18130. p.prev.next = p.next;
  18131. if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
  18132. if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
  18133. }
  18134. function Node( i, x, y ) {
  18135. // vertex index in coordinates array
  18136. this.i = i;
  18137. // vertex coordinates
  18138. this.x = x;
  18139. this.y = y;
  18140. // previous and next vertex nodes in a polygon ring
  18141. this.prev = null;
  18142. this.next = null;
  18143. // z-order curve value
  18144. this.z = null;
  18145. // previous and next nodes in z-order
  18146. this.prevZ = null;
  18147. this.nextZ = null;
  18148. // indicates whether this is a steiner point
  18149. this.steiner = false;
  18150. }
  18151. function signedArea( data, start, end, dim ) {
  18152. let sum = 0;
  18153. for ( let i = start, j = end - dim; i < end; i += dim ) {
  18154. sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
  18155. j = i;
  18156. }
  18157. return sum;
  18158. }
  18159. const ShapeUtils = {
  18160. // calculate area of the contour polygon
  18161. area: function ( contour ) {
  18162. const n = contour.length;
  18163. let a = 0.0;
  18164. for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
  18165. a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
  18166. }
  18167. return a * 0.5;
  18168. },
  18169. isClockWise: function ( pts ) {
  18170. return ShapeUtils.area( pts ) < 0;
  18171. },
  18172. triangulateShape: function ( contour, holes ) {
  18173. const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
  18174. const holeIndices = []; // array of hole indices
  18175. const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
  18176. removeDupEndPts( contour );
  18177. addContour( vertices, contour );
  18178. //
  18179. let holeIndex = contour.length;
  18180. holes.forEach( removeDupEndPts );
  18181. for ( let i = 0; i < holes.length; i ++ ) {
  18182. holeIndices.push( holeIndex );
  18183. holeIndex += holes[ i ].length;
  18184. addContour( vertices, holes[ i ] );
  18185. }
  18186. //
  18187. const triangles = Earcut.triangulate( vertices, holeIndices );
  18188. //
  18189. for ( let i = 0; i < triangles.length; i += 3 ) {
  18190. faces.push( triangles.slice( i, i + 3 ) );
  18191. }
  18192. return faces;
  18193. }
  18194. };
  18195. function removeDupEndPts( points ) {
  18196. const l = points.length;
  18197. if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
  18198. points.pop();
  18199. }
  18200. }
  18201. function addContour( vertices, contour ) {
  18202. for ( let i = 0; i < contour.length; i ++ ) {
  18203. vertices.push( contour[ i ].x );
  18204. vertices.push( contour[ i ].y );
  18205. }
  18206. }
  18207. /**
  18208. * Creates extruded geometry from a path shape.
  18209. *
  18210. * parameters = {
  18211. *
  18212. * curveSegments: <int>, // number of points on the curves
  18213. * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
  18214. * depth: <float>, // Depth to extrude the shape
  18215. *
  18216. * bevelEnabled: <bool>, // turn on bevel
  18217. * bevelThickness: <float>, // how deep into the original shape bevel goes
  18218. * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
  18219. * bevelOffset: <float>, // how far from shape outline does bevel start
  18220. * bevelSegments: <int>, // number of bevel layers
  18221. *
  18222. * extrudePath: <THREE.Curve> // curve to extrude shape along
  18223. *
  18224. * UVGenerator: <Object> // object that provides UV generator functions
  18225. *
  18226. * }
  18227. */
  18228. class ExtrudeBufferGeometry extends BufferGeometry {
  18229. constructor( shapes, options ) {
  18230. super();
  18231. this.type = 'ExtrudeBufferGeometry';
  18232. this.parameters = {
  18233. shapes: shapes,
  18234. options: options
  18235. };
  18236. shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
  18237. const scope = this;
  18238. const verticesArray = [];
  18239. const uvArray = [];
  18240. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  18241. const shape = shapes[ i ];
  18242. addShape( shape );
  18243. }
  18244. // build geometry
  18245. this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
  18246. this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
  18247. this.computeVertexNormals();
  18248. // functions
  18249. function addShape( shape ) {
  18250. const placeholder = [];
  18251. // options
  18252. const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
  18253. const steps = options.steps !== undefined ? options.steps : 1;
  18254. let depth = options.depth !== undefined ? options.depth : 100;
  18255. let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
  18256. let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
  18257. let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
  18258. let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
  18259. let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
  18260. const extrudePath = options.extrudePath;
  18261. const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
  18262. // deprecated options
  18263. if ( options.amount !== undefined ) {
  18264. console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
  18265. depth = options.amount;
  18266. }
  18267. //
  18268. let extrudePts, extrudeByPath = false;
  18269. let splineTube, binormal, normal, position2;
  18270. if ( extrudePath ) {
  18271. extrudePts = extrudePath.getSpacedPoints( steps );
  18272. extrudeByPath = true;
  18273. bevelEnabled = false; // bevels not supported for path extrusion
  18274. // SETUP TNB variables
  18275. // TODO1 - have a .isClosed in spline?
  18276. splineTube = extrudePath.computeFrenetFrames( steps, false );
  18277. // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
  18278. binormal = new Vector3();
  18279. normal = new Vector3();
  18280. position2 = new Vector3();
  18281. }
  18282. // Safeguards if bevels are not enabled
  18283. if ( ! bevelEnabled ) {
  18284. bevelSegments = 0;
  18285. bevelThickness = 0;
  18286. bevelSize = 0;
  18287. bevelOffset = 0;
  18288. }
  18289. // Variables initialization
  18290. const shapePoints = shape.extractPoints( curveSegments );
  18291. let vertices = shapePoints.shape;
  18292. const holes = shapePoints.holes;
  18293. const reverse = ! ShapeUtils.isClockWise( vertices );
  18294. if ( reverse ) {
  18295. vertices = vertices.reverse();
  18296. // Maybe we should also check if holes are in the opposite direction, just to be safe ...
  18297. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  18298. const ahole = holes[ h ];
  18299. if ( ShapeUtils.isClockWise( ahole ) ) {
  18300. holes[ h ] = ahole.reverse();
  18301. }
  18302. }
  18303. }
  18304. const faces = ShapeUtils.triangulateShape( vertices, holes );
  18305. /* Vertices */
  18306. const contour = vertices; // vertices has all points but contour has only points of circumference
  18307. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  18308. const ahole = holes[ h ];
  18309. vertices = vertices.concat( ahole );
  18310. }
  18311. function scalePt2( pt, vec, size ) {
  18312. if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
  18313. return vec.clone().multiplyScalar( size ).add( pt );
  18314. }
  18315. const vlen = vertices.length, flen = faces.length;
  18316. // Find directions for point movement
  18317. function getBevelVec( inPt, inPrev, inNext ) {
  18318. // computes for inPt the corresponding point inPt' on a new contour
  18319. // shifted by 1 unit (length of normalized vector) to the left
  18320. // if we walk along contour clockwise, this new contour is outside the old one
  18321. //
  18322. // inPt' is the intersection of the two lines parallel to the two
  18323. // adjacent edges of inPt at a distance of 1 unit on the left side.
  18324. let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
  18325. // good reading for geometry algorithms (here: line-line intersection)
  18326. // http://geomalgorithms.com/a05-_intersect-1.html
  18327. const v_prev_x = inPt.x - inPrev.x,
  18328. v_prev_y = inPt.y - inPrev.y;
  18329. const v_next_x = inNext.x - inPt.x,
  18330. v_next_y = inNext.y - inPt.y;
  18331. const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
  18332. // check for collinear edges
  18333. const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
  18334. if ( Math.abs( collinear0 ) > Number.EPSILON ) {
  18335. // not collinear
  18336. // length of vectors for normalizing
  18337. const v_prev_len = Math.sqrt( v_prev_lensq );
  18338. const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
  18339. // shift adjacent points by unit vectors to the left
  18340. const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
  18341. const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
  18342. const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
  18343. const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
  18344. // scaling factor for v_prev to intersection point
  18345. const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
  18346. ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
  18347. ( v_prev_x * v_next_y - v_prev_y * v_next_x );
  18348. // vector from inPt to intersection point
  18349. v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
  18350. v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
  18351. // Don't normalize!, otherwise sharp corners become ugly
  18352. // but prevent crazy spikes
  18353. const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
  18354. if ( v_trans_lensq <= 2 ) {
  18355. return new Vector2( v_trans_x, v_trans_y );
  18356. } else {
  18357. shrink_by = Math.sqrt( v_trans_lensq / 2 );
  18358. }
  18359. } else {
  18360. // handle special case of collinear edges
  18361. let direction_eq = false; // assumes: opposite
  18362. if ( v_prev_x > Number.EPSILON ) {
  18363. if ( v_next_x > Number.EPSILON ) {
  18364. direction_eq = true;
  18365. }
  18366. } else {
  18367. if ( v_prev_x < - Number.EPSILON ) {
  18368. if ( v_next_x < - Number.EPSILON ) {
  18369. direction_eq = true;
  18370. }
  18371. } else {
  18372. if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
  18373. direction_eq = true;
  18374. }
  18375. }
  18376. }
  18377. if ( direction_eq ) {
  18378. // console.log("Warning: lines are a straight sequence");
  18379. v_trans_x = - v_prev_y;
  18380. v_trans_y = v_prev_x;
  18381. shrink_by = Math.sqrt( v_prev_lensq );
  18382. } else {
  18383. // console.log("Warning: lines are a straight spike");
  18384. v_trans_x = v_prev_x;
  18385. v_trans_y = v_prev_y;
  18386. shrink_by = Math.sqrt( v_prev_lensq / 2 );
  18387. }
  18388. }
  18389. return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
  18390. }
  18391. const contourMovements = [];
  18392. for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
  18393. if ( j === il ) j = 0;
  18394. if ( k === il ) k = 0;
  18395. // (j)---(i)---(k)
  18396. // console.log('i,j,k', i, j , k)
  18397. contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
  18398. }
  18399. const holesMovements = [];
  18400. let oneHoleMovements, verticesMovements = contourMovements.concat();
  18401. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  18402. const ahole = holes[ h ];
  18403. oneHoleMovements = [];
  18404. for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
  18405. if ( j === il ) j = 0;
  18406. if ( k === il ) k = 0;
  18407. // (j)---(i)---(k)
  18408. oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
  18409. }
  18410. holesMovements.push( oneHoleMovements );
  18411. verticesMovements = verticesMovements.concat( oneHoleMovements );
  18412. }
  18413. // Loop bevelSegments, 1 for the front, 1 for the back
  18414. for ( let b = 0; b < bevelSegments; b ++ ) {
  18415. //for ( b = bevelSegments; b > 0; b -- ) {
  18416. const t = b / bevelSegments;
  18417. const z = bevelThickness * Math.cos( t * Math.PI / 2 );
  18418. const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
  18419. // contract shape
  18420. for ( let i = 0, il = contour.length; i < il; i ++ ) {
  18421. const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
  18422. v( vert.x, vert.y, - z );
  18423. }
  18424. // expand holes
  18425. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  18426. const ahole = holes[ h ];
  18427. oneHoleMovements = holesMovements[ h ];
  18428. for ( let i = 0, il = ahole.length; i < il; i ++ ) {
  18429. const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
  18430. v( vert.x, vert.y, - z );
  18431. }
  18432. }
  18433. }
  18434. const bs = bevelSize + bevelOffset;
  18435. // Back facing vertices
  18436. for ( let i = 0; i < vlen; i ++ ) {
  18437. const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
  18438. if ( ! extrudeByPath ) {
  18439. v( vert.x, vert.y, 0 );
  18440. } else {
  18441. // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
  18442. normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
  18443. binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
  18444. position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
  18445. v( position2.x, position2.y, position2.z );
  18446. }
  18447. }
  18448. // Add stepped vertices...
  18449. // Including front facing vertices
  18450. for ( let s = 1; s <= steps; s ++ ) {
  18451. for ( let i = 0; i < vlen; i ++ ) {
  18452. const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
  18453. if ( ! extrudeByPath ) {
  18454. v( vert.x, vert.y, depth / steps * s );
  18455. } else {
  18456. // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
  18457. normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
  18458. binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
  18459. position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
  18460. v( position2.x, position2.y, position2.z );
  18461. }
  18462. }
  18463. }
  18464. // Add bevel segments planes
  18465. //for ( b = 1; b <= bevelSegments; b ++ ) {
  18466. for ( let b = bevelSegments - 1; b >= 0; b -- ) {
  18467. const t = b / bevelSegments;
  18468. const z = bevelThickness * Math.cos( t * Math.PI / 2 );
  18469. const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
  18470. // contract shape
  18471. for ( let i = 0, il = contour.length; i < il; i ++ ) {
  18472. const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
  18473. v( vert.x, vert.y, depth + z );
  18474. }
  18475. // expand holes
  18476. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  18477. const ahole = holes[ h ];
  18478. oneHoleMovements = holesMovements[ h ];
  18479. for ( let i = 0, il = ahole.length; i < il; i ++ ) {
  18480. const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
  18481. if ( ! extrudeByPath ) {
  18482. v( vert.x, vert.y, depth + z );
  18483. } else {
  18484. v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
  18485. }
  18486. }
  18487. }
  18488. }
  18489. /* Faces */
  18490. // Top and bottom faces
  18491. buildLidFaces();
  18492. // Sides faces
  18493. buildSideFaces();
  18494. ///// Internal functions
  18495. function buildLidFaces() {
  18496. const start = verticesArray.length / 3;
  18497. if ( bevelEnabled ) {
  18498. let layer = 0; // steps + 1
  18499. let offset = vlen * layer;
  18500. // Bottom faces
  18501. for ( let i = 0; i < flen; i ++ ) {
  18502. const face = faces[ i ];
  18503. f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
  18504. }
  18505. layer = steps + bevelSegments * 2;
  18506. offset = vlen * layer;
  18507. // Top faces
  18508. for ( let i = 0; i < flen; i ++ ) {
  18509. const face = faces[ i ];
  18510. f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
  18511. }
  18512. } else {
  18513. // Bottom faces
  18514. for ( let i = 0; i < flen; i ++ ) {
  18515. const face = faces[ i ];
  18516. f3( face[ 2 ], face[ 1 ], face[ 0 ] );
  18517. }
  18518. // Top faces
  18519. for ( let i = 0; i < flen; i ++ ) {
  18520. const face = faces[ i ];
  18521. f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
  18522. }
  18523. }
  18524. scope.addGroup( start, verticesArray.length / 3 - start, 0 );
  18525. }
  18526. // Create faces for the z-sides of the shape
  18527. function buildSideFaces() {
  18528. const start = verticesArray.length / 3;
  18529. let layeroffset = 0;
  18530. sidewalls( contour, layeroffset );
  18531. layeroffset += contour.length;
  18532. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  18533. const ahole = holes[ h ];
  18534. sidewalls( ahole, layeroffset );
  18535. //, true
  18536. layeroffset += ahole.length;
  18537. }
  18538. scope.addGroup( start, verticesArray.length / 3 - start, 1 );
  18539. }
  18540. function sidewalls( contour, layeroffset ) {
  18541. let i = contour.length;
  18542. while ( -- i >= 0 ) {
  18543. const j = i;
  18544. let k = i - 1;
  18545. if ( k < 0 ) k = contour.length - 1;
  18546. //console.log('b', i,j, i-1, k,vertices.length);
  18547. for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
  18548. const slen1 = vlen * s;
  18549. const slen2 = vlen * ( s + 1 );
  18550. const a = layeroffset + j + slen1,
  18551. b = layeroffset + k + slen1,
  18552. c = layeroffset + k + slen2,
  18553. d = layeroffset + j + slen2;
  18554. f4( a, b, c, d );
  18555. }
  18556. }
  18557. }
  18558. function v( x, y, z ) {
  18559. placeholder.push( x );
  18560. placeholder.push( y );
  18561. placeholder.push( z );
  18562. }
  18563. function f3( a, b, c ) {
  18564. addVertex( a );
  18565. addVertex( b );
  18566. addVertex( c );
  18567. const nextIndex = verticesArray.length / 3;
  18568. const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
  18569. addUV( uvs[ 0 ] );
  18570. addUV( uvs[ 1 ] );
  18571. addUV( uvs[ 2 ] );
  18572. }
  18573. function f4( a, b, c, d ) {
  18574. addVertex( a );
  18575. addVertex( b );
  18576. addVertex( d );
  18577. addVertex( b );
  18578. addVertex( c );
  18579. addVertex( d );
  18580. const nextIndex = verticesArray.length / 3;
  18581. const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
  18582. addUV( uvs[ 0 ] );
  18583. addUV( uvs[ 1 ] );
  18584. addUV( uvs[ 3 ] );
  18585. addUV( uvs[ 1 ] );
  18586. addUV( uvs[ 2 ] );
  18587. addUV( uvs[ 3 ] );
  18588. }
  18589. function addVertex( index ) {
  18590. verticesArray.push( placeholder[ index * 3 + 0 ] );
  18591. verticesArray.push( placeholder[ index * 3 + 1 ] );
  18592. verticesArray.push( placeholder[ index * 3 + 2 ] );
  18593. }
  18594. function addUV( vector2 ) {
  18595. uvArray.push( vector2.x );
  18596. uvArray.push( vector2.y );
  18597. }
  18598. }
  18599. }
  18600. toJSON() {
  18601. const data = BufferGeometry.prototype.toJSON.call( this );
  18602. const shapes = this.parameters.shapes;
  18603. const options = this.parameters.options;
  18604. return toJSON( shapes, options, data );
  18605. }
  18606. }
  18607. const WorldUVGenerator = {
  18608. generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
  18609. const a_x = vertices[ indexA * 3 ];
  18610. const a_y = vertices[ indexA * 3 + 1 ];
  18611. const b_x = vertices[ indexB * 3 ];
  18612. const b_y = vertices[ indexB * 3 + 1 ];
  18613. const c_x = vertices[ indexC * 3 ];
  18614. const c_y = vertices[ indexC * 3 + 1 ];
  18615. return [
  18616. new Vector2( a_x, a_y ),
  18617. new Vector2( b_x, b_y ),
  18618. new Vector2( c_x, c_y )
  18619. ];
  18620. },
  18621. generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
  18622. const a_x = vertices[ indexA * 3 ];
  18623. const a_y = vertices[ indexA * 3 + 1 ];
  18624. const a_z = vertices[ indexA * 3 + 2 ];
  18625. const b_x = vertices[ indexB * 3 ];
  18626. const b_y = vertices[ indexB * 3 + 1 ];
  18627. const b_z = vertices[ indexB * 3 + 2 ];
  18628. const c_x = vertices[ indexC * 3 ];
  18629. const c_y = vertices[ indexC * 3 + 1 ];
  18630. const c_z = vertices[ indexC * 3 + 2 ];
  18631. const d_x = vertices[ indexD * 3 ];
  18632. const d_y = vertices[ indexD * 3 + 1 ];
  18633. const d_z = vertices[ indexD * 3 + 2 ];
  18634. if ( Math.abs( a_y - b_y ) < 0.01 ) {
  18635. return [
  18636. new Vector2( a_x, 1 - a_z ),
  18637. new Vector2( b_x, 1 - b_z ),
  18638. new Vector2( c_x, 1 - c_z ),
  18639. new Vector2( d_x, 1 - d_z )
  18640. ];
  18641. } else {
  18642. return [
  18643. new Vector2( a_y, 1 - a_z ),
  18644. new Vector2( b_y, 1 - b_z ),
  18645. new Vector2( c_y, 1 - c_z ),
  18646. new Vector2( d_y, 1 - d_z )
  18647. ];
  18648. }
  18649. }
  18650. };
  18651. function toJSON( shapes, options, data ) {
  18652. data.shapes = [];
  18653. if ( Array.isArray( shapes ) ) {
  18654. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  18655. const shape = shapes[ i ];
  18656. data.shapes.push( shape.uuid );
  18657. }
  18658. } else {
  18659. data.shapes.push( shapes.uuid );
  18660. }
  18661. if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
  18662. return data;
  18663. }
  18664. /**
  18665. * Creates extruded geometry from a path shape.
  18666. *
  18667. * parameters = {
  18668. *
  18669. * curveSegments: <int>, // number of points on the curves
  18670. * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
  18671. * depth: <float>, // Depth to extrude the shape
  18672. *
  18673. * bevelEnabled: <bool>, // turn on bevel
  18674. * bevelThickness: <float>, // how deep into the original shape bevel goes
  18675. * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
  18676. * bevelOffset: <float>, // how far from shape outline does bevel start
  18677. * bevelSegments: <int>, // number of bevel layers
  18678. *
  18679. * extrudePath: <THREE.Curve> // curve to extrude shape along
  18680. *
  18681. * UVGenerator: <Object> // object that provides UV generator functions
  18682. *
  18683. * }
  18684. */
  18685. class ExtrudeGeometry extends Geometry {
  18686. constructor( shapes, options ) {
  18687. super();
  18688. this.type = 'ExtrudeGeometry';
  18689. this.parameters = {
  18690. shapes: shapes,
  18691. options: options
  18692. };
  18693. this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
  18694. this.mergeVertices();
  18695. }
  18696. toJSON() {
  18697. const data = super.toJSON();
  18698. const shapes = this.parameters.shapes;
  18699. const options = this.parameters.options;
  18700. return toJSON$1( shapes, options, data );
  18701. }
  18702. }
  18703. function toJSON$1( shapes, options, data ) {
  18704. data.shapes = [];
  18705. if ( Array.isArray( shapes ) ) {
  18706. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  18707. const shape = shapes[ i ];
  18708. data.shapes.push( shape.uuid );
  18709. }
  18710. } else {
  18711. data.shapes.push( shapes.uuid );
  18712. }
  18713. if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
  18714. return data;
  18715. }
  18716. class IcosahedronBufferGeometry extends PolyhedronBufferGeometry {
  18717. constructor( radius = 1, detail = 0 ) {
  18718. const t = ( 1 + Math.sqrt( 5 ) ) / 2;
  18719. const vertices = [
  18720. - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
  18721. 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
  18722. t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
  18723. ];
  18724. const indices = [
  18725. 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
  18726. 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
  18727. 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
  18728. 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
  18729. ];
  18730. super( vertices, indices, radius, detail );
  18731. this.type = 'IcosahedronBufferGeometry';
  18732. this.parameters = {
  18733. radius: radius,
  18734. detail: detail
  18735. };
  18736. }
  18737. }
  18738. class IcosahedronGeometry extends Geometry {
  18739. constructor( radius, detail ) {
  18740. super();
  18741. this.type = 'IcosahedronGeometry';
  18742. this.parameters = {
  18743. radius: radius,
  18744. detail: detail
  18745. };
  18746. this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
  18747. this.mergeVertices();
  18748. }
  18749. }
  18750. class LatheBufferGeometry extends BufferGeometry {
  18751. constructor( points, segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) {
  18752. super();
  18753. this.type = 'LatheBufferGeometry';
  18754. this.parameters = {
  18755. points: points,
  18756. segments: segments,
  18757. phiStart: phiStart,
  18758. phiLength: phiLength
  18759. };
  18760. segments = Math.floor( segments );
  18761. // clamp phiLength so it's in range of [ 0, 2PI ]
  18762. phiLength = MathUtils$1.clamp( phiLength, 0, Math.PI * 2 );
  18763. // buffers
  18764. const indices = [];
  18765. const vertices = [];
  18766. const uvs = [];
  18767. // helper variables
  18768. const inverseSegments = 1.0 / segments;
  18769. const vertex = new Vector3();
  18770. const uv = new Vector2();
  18771. // generate vertices and uvs
  18772. for ( let i = 0; i <= segments; i ++ ) {
  18773. const phi = phiStart + i * inverseSegments * phiLength;
  18774. const sin = Math.sin( phi );
  18775. const cos = Math.cos( phi );
  18776. for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
  18777. // vertex
  18778. vertex.x = points[ j ].x * sin;
  18779. vertex.y = points[ j ].y;
  18780. vertex.z = points[ j ].x * cos;
  18781. vertices.push( vertex.x, vertex.y, vertex.z );
  18782. // uv
  18783. uv.x = i / segments;
  18784. uv.y = j / ( points.length - 1 );
  18785. uvs.push( uv.x, uv.y );
  18786. }
  18787. }
  18788. // indices
  18789. for ( let i = 0; i < segments; i ++ ) {
  18790. for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
  18791. const base = j + i * points.length;
  18792. const a = base;
  18793. const b = base + points.length;
  18794. const c = base + points.length + 1;
  18795. const d = base + 1;
  18796. // faces
  18797. indices.push( a, b, d );
  18798. indices.push( b, c, d );
  18799. }
  18800. }
  18801. // build geometry
  18802. this.setIndex( indices );
  18803. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  18804. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  18805. // generate normals
  18806. this.computeVertexNormals();
  18807. // if the geometry is closed, we need to average the normals along the seam.
  18808. // because the corresponding vertices are identical (but still have different UVs).
  18809. if ( phiLength === Math.PI * 2 ) {
  18810. const normals = this.attributes.normal.array;
  18811. const n1 = new Vector3();
  18812. const n2 = new Vector3();
  18813. const n = new Vector3();
  18814. // this is the buffer offset for the last line of vertices
  18815. const base = segments * points.length * 3;
  18816. for ( let i = 0, j = 0; i < points.length; i ++, j += 3 ) {
  18817. // select the normal of the vertex in the first line
  18818. n1.x = normals[ j + 0 ];
  18819. n1.y = normals[ j + 1 ];
  18820. n1.z = normals[ j + 2 ];
  18821. // select the normal of the vertex in the last line
  18822. n2.x = normals[ base + j + 0 ];
  18823. n2.y = normals[ base + j + 1 ];
  18824. n2.z = normals[ base + j + 2 ];
  18825. // average normals
  18826. n.addVectors( n1, n2 ).normalize();
  18827. // assign the new values to both normals
  18828. normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
  18829. normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
  18830. normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
  18831. }
  18832. }
  18833. }
  18834. }
  18835. class LatheGeometry extends Geometry {
  18836. constructor( points, segments, phiStart, phiLength ) {
  18837. super();
  18838. this.type = 'LatheGeometry';
  18839. this.parameters = {
  18840. points: points,
  18841. segments: segments,
  18842. phiStart: phiStart,
  18843. phiLength: phiLength
  18844. };
  18845. this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
  18846. this.mergeVertices();
  18847. }
  18848. }
  18849. class OctahedronBufferGeometry extends PolyhedronBufferGeometry {
  18850. constructor( radius = 1, detail = 0 ) {
  18851. const vertices = [
  18852. 1, 0, 0, - 1, 0, 0, 0, 1, 0,
  18853. 0, - 1, 0, 0, 0, 1, 0, 0, - 1
  18854. ];
  18855. const indices = [
  18856. 0, 2, 4, 0, 4, 3, 0, 3, 5,
  18857. 0, 5, 2, 1, 2, 5, 1, 5, 3,
  18858. 1, 3, 4, 1, 4, 2
  18859. ];
  18860. super( vertices, indices, radius, detail );
  18861. this.type = 'OctahedronBufferGeometry';
  18862. this.parameters = {
  18863. radius: radius,
  18864. detail: detail
  18865. };
  18866. }
  18867. }
  18868. class OctahedronGeometry extends Geometry {
  18869. constructor( radius, detail ) {
  18870. super();
  18871. this.type = 'OctahedronGeometry';
  18872. this.parameters = {
  18873. radius: radius,
  18874. detail: detail
  18875. };
  18876. this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
  18877. this.mergeVertices();
  18878. }
  18879. }
  18880. /**
  18881. * Parametric Surfaces Geometry
  18882. * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
  18883. */
  18884. function ParametricBufferGeometry( func, slices, stacks ) {
  18885. BufferGeometry.call( this );
  18886. this.type = 'ParametricBufferGeometry';
  18887. this.parameters = {
  18888. func: func,
  18889. slices: slices,
  18890. stacks: stacks
  18891. };
  18892. // buffers
  18893. const indices = [];
  18894. const vertices = [];
  18895. const normals = [];
  18896. const uvs = [];
  18897. const EPS = 0.00001;
  18898. const normal = new Vector3();
  18899. const p0 = new Vector3(), p1 = new Vector3();
  18900. const pu = new Vector3(), pv = new Vector3();
  18901. if ( func.length < 3 ) {
  18902. console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
  18903. }
  18904. // generate vertices, normals and uvs
  18905. const sliceCount = slices + 1;
  18906. for ( let i = 0; i <= stacks; i ++ ) {
  18907. const v = i / stacks;
  18908. for ( let j = 0; j <= slices; j ++ ) {
  18909. const u = j / slices;
  18910. // vertex
  18911. func( u, v, p0 );
  18912. vertices.push( p0.x, p0.y, p0.z );
  18913. // normal
  18914. // approximate tangent vectors via finite differences
  18915. if ( u - EPS >= 0 ) {
  18916. func( u - EPS, v, p1 );
  18917. pu.subVectors( p0, p1 );
  18918. } else {
  18919. func( u + EPS, v, p1 );
  18920. pu.subVectors( p1, p0 );
  18921. }
  18922. if ( v - EPS >= 0 ) {
  18923. func( u, v - EPS, p1 );
  18924. pv.subVectors( p0, p1 );
  18925. } else {
  18926. func( u, v + EPS, p1 );
  18927. pv.subVectors( p1, p0 );
  18928. }
  18929. // cross product of tangent vectors returns surface normal
  18930. normal.crossVectors( pu, pv ).normalize();
  18931. normals.push( normal.x, normal.y, normal.z );
  18932. // uv
  18933. uvs.push( u, v );
  18934. }
  18935. }
  18936. // generate indices
  18937. for ( let i = 0; i < stacks; i ++ ) {
  18938. for ( let j = 0; j < slices; j ++ ) {
  18939. const a = i * sliceCount + j;
  18940. const b = i * sliceCount + j + 1;
  18941. const c = ( i + 1 ) * sliceCount + j + 1;
  18942. const d = ( i + 1 ) * sliceCount + j;
  18943. // faces one and two
  18944. indices.push( a, b, d );
  18945. indices.push( b, c, d );
  18946. }
  18947. }
  18948. // build geometry
  18949. this.setIndex( indices );
  18950. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  18951. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  18952. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  18953. }
  18954. ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
  18955. ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
  18956. /**
  18957. * Parametric Surfaces Geometry
  18958. * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
  18959. */
  18960. function ParametricGeometry( func, slices, stacks ) {
  18961. Geometry.call( this );
  18962. this.type = 'ParametricGeometry';
  18963. this.parameters = {
  18964. func: func,
  18965. slices: slices,
  18966. stacks: stacks
  18967. };
  18968. this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
  18969. this.mergeVertices();
  18970. }
  18971. ParametricGeometry.prototype = Object.create( Geometry.prototype );
  18972. ParametricGeometry.prototype.constructor = ParametricGeometry;
  18973. class PlaneGeometry extends Geometry {
  18974. constructor( width, height, widthSegments, heightSegments ) {
  18975. super();
  18976. this.type = 'PlaneGeometry';
  18977. this.parameters = {
  18978. width: width,
  18979. height: height,
  18980. widthSegments: widthSegments,
  18981. heightSegments: heightSegments
  18982. };
  18983. this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
  18984. this.mergeVertices();
  18985. }
  18986. }
  18987. class PolyhedronGeometry extends Geometry {
  18988. constructor( vertices, indices, radius, detail ) {
  18989. super();
  18990. this.type = 'PolyhedronGeometry';
  18991. this.parameters = {
  18992. vertices: vertices,
  18993. indices: indices,
  18994. radius: radius,
  18995. detail: detail
  18996. };
  18997. this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
  18998. this.mergeVertices();
  18999. }
  19000. }
  19001. class RingBufferGeometry extends BufferGeometry {
  19002. constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 8, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
  19003. super();
  19004. this.type = 'RingBufferGeometry';
  19005. this.parameters = {
  19006. innerRadius: innerRadius,
  19007. outerRadius: outerRadius,
  19008. thetaSegments: thetaSegments,
  19009. phiSegments: phiSegments,
  19010. thetaStart: thetaStart,
  19011. thetaLength: thetaLength
  19012. };
  19013. thetaSegments = Math.max( 3, thetaSegments );
  19014. phiSegments = Math.max( 1, phiSegments );
  19015. // buffers
  19016. const indices = [];
  19017. const vertices = [];
  19018. const normals = [];
  19019. const uvs = [];
  19020. // some helper variables
  19021. let radius = innerRadius;
  19022. const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
  19023. const vertex = new Vector3();
  19024. const uv = new Vector2();
  19025. // generate vertices, normals and uvs
  19026. for ( let j = 0; j <= phiSegments; j ++ ) {
  19027. for ( let i = 0; i <= thetaSegments; i ++ ) {
  19028. // values are generate from the inside of the ring to the outside
  19029. const segment = thetaStart + i / thetaSegments * thetaLength;
  19030. // vertex
  19031. vertex.x = radius * Math.cos( segment );
  19032. vertex.y = radius * Math.sin( segment );
  19033. vertices.push( vertex.x, vertex.y, vertex.z );
  19034. // normal
  19035. normals.push( 0, 0, 1 );
  19036. // uv
  19037. uv.x = ( vertex.x / outerRadius + 1 ) / 2;
  19038. uv.y = ( vertex.y / outerRadius + 1 ) / 2;
  19039. uvs.push( uv.x, uv.y );
  19040. }
  19041. // increase the radius for next row of vertices
  19042. radius += radiusStep;
  19043. }
  19044. // indices
  19045. for ( let j = 0; j < phiSegments; j ++ ) {
  19046. const thetaSegmentLevel = j * ( thetaSegments + 1 );
  19047. for ( let i = 0; i < thetaSegments; i ++ ) {
  19048. const segment = i + thetaSegmentLevel;
  19049. const a = segment;
  19050. const b = segment + thetaSegments + 1;
  19051. const c = segment + thetaSegments + 2;
  19052. const d = segment + 1;
  19053. // faces
  19054. indices.push( a, b, d );
  19055. indices.push( b, c, d );
  19056. }
  19057. }
  19058. // build geometry
  19059. this.setIndex( indices );
  19060. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  19061. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  19062. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  19063. }
  19064. }
  19065. class RingGeometry extends Geometry {
  19066. constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
  19067. super();
  19068. this.type = 'RingGeometry';
  19069. this.parameters = {
  19070. innerRadius: innerRadius,
  19071. outerRadius: outerRadius,
  19072. thetaSegments: thetaSegments,
  19073. phiSegments: phiSegments,
  19074. thetaStart: thetaStart,
  19075. thetaLength: thetaLength
  19076. };
  19077. this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
  19078. this.mergeVertices();
  19079. }
  19080. }
  19081. class ShapeBufferGeometry extends BufferGeometry {
  19082. constructor( shapes, curveSegments = 12 ) {
  19083. super();
  19084. this.type = 'ShapeBufferGeometry';
  19085. this.parameters = {
  19086. shapes: shapes,
  19087. curveSegments: curveSegments
  19088. };
  19089. // buffers
  19090. const indices = [];
  19091. const vertices = [];
  19092. const normals = [];
  19093. const uvs = [];
  19094. // helper variables
  19095. let groupStart = 0;
  19096. let groupCount = 0;
  19097. // allow single and array values for "shapes" parameter
  19098. if ( Array.isArray( shapes ) === false ) {
  19099. addShape( shapes );
  19100. } else {
  19101. for ( let i = 0; i < shapes.length; i ++ ) {
  19102. addShape( shapes[ i ] );
  19103. this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
  19104. groupStart += groupCount;
  19105. groupCount = 0;
  19106. }
  19107. }
  19108. // build geometry
  19109. this.setIndex( indices );
  19110. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  19111. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  19112. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  19113. // helper functions
  19114. function addShape( shape ) {
  19115. const indexOffset = vertices.length / 3;
  19116. const points = shape.extractPoints( curveSegments );
  19117. let shapeVertices = points.shape;
  19118. const shapeHoles = points.holes;
  19119. // check direction of vertices
  19120. if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
  19121. shapeVertices = shapeVertices.reverse();
  19122. }
  19123. for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
  19124. const shapeHole = shapeHoles[ i ];
  19125. if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
  19126. shapeHoles[ i ] = shapeHole.reverse();
  19127. }
  19128. }
  19129. const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
  19130. // join vertices of inner and outer paths to a single array
  19131. for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
  19132. const shapeHole = shapeHoles[ i ];
  19133. shapeVertices = shapeVertices.concat( shapeHole );
  19134. }
  19135. // vertices, normals, uvs
  19136. for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
  19137. const vertex = shapeVertices[ i ];
  19138. vertices.push( vertex.x, vertex.y, 0 );
  19139. normals.push( 0, 0, 1 );
  19140. uvs.push( vertex.x, vertex.y ); // world uvs
  19141. }
  19142. // incides
  19143. for ( let i = 0, l = faces.length; i < l; i ++ ) {
  19144. const face = faces[ i ];
  19145. const a = face[ 0 ] + indexOffset;
  19146. const b = face[ 1 ] + indexOffset;
  19147. const c = face[ 2 ] + indexOffset;
  19148. indices.push( a, b, c );
  19149. groupCount += 3;
  19150. }
  19151. }
  19152. }
  19153. toJSON() {
  19154. const data = BufferGeometry.prototype.toJSON.call( this );
  19155. const shapes = this.parameters.shapes;
  19156. return toJSON$2( shapes, data );
  19157. }
  19158. }
  19159. function toJSON$2( shapes, data ) {
  19160. data.shapes = [];
  19161. if ( Array.isArray( shapes ) ) {
  19162. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  19163. const shape = shapes[ i ];
  19164. data.shapes.push( shape.uuid );
  19165. }
  19166. } else {
  19167. data.shapes.push( shapes.uuid );
  19168. }
  19169. return data;
  19170. }
  19171. class ShapeGeometry extends Geometry {
  19172. constructor( shapes, curveSegments ) {
  19173. super();
  19174. this.type = 'ShapeGeometry';
  19175. if ( typeof curveSegments === 'object' ) {
  19176. console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
  19177. curveSegments = curveSegments.curveSegments;
  19178. }
  19179. this.parameters = {
  19180. shapes: shapes,
  19181. curveSegments: curveSegments
  19182. };
  19183. this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
  19184. this.mergeVertices();
  19185. }
  19186. toJSON() {
  19187. const data = Geometry.prototype.toJSON.call( this );
  19188. const shapes = this.parameters.shapes;
  19189. return toJSON$3( shapes, data );
  19190. }
  19191. }
  19192. function toJSON$3( shapes, data ) {
  19193. data.shapes = [];
  19194. if ( Array.isArray( shapes ) ) {
  19195. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  19196. const shape = shapes[ i ];
  19197. data.shapes.push( shape.uuid );
  19198. }
  19199. } else {
  19200. data.shapes.push( shapes.uuid );
  19201. }
  19202. return data;
  19203. }
  19204. class SphereBufferGeometry extends BufferGeometry {
  19205. constructor( radius = 1, widthSegments = 8, heightSegments = 6, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
  19206. super();
  19207. this.type = 'SphereBufferGeometry';
  19208. this.parameters = {
  19209. radius: radius,
  19210. widthSegments: widthSegments,
  19211. heightSegments: heightSegments,
  19212. phiStart: phiStart,
  19213. phiLength: phiLength,
  19214. thetaStart: thetaStart,
  19215. thetaLength: thetaLength
  19216. };
  19217. widthSegments = Math.max( 3, Math.floor( widthSegments ) );
  19218. heightSegments = Math.max( 2, Math.floor( heightSegments ) );
  19219. const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
  19220. let index = 0;
  19221. const grid = [];
  19222. const vertex = new Vector3();
  19223. const normal = new Vector3();
  19224. // buffers
  19225. const indices = [];
  19226. const vertices = [];
  19227. const normals = [];
  19228. const uvs = [];
  19229. // generate vertices, normals and uvs
  19230. for ( let iy = 0; iy <= heightSegments; iy ++ ) {
  19231. const verticesRow = [];
  19232. const v = iy / heightSegments;
  19233. // special case for the poles
  19234. let uOffset = 0;
  19235. if ( iy == 0 && thetaStart == 0 ) {
  19236. uOffset = 0.5 / widthSegments;
  19237. } else if ( iy == heightSegments && thetaEnd == Math.PI ) {
  19238. uOffset = - 0.5 / widthSegments;
  19239. }
  19240. for ( let ix = 0; ix <= widthSegments; ix ++ ) {
  19241. const u = ix / widthSegments;
  19242. // vertex
  19243. vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
  19244. vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
  19245. vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
  19246. vertices.push( vertex.x, vertex.y, vertex.z );
  19247. // normal
  19248. normal.copy( vertex ).normalize();
  19249. normals.push( normal.x, normal.y, normal.z );
  19250. // uv
  19251. uvs.push( u + uOffset, 1 - v );
  19252. verticesRow.push( index ++ );
  19253. }
  19254. grid.push( verticesRow );
  19255. }
  19256. // indices
  19257. for ( let iy = 0; iy < heightSegments; iy ++ ) {
  19258. for ( let ix = 0; ix < widthSegments; ix ++ ) {
  19259. const a = grid[ iy ][ ix + 1 ];
  19260. const b = grid[ iy ][ ix ];
  19261. const c = grid[ iy + 1 ][ ix ];
  19262. const d = grid[ iy + 1 ][ ix + 1 ];
  19263. if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
  19264. if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
  19265. }
  19266. }
  19267. // build geometry
  19268. this.setIndex( indices );
  19269. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  19270. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  19271. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  19272. }
  19273. }
  19274. class SphereGeometry extends Geometry {
  19275. constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
  19276. super();
  19277. this.type = 'SphereGeometry';
  19278. this.parameters = {
  19279. radius: radius,
  19280. widthSegments: widthSegments,
  19281. heightSegments: heightSegments,
  19282. phiStart: phiStart,
  19283. phiLength: phiLength,
  19284. thetaStart: thetaStart,
  19285. thetaLength: thetaLength
  19286. };
  19287. this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
  19288. this.mergeVertices();
  19289. }
  19290. }
  19291. class TetrahedronBufferGeometry extends PolyhedronBufferGeometry {
  19292. constructor( radius = 1, detail = 0 ) {
  19293. const vertices = [
  19294. 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
  19295. ];
  19296. const indices = [
  19297. 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
  19298. ];
  19299. super( vertices, indices, radius, detail );
  19300. this.type = 'TetrahedronBufferGeometry';
  19301. this.parameters = {
  19302. radius: radius,
  19303. detail: detail
  19304. };
  19305. }
  19306. }
  19307. class TetrahedronGeometry extends Geometry {
  19308. constructor( radius, detail ) {
  19309. super();
  19310. this.type = 'TetrahedronGeometry';
  19311. this.parameters = {
  19312. radius: radius,
  19313. detail: detail
  19314. };
  19315. this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
  19316. this.mergeVertices();
  19317. }
  19318. }
  19319. /**
  19320. * Text = 3D Text
  19321. *
  19322. * parameters = {
  19323. * font: <THREE.Font>, // font
  19324. *
  19325. * size: <float>, // size of the text
  19326. * height: <float>, // thickness to extrude text
  19327. * curveSegments: <int>, // number of points on the curves
  19328. *
  19329. * bevelEnabled: <bool>, // turn on bevel
  19330. * bevelThickness: <float>, // how deep into text bevel goes
  19331. * bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
  19332. * bevelOffset: <float> // how far from text outline does bevel start
  19333. * }
  19334. */
  19335. class TextBufferGeometry extends ExtrudeBufferGeometry {
  19336. constructor( text, parameters = {} ) {
  19337. const font = parameters.font;
  19338. if ( ! ( font && font.isFont ) ) {
  19339. console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
  19340. return new BufferGeometry();
  19341. }
  19342. const shapes = font.generateShapes( text, parameters.size );
  19343. // translate parameters to ExtrudeGeometry API
  19344. parameters.depth = parameters.height !== undefined ? parameters.height : 50;
  19345. // defaults
  19346. if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
  19347. if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
  19348. if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
  19349. super( shapes, parameters );
  19350. this.type = 'TextBufferGeometry';
  19351. }
  19352. }
  19353. /**
  19354. * Text = 3D Text
  19355. *
  19356. * parameters = {
  19357. * font: <THREE.Font>, // font
  19358. *
  19359. * size: <float>, // size of the text
  19360. * height: <float>, // thickness to extrude text
  19361. * curveSegments: <int>, // number of points on the curves
  19362. *
  19363. * bevelEnabled: <bool>, // turn on bevel
  19364. * bevelThickness: <float>, // how deep into text bevel goes
  19365. * bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
  19366. * bevelOffset: <float> // how far from text outline does bevel start
  19367. * }
  19368. */
  19369. class TextGeometry extends Geometry {
  19370. constructor( text, parameters ) {
  19371. super();
  19372. this.type = 'TextGeometry';
  19373. this.parameters = {
  19374. text: text,
  19375. parameters: parameters
  19376. };
  19377. this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
  19378. this.mergeVertices();
  19379. }
  19380. }
  19381. class TorusBufferGeometry extends BufferGeometry {
  19382. constructor( radius = 1, tube = 0.4, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2 ) {
  19383. super();
  19384. this.type = 'TorusBufferGeometry';
  19385. this.parameters = {
  19386. radius: radius,
  19387. tube: tube,
  19388. radialSegments: radialSegments,
  19389. tubularSegments: tubularSegments,
  19390. arc: arc
  19391. };
  19392. radialSegments = Math.floor( radialSegments );
  19393. tubularSegments = Math.floor( tubularSegments );
  19394. // buffers
  19395. const indices = [];
  19396. const vertices = [];
  19397. const normals = [];
  19398. const uvs = [];
  19399. // helper variables
  19400. const center = new Vector3();
  19401. const vertex = new Vector3();
  19402. const normal = new Vector3();
  19403. // generate vertices, normals and uvs
  19404. for ( let j = 0; j <= radialSegments; j ++ ) {
  19405. for ( let i = 0; i <= tubularSegments; i ++ ) {
  19406. const u = i / tubularSegments * arc;
  19407. const v = j / radialSegments * Math.PI * 2;
  19408. // vertex
  19409. vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
  19410. vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
  19411. vertex.z = tube * Math.sin( v );
  19412. vertices.push( vertex.x, vertex.y, vertex.z );
  19413. // normal
  19414. center.x = radius * Math.cos( u );
  19415. center.y = radius * Math.sin( u );
  19416. normal.subVectors( vertex, center ).normalize();
  19417. normals.push( normal.x, normal.y, normal.z );
  19418. // uv
  19419. uvs.push( i / tubularSegments );
  19420. uvs.push( j / radialSegments );
  19421. }
  19422. }
  19423. // generate indices
  19424. for ( let j = 1; j <= radialSegments; j ++ ) {
  19425. for ( let i = 1; i <= tubularSegments; i ++ ) {
  19426. // indices
  19427. const a = ( tubularSegments + 1 ) * j + i - 1;
  19428. const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
  19429. const c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
  19430. const d = ( tubularSegments + 1 ) * j + i;
  19431. // faces
  19432. indices.push( a, b, d );
  19433. indices.push( b, c, d );
  19434. }
  19435. }
  19436. // build geometry
  19437. this.setIndex( indices );
  19438. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  19439. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  19440. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  19441. }
  19442. }
  19443. class TorusGeometry extends Geometry {
  19444. constructor( radius, tube, radialSegments, tubularSegments, arc ) {
  19445. super();
  19446. this.type = 'TorusGeometry';
  19447. this.parameters = {
  19448. radius: radius,
  19449. tube: tube,
  19450. radialSegments: radialSegments,
  19451. tubularSegments: tubularSegments,
  19452. arc: arc
  19453. };
  19454. this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
  19455. this.mergeVertices();
  19456. }
  19457. }
  19458. class TorusKnotBufferGeometry extends BufferGeometry {
  19459. constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
  19460. super();
  19461. this.type = 'TorusKnotBufferGeometry';
  19462. this.parameters = {
  19463. radius: radius,
  19464. tube: tube,
  19465. tubularSegments: tubularSegments,
  19466. radialSegments: radialSegments,
  19467. p: p,
  19468. q: q
  19469. };
  19470. tubularSegments = Math.floor( tubularSegments );
  19471. radialSegments = Math.floor( radialSegments );
  19472. // buffers
  19473. const indices = [];
  19474. const vertices = [];
  19475. const normals = [];
  19476. const uvs = [];
  19477. // helper variables
  19478. const vertex = new Vector3();
  19479. const normal = new Vector3();
  19480. const P1 = new Vector3();
  19481. const P2 = new Vector3();
  19482. const B = new Vector3();
  19483. const T = new Vector3();
  19484. const N = new Vector3();
  19485. // generate vertices, normals and uvs
  19486. for ( let i = 0; i <= tubularSegments; ++ i ) {
  19487. // the radian "u" is used to calculate the position on the torus curve of the current tubular segement
  19488. const u = i / tubularSegments * p * Math.PI * 2;
  19489. // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
  19490. // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
  19491. calculatePositionOnCurve( u, p, q, radius, P1 );
  19492. calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
  19493. // calculate orthonormal basis
  19494. T.subVectors( P2, P1 );
  19495. N.addVectors( P2, P1 );
  19496. B.crossVectors( T, N );
  19497. N.crossVectors( B, T );
  19498. // normalize B, N. T can be ignored, we don't use it
  19499. B.normalize();
  19500. N.normalize();
  19501. for ( let j = 0; j <= radialSegments; ++ j ) {
  19502. // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
  19503. // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
  19504. const v = j / radialSegments * Math.PI * 2;
  19505. const cx = - tube * Math.cos( v );
  19506. const cy = tube * Math.sin( v );
  19507. // now calculate the final vertex position.
  19508. // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
  19509. vertex.x = P1.x + ( cx * N.x + cy * B.x );
  19510. vertex.y = P1.y + ( cx * N.y + cy * B.y );
  19511. vertex.z = P1.z + ( cx * N.z + cy * B.z );
  19512. vertices.push( vertex.x, vertex.y, vertex.z );
  19513. // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
  19514. normal.subVectors( vertex, P1 ).normalize();
  19515. normals.push( normal.x, normal.y, normal.z );
  19516. // uv
  19517. uvs.push( i / tubularSegments );
  19518. uvs.push( j / radialSegments );
  19519. }
  19520. }
  19521. // generate indices
  19522. for ( let j = 1; j <= tubularSegments; j ++ ) {
  19523. for ( let i = 1; i <= radialSegments; i ++ ) {
  19524. // indices
  19525. const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
  19526. const b = ( radialSegments + 1 ) * j + ( i - 1 );
  19527. const c = ( radialSegments + 1 ) * j + i;
  19528. const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
  19529. // faces
  19530. indices.push( a, b, d );
  19531. indices.push( b, c, d );
  19532. }
  19533. }
  19534. // build geometry
  19535. this.setIndex( indices );
  19536. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  19537. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  19538. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  19539. // this function calculates the current position on the torus curve
  19540. function calculatePositionOnCurve( u, p, q, radius, position ) {
  19541. const cu = Math.cos( u );
  19542. const su = Math.sin( u );
  19543. const quOverP = q / p * u;
  19544. const cs = Math.cos( quOverP );
  19545. position.x = radius * ( 2 + cs ) * 0.5 * cu;
  19546. position.y = radius * ( 2 + cs ) * su * 0.5;
  19547. position.z = radius * Math.sin( quOverP ) * 0.5;
  19548. }
  19549. }
  19550. }
  19551. class TorusKnotGeometry extends Geometry {
  19552. constructor( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
  19553. super();
  19554. this.type = 'TorusKnotGeometry';
  19555. this.parameters = {
  19556. radius: radius,
  19557. tube: tube,
  19558. tubularSegments: tubularSegments,
  19559. radialSegments: radialSegments,
  19560. p: p,
  19561. q: q
  19562. };
  19563. if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
  19564. this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
  19565. this.mergeVertices();
  19566. }
  19567. }
  19568. class TubeBufferGeometry extends BufferGeometry {
  19569. constructor( path, tubularSegments = 64, radius = 1, radialSegments = 8, closed = false ) {
  19570. super();
  19571. this.type = 'TubeBufferGeometry';
  19572. this.parameters = {
  19573. path: path,
  19574. tubularSegments: tubularSegments,
  19575. radius: radius,
  19576. radialSegments: radialSegments,
  19577. closed: closed
  19578. };
  19579. const frames = path.computeFrenetFrames( tubularSegments, closed );
  19580. // expose internals
  19581. this.tangents = frames.tangents;
  19582. this.normals = frames.normals;
  19583. this.binormals = frames.binormals;
  19584. // helper variables
  19585. const vertex = new Vector3();
  19586. const normal = new Vector3();
  19587. const uv = new Vector2();
  19588. let P = new Vector3();
  19589. // buffer
  19590. const vertices = [];
  19591. const normals = [];
  19592. const uvs = [];
  19593. const indices = [];
  19594. // create buffer data
  19595. generateBufferData();
  19596. // build geometry
  19597. this.setIndex( indices );
  19598. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  19599. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  19600. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  19601. // functions
  19602. function generateBufferData() {
  19603. for ( let i = 0; i < tubularSegments; i ++ ) {
  19604. generateSegment( i );
  19605. }
  19606. // if the geometry is not closed, generate the last row of vertices and normals
  19607. // at the regular position on the given path
  19608. //
  19609. // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
  19610. generateSegment( ( closed === false ) ? tubularSegments : 0 );
  19611. // uvs are generated in a separate function.
  19612. // this makes it easy compute correct values for closed geometries
  19613. generateUVs();
  19614. // finally create faces
  19615. generateIndices();
  19616. }
  19617. function generateSegment( i ) {
  19618. // we use getPointAt to sample evenly distributed points from the given path
  19619. P = path.getPointAt( i / tubularSegments, P );
  19620. // retrieve corresponding normal and binormal
  19621. const N = frames.normals[ i ];
  19622. const B = frames.binormals[ i ];
  19623. // generate normals and vertices for the current segment
  19624. for ( let j = 0; j <= radialSegments; j ++ ) {
  19625. const v = j / radialSegments * Math.PI * 2;
  19626. const sin = Math.sin( v );
  19627. const cos = - Math.cos( v );
  19628. // normal
  19629. normal.x = ( cos * N.x + sin * B.x );
  19630. normal.y = ( cos * N.y + sin * B.y );
  19631. normal.z = ( cos * N.z + sin * B.z );
  19632. normal.normalize();
  19633. normals.push( normal.x, normal.y, normal.z );
  19634. // vertex
  19635. vertex.x = P.x + radius * normal.x;
  19636. vertex.y = P.y + radius * normal.y;
  19637. vertex.z = P.z + radius * normal.z;
  19638. vertices.push( vertex.x, vertex.y, vertex.z );
  19639. }
  19640. }
  19641. function generateIndices() {
  19642. for ( let j = 1; j <= tubularSegments; j ++ ) {
  19643. for ( let i = 1; i <= radialSegments; i ++ ) {
  19644. const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
  19645. const b = ( radialSegments + 1 ) * j + ( i - 1 );
  19646. const c = ( radialSegments + 1 ) * j + i;
  19647. const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
  19648. // faces
  19649. indices.push( a, b, d );
  19650. indices.push( b, c, d );
  19651. }
  19652. }
  19653. }
  19654. function generateUVs() {
  19655. for ( let i = 0; i <= tubularSegments; i ++ ) {
  19656. for ( let j = 0; j <= radialSegments; j ++ ) {
  19657. uv.x = i / tubularSegments;
  19658. uv.y = j / radialSegments;
  19659. uvs.push( uv.x, uv.y );
  19660. }
  19661. }
  19662. }
  19663. }
  19664. toJSON() {
  19665. const data = BufferGeometry.prototype.toJSON.call( this );
  19666. data.path = this.parameters.path.toJSON();
  19667. return data;
  19668. }
  19669. }
  19670. class TubeGeometry extends Geometry {
  19671. constructor( path, tubularSegments, radius, radialSegments, closed, taper ) {
  19672. super();
  19673. this.type = 'TubeGeometry';
  19674. this.parameters = {
  19675. path: path,
  19676. tubularSegments: tubularSegments,
  19677. radius: radius,
  19678. radialSegments: radialSegments,
  19679. closed: closed
  19680. };
  19681. if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
  19682. const bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
  19683. // expose internals
  19684. this.tangents = bufferGeometry.tangents;
  19685. this.normals = bufferGeometry.normals;
  19686. this.binormals = bufferGeometry.binormals;
  19687. // create geometry
  19688. this.fromBufferGeometry( bufferGeometry );
  19689. this.mergeVertices();
  19690. }
  19691. }
  19692. class WireframeGeometry extends BufferGeometry {
  19693. constructor( geometry ) {
  19694. super();
  19695. this.type = 'WireframeGeometry';
  19696. // buffer
  19697. const vertices = [];
  19698. // helper variables
  19699. const edge = [ 0, 0 ], edges = {};
  19700. const keys = [ 'a', 'b', 'c' ];
  19701. // different logic for Geometry and BufferGeometry
  19702. if ( geometry && geometry.isGeometry ) {
  19703. // create a data structure that contains all edges without duplicates
  19704. const faces = geometry.faces;
  19705. for ( let i = 0, l = faces.length; i < l; i ++ ) {
  19706. const face = faces[ i ];
  19707. for ( let j = 0; j < 3; j ++ ) {
  19708. const edge1 = face[ keys[ j ] ];
  19709. const edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
  19710. edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
  19711. edge[ 1 ] = Math.max( edge1, edge2 );
  19712. const key = edge[ 0 ] + ',' + edge[ 1 ];
  19713. if ( edges[ key ] === undefined ) {
  19714. edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
  19715. }
  19716. }
  19717. }
  19718. // generate vertices
  19719. for ( const key in edges ) {
  19720. const e = edges[ key ];
  19721. let vertex = geometry.vertices[ e.index1 ];
  19722. vertices.push( vertex.x, vertex.y, vertex.z );
  19723. vertex = geometry.vertices[ e.index2 ];
  19724. vertices.push( vertex.x, vertex.y, vertex.z );
  19725. }
  19726. } else if ( geometry && geometry.isBufferGeometry ) {
  19727. const vertex = new Vector3();
  19728. if ( geometry.index !== null ) {
  19729. // indexed BufferGeometry
  19730. const position = geometry.attributes.position;
  19731. const indices = geometry.index;
  19732. let groups = geometry.groups;
  19733. if ( groups.length === 0 ) {
  19734. groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
  19735. }
  19736. // create a data structure that contains all eges without duplicates
  19737. for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
  19738. const group = groups[ o ];
  19739. const start = group.start;
  19740. const count = group.count;
  19741. for ( let i = start, l = ( start + count ); i < l; i += 3 ) {
  19742. for ( let j = 0; j < 3; j ++ ) {
  19743. const edge1 = indices.getX( i + j );
  19744. const edge2 = indices.getX( i + ( j + 1 ) % 3 );
  19745. edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
  19746. edge[ 1 ] = Math.max( edge1, edge2 );
  19747. const key = edge[ 0 ] + ',' + edge[ 1 ];
  19748. if ( edges[ key ] === undefined ) {
  19749. edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
  19750. }
  19751. }
  19752. }
  19753. }
  19754. // generate vertices
  19755. for ( const key in edges ) {
  19756. const e = edges[ key ];
  19757. vertex.fromBufferAttribute( position, e.index1 );
  19758. vertices.push( vertex.x, vertex.y, vertex.z );
  19759. vertex.fromBufferAttribute( position, e.index2 );
  19760. vertices.push( vertex.x, vertex.y, vertex.z );
  19761. }
  19762. } else {
  19763. // non-indexed BufferGeometry
  19764. const position = geometry.attributes.position;
  19765. for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
  19766. for ( let j = 0; j < 3; j ++ ) {
  19767. // three edges per triangle, an edge is represented as (index1, index2)
  19768. // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
  19769. const index1 = 3 * i + j;
  19770. vertex.fromBufferAttribute( position, index1 );
  19771. vertices.push( vertex.x, vertex.y, vertex.z );
  19772. const index2 = 3 * i + ( ( j + 1 ) % 3 );
  19773. vertex.fromBufferAttribute( position, index2 );
  19774. vertices.push( vertex.x, vertex.y, vertex.z );
  19775. }
  19776. }
  19777. }
  19778. }
  19779. // build geometry
  19780. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  19781. }
  19782. }
  19783. var Geometries = /*#__PURE__*/Object.freeze({
  19784. __proto__: null,
  19785. BoxGeometry: BoxGeometry,
  19786. BoxBufferGeometry: BoxBufferGeometry,
  19787. CircleGeometry: CircleGeometry,
  19788. CircleBufferGeometry: CircleBufferGeometry,
  19789. ConeGeometry: ConeGeometry,
  19790. ConeBufferGeometry: ConeBufferGeometry,
  19791. CylinderGeometry: CylinderGeometry,
  19792. CylinderBufferGeometry: CylinderBufferGeometry,
  19793. DodecahedronGeometry: DodecahedronGeometry,
  19794. DodecahedronBufferGeometry: DodecahedronBufferGeometry,
  19795. EdgesGeometry: EdgesGeometry,
  19796. ExtrudeGeometry: ExtrudeGeometry,
  19797. ExtrudeBufferGeometry: ExtrudeBufferGeometry,
  19798. IcosahedronGeometry: IcosahedronGeometry,
  19799. IcosahedronBufferGeometry: IcosahedronBufferGeometry,
  19800. LatheGeometry: LatheGeometry,
  19801. LatheBufferGeometry: LatheBufferGeometry,
  19802. OctahedronGeometry: OctahedronGeometry,
  19803. OctahedronBufferGeometry: OctahedronBufferGeometry,
  19804. ParametricGeometry: ParametricGeometry,
  19805. ParametricBufferGeometry: ParametricBufferGeometry,
  19806. PlaneGeometry: PlaneGeometry,
  19807. PlaneBufferGeometry: PlaneBufferGeometry,
  19808. PolyhedronGeometry: PolyhedronGeometry,
  19809. PolyhedronBufferGeometry: PolyhedronBufferGeometry,
  19810. RingGeometry: RingGeometry,
  19811. RingBufferGeometry: RingBufferGeometry,
  19812. ShapeGeometry: ShapeGeometry,
  19813. ShapeBufferGeometry: ShapeBufferGeometry,
  19814. SphereGeometry: SphereGeometry,
  19815. SphereBufferGeometry: SphereBufferGeometry,
  19816. TetrahedronGeometry: TetrahedronGeometry,
  19817. TetrahedronBufferGeometry: TetrahedronBufferGeometry,
  19818. TextGeometry: TextGeometry,
  19819. TextBufferGeometry: TextBufferGeometry,
  19820. TorusGeometry: TorusGeometry,
  19821. TorusBufferGeometry: TorusBufferGeometry,
  19822. TorusKnotGeometry: TorusKnotGeometry,
  19823. TorusKnotBufferGeometry: TorusKnotBufferGeometry,
  19824. TubeGeometry: TubeGeometry,
  19825. TubeBufferGeometry: TubeBufferGeometry,
  19826. WireframeGeometry: WireframeGeometry
  19827. });
  19828. /**
  19829. * parameters = {
  19830. * color: <THREE.Color>
  19831. * }
  19832. */
  19833. function ShadowMaterial( parameters ) {
  19834. Material.call( this );
  19835. this.type = 'ShadowMaterial';
  19836. this.color = new Color( 0x000000 );
  19837. this.transparent = true;
  19838. this.setValues( parameters );
  19839. }
  19840. ShadowMaterial.prototype = Object.create( Material.prototype );
  19841. ShadowMaterial.prototype.constructor = ShadowMaterial;
  19842. ShadowMaterial.prototype.isShadowMaterial = true;
  19843. ShadowMaterial.prototype.copy = function ( source ) {
  19844. Material.prototype.copy.call( this, source );
  19845. this.color.copy( source.color );
  19846. return this;
  19847. };
  19848. function RawShaderMaterial( parameters ) {
  19849. ShaderMaterial.call( this, parameters );
  19850. this.type = 'RawShaderMaterial';
  19851. }
  19852. RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
  19853. RawShaderMaterial.prototype.constructor = RawShaderMaterial;
  19854. RawShaderMaterial.prototype.isRawShaderMaterial = true;
  19855. /**
  19856. * parameters = {
  19857. * color: <hex>,
  19858. * roughness: <float>,
  19859. * metalness: <float>,
  19860. * opacity: <float>,
  19861. *
  19862. * map: new THREE.Texture( <Image> ),
  19863. *
  19864. * lightMap: new THREE.Texture( <Image> ),
  19865. * lightMapIntensity: <float>
  19866. *
  19867. * aoMap: new THREE.Texture( <Image> ),
  19868. * aoMapIntensity: <float>
  19869. *
  19870. * emissive: <hex>,
  19871. * emissiveIntensity: <float>
  19872. * emissiveMap: new THREE.Texture( <Image> ),
  19873. *
  19874. * bumpMap: new THREE.Texture( <Image> ),
  19875. * bumpScale: <float>,
  19876. *
  19877. * normalMap: new THREE.Texture( <Image> ),
  19878. * normalMapType: THREE.TangentSpaceNormalMap,
  19879. * normalScale: <Vector2>,
  19880. *
  19881. * displacementMap: new THREE.Texture( <Image> ),
  19882. * displacementScale: <float>,
  19883. * displacementBias: <float>,
  19884. *
  19885. * roughnessMap: new THREE.Texture( <Image> ),
  19886. *
  19887. * metalnessMap: new THREE.Texture( <Image> ),
  19888. *
  19889. * alphaMap: new THREE.Texture( <Image> ),
  19890. *
  19891. * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
  19892. * envMapIntensity: <float>
  19893. *
  19894. * refractionRatio: <float>,
  19895. *
  19896. * wireframe: <boolean>,
  19897. * wireframeLinewidth: <float>,
  19898. *
  19899. * skinning: <bool>,
  19900. * morphTargets: <bool>,
  19901. * morphNormals: <bool>
  19902. * }
  19903. */
  19904. function MeshStandardMaterial( parameters ) {
  19905. Material.call( this );
  19906. this.defines = { 'STANDARD': '' };
  19907. this.type = 'MeshStandardMaterial';
  19908. this.color = new Color( 0xffffff ); // diffuse
  19909. this.roughness = 1.0;
  19910. this.metalness = 0.0;
  19911. this.map = null;
  19912. this.lightMap = null;
  19913. this.lightMapIntensity = 1.0;
  19914. this.aoMap = null;
  19915. this.aoMapIntensity = 1.0;
  19916. this.emissive = new Color( 0x000000 );
  19917. this.emissiveIntensity = 1.0;
  19918. this.emissiveMap = null;
  19919. this.bumpMap = null;
  19920. this.bumpScale = 1;
  19921. this.normalMap = null;
  19922. this.normalMapType = TangentSpaceNormalMap;
  19923. this.normalScale = new Vector2( 1, 1 );
  19924. this.displacementMap = null;
  19925. this.displacementScale = 1;
  19926. this.displacementBias = 0;
  19927. this.roughnessMap = null;
  19928. this.metalnessMap = null;
  19929. this.alphaMap = null;
  19930. this.envMap = null;
  19931. this.envMapIntensity = 1.0;
  19932. this.refractionRatio = 0.98;
  19933. this.wireframe = false;
  19934. this.wireframeLinewidth = 1;
  19935. this.wireframeLinecap = 'round';
  19936. this.wireframeLinejoin = 'round';
  19937. this.skinning = false;
  19938. this.morphTargets = false;
  19939. this.morphNormals = false;
  19940. this.vertexTangents = false;
  19941. this.setValues( parameters );
  19942. }
  19943. MeshStandardMaterial.prototype = Object.create( Material.prototype );
  19944. MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
  19945. MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
  19946. MeshStandardMaterial.prototype.copy = function ( source ) {
  19947. Material.prototype.copy.call( this, source );
  19948. this.defines = { 'STANDARD': '' };
  19949. this.color.copy( source.color );
  19950. this.roughness = source.roughness;
  19951. this.metalness = source.metalness;
  19952. this.map = source.map;
  19953. this.lightMap = source.lightMap;
  19954. this.lightMapIntensity = source.lightMapIntensity;
  19955. this.aoMap = source.aoMap;
  19956. this.aoMapIntensity = source.aoMapIntensity;
  19957. this.emissive.copy( source.emissive );
  19958. this.emissiveMap = source.emissiveMap;
  19959. this.emissiveIntensity = source.emissiveIntensity;
  19960. this.bumpMap = source.bumpMap;
  19961. this.bumpScale = source.bumpScale;
  19962. this.normalMap = source.normalMap;
  19963. this.normalMapType = source.normalMapType;
  19964. this.normalScale.copy( source.normalScale );
  19965. this.displacementMap = source.displacementMap;
  19966. this.displacementScale = source.displacementScale;
  19967. this.displacementBias = source.displacementBias;
  19968. this.roughnessMap = source.roughnessMap;
  19969. this.metalnessMap = source.metalnessMap;
  19970. this.alphaMap = source.alphaMap;
  19971. this.envMap = source.envMap;
  19972. this.envMapIntensity = source.envMapIntensity;
  19973. this.refractionRatio = source.refractionRatio;
  19974. this.wireframe = source.wireframe;
  19975. this.wireframeLinewidth = source.wireframeLinewidth;
  19976. this.wireframeLinecap = source.wireframeLinecap;
  19977. this.wireframeLinejoin = source.wireframeLinejoin;
  19978. this.skinning = source.skinning;
  19979. this.morphTargets = source.morphTargets;
  19980. this.morphNormals = source.morphNormals;
  19981. this.vertexTangents = source.vertexTangents;
  19982. return this;
  19983. };
  19984. /**
  19985. * parameters = {
  19986. * clearcoat: <float>,
  19987. * clearcoatMap: new THREE.Texture( <Image> ),
  19988. * clearcoatRoughness: <float>,
  19989. * clearcoatRoughnessMap: new THREE.Texture( <Image> ),
  19990. * clearcoatNormalScale: <Vector2>,
  19991. * clearcoatNormalMap: new THREE.Texture( <Image> ),
  19992. *
  19993. * reflectivity: <float>,
  19994. * ior: <float>,
  19995. *
  19996. * sheen: <Color>,
  19997. *
  19998. * transmission: <float>,
  19999. * transmissionMap: new THREE.Texture( <Image> )
  20000. * }
  20001. */
  20002. function MeshPhysicalMaterial( parameters ) {
  20003. MeshStandardMaterial.call( this );
  20004. this.defines = {
  20005. 'STANDARD': '',
  20006. 'PHYSICAL': ''
  20007. };
  20008. this.type = 'MeshPhysicalMaterial';
  20009. this.clearcoat = 0.0;
  20010. this.clearcoatMap = null;
  20011. this.clearcoatRoughness = 0.0;
  20012. this.clearcoatRoughnessMap = null;
  20013. this.clearcoatNormalScale = new Vector2( 1, 1 );
  20014. this.clearcoatNormalMap = null;
  20015. this.reflectivity = 0.5; // maps to F0 = 0.04
  20016. Object.defineProperty( this, 'ior', {
  20017. get: function () {
  20018. return ( 1 + 0.4 * this.reflectivity ) / ( 1 - 0.4 * this.reflectivity );
  20019. },
  20020. set: function ( ior ) {
  20021. this.reflectivity = MathUtils$1.clamp( 2.5 * ( ior - 1 ) / ( ior + 1 ), 0, 1 );
  20022. }
  20023. } );
  20024. this.sheen = null; // null will disable sheen bsdf
  20025. this.transmission = 0.0;
  20026. this.transmissionMap = null;
  20027. this.setValues( parameters );
  20028. }
  20029. MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
  20030. MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
  20031. MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
  20032. MeshPhysicalMaterial.prototype.copy = function ( source ) {
  20033. MeshStandardMaterial.prototype.copy.call( this, source );
  20034. this.defines = {
  20035. 'STANDARD': '',
  20036. 'PHYSICAL': ''
  20037. };
  20038. this.clearcoat = source.clearcoat;
  20039. this.clearcoatMap = source.clearcoatMap;
  20040. this.clearcoatRoughness = source.clearcoatRoughness;
  20041. this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
  20042. this.clearcoatNormalMap = source.clearcoatNormalMap;
  20043. this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
  20044. this.reflectivity = source.reflectivity;
  20045. if ( source.sheen ) {
  20046. this.sheen = ( this.sheen || new Color() ).copy( source.sheen );
  20047. } else {
  20048. this.sheen = null;
  20049. }
  20050. this.transmission = source.transmission;
  20051. this.transmissionMap = source.transmissionMap;
  20052. return this;
  20053. };
  20054. /**
  20055. * parameters = {
  20056. * color: <hex>,
  20057. * specular: <hex>,
  20058. * shininess: <float>,
  20059. * opacity: <float>,
  20060. *
  20061. * map: new THREE.Texture( <Image> ),
  20062. *
  20063. * lightMap: new THREE.Texture( <Image> ),
  20064. * lightMapIntensity: <float>
  20065. *
  20066. * aoMap: new THREE.Texture( <Image> ),
  20067. * aoMapIntensity: <float>
  20068. *
  20069. * emissive: <hex>,
  20070. * emissiveIntensity: <float>
  20071. * emissiveMap: new THREE.Texture( <Image> ),
  20072. *
  20073. * bumpMap: new THREE.Texture( <Image> ),
  20074. * bumpScale: <float>,
  20075. *
  20076. * normalMap: new THREE.Texture( <Image> ),
  20077. * normalMapType: THREE.TangentSpaceNormalMap,
  20078. * normalScale: <Vector2>,
  20079. *
  20080. * displacementMap: new THREE.Texture( <Image> ),
  20081. * displacementScale: <float>,
  20082. * displacementBias: <float>,
  20083. *
  20084. * specularMap: new THREE.Texture( <Image> ),
  20085. *
  20086. * alphaMap: new THREE.Texture( <Image> ),
  20087. *
  20088. * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
  20089. * combine: THREE.MultiplyOperation,
  20090. * reflectivity: <float>,
  20091. * refractionRatio: <float>,
  20092. *
  20093. * wireframe: <boolean>,
  20094. * wireframeLinewidth: <float>,
  20095. *
  20096. * skinning: <bool>,
  20097. * morphTargets: <bool>,
  20098. * morphNormals: <bool>
  20099. * }
  20100. */
  20101. function MeshPhongMaterial( parameters ) {
  20102. Material.call( this );
  20103. this.type = 'MeshPhongMaterial';
  20104. this.color = new Color( 0xffffff ); // diffuse
  20105. this.specular = new Color( 0x111111 );
  20106. this.shininess = 30;
  20107. this.map = null;
  20108. this.lightMap = null;
  20109. this.lightMapIntensity = 1.0;
  20110. this.aoMap = null;
  20111. this.aoMapIntensity = 1.0;
  20112. this.emissive = new Color( 0x000000 );
  20113. this.emissiveIntensity = 1.0;
  20114. this.emissiveMap = null;
  20115. this.bumpMap = null;
  20116. this.bumpScale = 1;
  20117. this.normalMap = null;
  20118. this.normalMapType = TangentSpaceNormalMap;
  20119. this.normalScale = new Vector2( 1, 1 );
  20120. this.displacementMap = null;
  20121. this.displacementScale = 1;
  20122. this.displacementBias = 0;
  20123. this.specularMap = null;
  20124. this.alphaMap = null;
  20125. this.envMap = null;
  20126. this.combine = MultiplyOperation;
  20127. this.reflectivity = 1;
  20128. this.refractionRatio = 0.98;
  20129. this.wireframe = false;
  20130. this.wireframeLinewidth = 1;
  20131. this.wireframeLinecap = 'round';
  20132. this.wireframeLinejoin = 'round';
  20133. this.skinning = false;
  20134. this.morphTargets = false;
  20135. this.morphNormals = false;
  20136. this.setValues( parameters );
  20137. }
  20138. MeshPhongMaterial.prototype = Object.create( Material.prototype );
  20139. MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
  20140. MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
  20141. MeshPhongMaterial.prototype.copy = function ( source ) {
  20142. Material.prototype.copy.call( this, source );
  20143. this.color.copy( source.color );
  20144. this.specular.copy( source.specular );
  20145. this.shininess = source.shininess;
  20146. this.map = source.map;
  20147. this.lightMap = source.lightMap;
  20148. this.lightMapIntensity = source.lightMapIntensity;
  20149. this.aoMap = source.aoMap;
  20150. this.aoMapIntensity = source.aoMapIntensity;
  20151. this.emissive.copy( source.emissive );
  20152. this.emissiveMap = source.emissiveMap;
  20153. this.emissiveIntensity = source.emissiveIntensity;
  20154. this.bumpMap = source.bumpMap;
  20155. this.bumpScale = source.bumpScale;
  20156. this.normalMap = source.normalMap;
  20157. this.normalMapType = source.normalMapType;
  20158. this.normalScale.copy( source.normalScale );
  20159. this.displacementMap = source.displacementMap;
  20160. this.displacementScale = source.displacementScale;
  20161. this.displacementBias = source.displacementBias;
  20162. this.specularMap = source.specularMap;
  20163. this.alphaMap = source.alphaMap;
  20164. this.envMap = source.envMap;
  20165. this.combine = source.combine;
  20166. this.reflectivity = source.reflectivity;
  20167. this.refractionRatio = source.refractionRatio;
  20168. this.wireframe = source.wireframe;
  20169. this.wireframeLinewidth = source.wireframeLinewidth;
  20170. this.wireframeLinecap = source.wireframeLinecap;
  20171. this.wireframeLinejoin = source.wireframeLinejoin;
  20172. this.skinning = source.skinning;
  20173. this.morphTargets = source.morphTargets;
  20174. this.morphNormals = source.morphNormals;
  20175. return this;
  20176. };
  20177. /**
  20178. * parameters = {
  20179. * color: <hex>,
  20180. *
  20181. * map: new THREE.Texture( <Image> ),
  20182. * gradientMap: new THREE.Texture( <Image> ),
  20183. *
  20184. * lightMap: new THREE.Texture( <Image> ),
  20185. * lightMapIntensity: <float>
  20186. *
  20187. * aoMap: new THREE.Texture( <Image> ),
  20188. * aoMapIntensity: <float>
  20189. *
  20190. * emissive: <hex>,
  20191. * emissiveIntensity: <float>
  20192. * emissiveMap: new THREE.Texture( <Image> ),
  20193. *
  20194. * bumpMap: new THREE.Texture( <Image> ),
  20195. * bumpScale: <float>,
  20196. *
  20197. * normalMap: new THREE.Texture( <Image> ),
  20198. * normalMapType: THREE.TangentSpaceNormalMap,
  20199. * normalScale: <Vector2>,
  20200. *
  20201. * displacementMap: new THREE.Texture( <Image> ),
  20202. * displacementScale: <float>,
  20203. * displacementBias: <float>,
  20204. *
  20205. * alphaMap: new THREE.Texture( <Image> ),
  20206. *
  20207. * wireframe: <boolean>,
  20208. * wireframeLinewidth: <float>,
  20209. *
  20210. * skinning: <bool>,
  20211. * morphTargets: <bool>,
  20212. * morphNormals: <bool>
  20213. * }
  20214. */
  20215. function MeshToonMaterial( parameters ) {
  20216. Material.call( this );
  20217. this.defines = { 'TOON': '' };
  20218. this.type = 'MeshToonMaterial';
  20219. this.color = new Color( 0xffffff );
  20220. this.map = null;
  20221. this.gradientMap = null;
  20222. this.lightMap = null;
  20223. this.lightMapIntensity = 1.0;
  20224. this.aoMap = null;
  20225. this.aoMapIntensity = 1.0;
  20226. this.emissive = new Color( 0x000000 );
  20227. this.emissiveIntensity = 1.0;
  20228. this.emissiveMap = null;
  20229. this.bumpMap = null;
  20230. this.bumpScale = 1;
  20231. this.normalMap = null;
  20232. this.normalMapType = TangentSpaceNormalMap;
  20233. this.normalScale = new Vector2( 1, 1 );
  20234. this.displacementMap = null;
  20235. this.displacementScale = 1;
  20236. this.displacementBias = 0;
  20237. this.alphaMap = null;
  20238. this.wireframe = false;
  20239. this.wireframeLinewidth = 1;
  20240. this.wireframeLinecap = 'round';
  20241. this.wireframeLinejoin = 'round';
  20242. this.skinning = false;
  20243. this.morphTargets = false;
  20244. this.morphNormals = false;
  20245. this.setValues( parameters );
  20246. }
  20247. MeshToonMaterial.prototype = Object.create( Material.prototype );
  20248. MeshToonMaterial.prototype.constructor = MeshToonMaterial;
  20249. MeshToonMaterial.prototype.isMeshToonMaterial = true;
  20250. MeshToonMaterial.prototype.copy = function ( source ) {
  20251. Material.prototype.copy.call( this, source );
  20252. this.color.copy( source.color );
  20253. this.map = source.map;
  20254. this.gradientMap = source.gradientMap;
  20255. this.lightMap = source.lightMap;
  20256. this.lightMapIntensity = source.lightMapIntensity;
  20257. this.aoMap = source.aoMap;
  20258. this.aoMapIntensity = source.aoMapIntensity;
  20259. this.emissive.copy( source.emissive );
  20260. this.emissiveMap = source.emissiveMap;
  20261. this.emissiveIntensity = source.emissiveIntensity;
  20262. this.bumpMap = source.bumpMap;
  20263. this.bumpScale = source.bumpScale;
  20264. this.normalMap = source.normalMap;
  20265. this.normalMapType = source.normalMapType;
  20266. this.normalScale.copy( source.normalScale );
  20267. this.displacementMap = source.displacementMap;
  20268. this.displacementScale = source.displacementScale;
  20269. this.displacementBias = source.displacementBias;
  20270. this.alphaMap = source.alphaMap;
  20271. this.wireframe = source.wireframe;
  20272. this.wireframeLinewidth = source.wireframeLinewidth;
  20273. this.wireframeLinecap = source.wireframeLinecap;
  20274. this.wireframeLinejoin = source.wireframeLinejoin;
  20275. this.skinning = source.skinning;
  20276. this.morphTargets = source.morphTargets;
  20277. this.morphNormals = source.morphNormals;
  20278. return this;
  20279. };
  20280. /**
  20281. * parameters = {
  20282. * opacity: <float>,
  20283. *
  20284. * bumpMap: new THREE.Texture( <Image> ),
  20285. * bumpScale: <float>,
  20286. *
  20287. * normalMap: new THREE.Texture( <Image> ),
  20288. * normalMapType: THREE.TangentSpaceNormalMap,
  20289. * normalScale: <Vector2>,
  20290. *
  20291. * displacementMap: new THREE.Texture( <Image> ),
  20292. * displacementScale: <float>,
  20293. * displacementBias: <float>,
  20294. *
  20295. * wireframe: <boolean>,
  20296. * wireframeLinewidth: <float>
  20297. *
  20298. * skinning: <bool>,
  20299. * morphTargets: <bool>,
  20300. * morphNormals: <bool>
  20301. * }
  20302. */
  20303. function MeshNormalMaterial( parameters ) {
  20304. Material.call( this );
  20305. this.type = 'MeshNormalMaterial';
  20306. this.bumpMap = null;
  20307. this.bumpScale = 1;
  20308. this.normalMap = null;
  20309. this.normalMapType = TangentSpaceNormalMap;
  20310. this.normalScale = new Vector2( 1, 1 );
  20311. this.displacementMap = null;
  20312. this.displacementScale = 1;
  20313. this.displacementBias = 0;
  20314. this.wireframe = false;
  20315. this.wireframeLinewidth = 1;
  20316. this.fog = false;
  20317. this.skinning = false;
  20318. this.morphTargets = false;
  20319. this.morphNormals = false;
  20320. this.setValues( parameters );
  20321. }
  20322. MeshNormalMaterial.prototype = Object.create( Material.prototype );
  20323. MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
  20324. MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
  20325. MeshNormalMaterial.prototype.copy = function ( source ) {
  20326. Material.prototype.copy.call( this, source );
  20327. this.bumpMap = source.bumpMap;
  20328. this.bumpScale = source.bumpScale;
  20329. this.normalMap = source.normalMap;
  20330. this.normalMapType = source.normalMapType;
  20331. this.normalScale.copy( source.normalScale );
  20332. this.displacementMap = source.displacementMap;
  20333. this.displacementScale = source.displacementScale;
  20334. this.displacementBias = source.displacementBias;
  20335. this.wireframe = source.wireframe;
  20336. this.wireframeLinewidth = source.wireframeLinewidth;
  20337. this.skinning = source.skinning;
  20338. this.morphTargets = source.morphTargets;
  20339. this.morphNormals = source.morphNormals;
  20340. return this;
  20341. };
  20342. /**
  20343. * parameters = {
  20344. * color: <hex>,
  20345. * opacity: <float>,
  20346. *
  20347. * map: new THREE.Texture( <Image> ),
  20348. *
  20349. * lightMap: new THREE.Texture( <Image> ),
  20350. * lightMapIntensity: <float>
  20351. *
  20352. * aoMap: new THREE.Texture( <Image> ),
  20353. * aoMapIntensity: <float>
  20354. *
  20355. * emissive: <hex>,
  20356. * emissiveIntensity: <float>
  20357. * emissiveMap: new THREE.Texture( <Image> ),
  20358. *
  20359. * specularMap: new THREE.Texture( <Image> ),
  20360. *
  20361. * alphaMap: new THREE.Texture( <Image> ),
  20362. *
  20363. * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
  20364. * combine: THREE.Multiply,
  20365. * reflectivity: <float>,
  20366. * refractionRatio: <float>,
  20367. *
  20368. * wireframe: <boolean>,
  20369. * wireframeLinewidth: <float>,
  20370. *
  20371. * skinning: <bool>,
  20372. * morphTargets: <bool>,
  20373. * morphNormals: <bool>
  20374. * }
  20375. */
  20376. function MeshLambertMaterial( parameters ) {
  20377. Material.call( this );
  20378. this.type = 'MeshLambertMaterial';
  20379. this.color = new Color( 0xffffff ); // diffuse
  20380. this.map = null;
  20381. this.lightMap = null;
  20382. this.lightMapIntensity = 1.0;
  20383. this.aoMap = null;
  20384. this.aoMapIntensity = 1.0;
  20385. this.emissive = new Color( 0x000000 );
  20386. this.emissiveIntensity = 1.0;
  20387. this.emissiveMap = null;
  20388. this.specularMap = null;
  20389. this.alphaMap = null;
  20390. this.envMap = null;
  20391. this.combine = MultiplyOperation;
  20392. this.reflectivity = 1;
  20393. this.refractionRatio = 0.98;
  20394. this.wireframe = false;
  20395. this.wireframeLinewidth = 1;
  20396. this.wireframeLinecap = 'round';
  20397. this.wireframeLinejoin = 'round';
  20398. this.skinning = false;
  20399. this.morphTargets = false;
  20400. this.morphNormals = false;
  20401. this.setValues( parameters );
  20402. }
  20403. MeshLambertMaterial.prototype = Object.create( Material.prototype );
  20404. MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
  20405. MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
  20406. MeshLambertMaterial.prototype.copy = function ( source ) {
  20407. Material.prototype.copy.call( this, source );
  20408. this.color.copy( source.color );
  20409. this.map = source.map;
  20410. this.lightMap = source.lightMap;
  20411. this.lightMapIntensity = source.lightMapIntensity;
  20412. this.aoMap = source.aoMap;
  20413. this.aoMapIntensity = source.aoMapIntensity;
  20414. this.emissive.copy( source.emissive );
  20415. this.emissiveMap = source.emissiveMap;
  20416. this.emissiveIntensity = source.emissiveIntensity;
  20417. this.specularMap = source.specularMap;
  20418. this.alphaMap = source.alphaMap;
  20419. this.envMap = source.envMap;
  20420. this.combine = source.combine;
  20421. this.reflectivity = source.reflectivity;
  20422. this.refractionRatio = source.refractionRatio;
  20423. this.wireframe = source.wireframe;
  20424. this.wireframeLinewidth = source.wireframeLinewidth;
  20425. this.wireframeLinecap = source.wireframeLinecap;
  20426. this.wireframeLinejoin = source.wireframeLinejoin;
  20427. this.skinning = source.skinning;
  20428. this.morphTargets = source.morphTargets;
  20429. this.morphNormals = source.morphNormals;
  20430. return this;
  20431. };
  20432. /**
  20433. * parameters = {
  20434. * color: <hex>,
  20435. * opacity: <float>,
  20436. *
  20437. * matcap: new THREE.Texture( <Image> ),
  20438. *
  20439. * map: new THREE.Texture( <Image> ),
  20440. *
  20441. * bumpMap: new THREE.Texture( <Image> ),
  20442. * bumpScale: <float>,
  20443. *
  20444. * normalMap: new THREE.Texture( <Image> ),
  20445. * normalMapType: THREE.TangentSpaceNormalMap,
  20446. * normalScale: <Vector2>,
  20447. *
  20448. * displacementMap: new THREE.Texture( <Image> ),
  20449. * displacementScale: <float>,
  20450. * displacementBias: <float>,
  20451. *
  20452. * alphaMap: new THREE.Texture( <Image> ),
  20453. *
  20454. * skinning: <bool>,
  20455. * morphTargets: <bool>,
  20456. * morphNormals: <bool>
  20457. * }
  20458. */
  20459. function MeshMatcapMaterial( parameters ) {
  20460. Material.call( this );
  20461. this.defines = { 'MATCAP': '' };
  20462. this.type = 'MeshMatcapMaterial';
  20463. this.color = new Color( 0xffffff ); // diffuse
  20464. this.matcap = null;
  20465. this.map = null;
  20466. this.bumpMap = null;
  20467. this.bumpScale = 1;
  20468. this.normalMap = null;
  20469. this.normalMapType = TangentSpaceNormalMap;
  20470. this.normalScale = new Vector2( 1, 1 );
  20471. this.displacementMap = null;
  20472. this.displacementScale = 1;
  20473. this.displacementBias = 0;
  20474. this.alphaMap = null;
  20475. this.skinning = false;
  20476. this.morphTargets = false;
  20477. this.morphNormals = false;
  20478. this.setValues( parameters );
  20479. }
  20480. MeshMatcapMaterial.prototype = Object.create( Material.prototype );
  20481. MeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;
  20482. MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
  20483. MeshMatcapMaterial.prototype.copy = function ( source ) {
  20484. Material.prototype.copy.call( this, source );
  20485. this.defines = { 'MATCAP': '' };
  20486. this.color.copy( source.color );
  20487. this.matcap = source.matcap;
  20488. this.map = source.map;
  20489. this.bumpMap = source.bumpMap;
  20490. this.bumpScale = source.bumpScale;
  20491. this.normalMap = source.normalMap;
  20492. this.normalMapType = source.normalMapType;
  20493. this.normalScale.copy( source.normalScale );
  20494. this.displacementMap = source.displacementMap;
  20495. this.displacementScale = source.displacementScale;
  20496. this.displacementBias = source.displacementBias;
  20497. this.alphaMap = source.alphaMap;
  20498. this.skinning = source.skinning;
  20499. this.morphTargets = source.morphTargets;
  20500. this.morphNormals = source.morphNormals;
  20501. return this;
  20502. };
  20503. /**
  20504. * parameters = {
  20505. * color: <hex>,
  20506. * opacity: <float>,
  20507. *
  20508. * linewidth: <float>,
  20509. *
  20510. * scale: <float>,
  20511. * dashSize: <float>,
  20512. * gapSize: <float>
  20513. * }
  20514. */
  20515. function LineDashedMaterial( parameters ) {
  20516. LineBasicMaterial.call( this );
  20517. this.type = 'LineDashedMaterial';
  20518. this.scale = 1;
  20519. this.dashSize = 3;
  20520. this.gapSize = 1;
  20521. this.setValues( parameters );
  20522. }
  20523. LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
  20524. LineDashedMaterial.prototype.constructor = LineDashedMaterial;
  20525. LineDashedMaterial.prototype.isLineDashedMaterial = true;
  20526. LineDashedMaterial.prototype.copy = function ( source ) {
  20527. LineBasicMaterial.prototype.copy.call( this, source );
  20528. this.scale = source.scale;
  20529. this.dashSize = source.dashSize;
  20530. this.gapSize = source.gapSize;
  20531. return this;
  20532. };
  20533. var Materials = /*#__PURE__*/Object.freeze({
  20534. __proto__: null,
  20535. ShadowMaterial: ShadowMaterial,
  20536. SpriteMaterial: SpriteMaterial,
  20537. RawShaderMaterial: RawShaderMaterial,
  20538. ShaderMaterial: ShaderMaterial,
  20539. PointsMaterial: PointsMaterial,
  20540. MeshPhysicalMaterial: MeshPhysicalMaterial,
  20541. MeshStandardMaterial: MeshStandardMaterial,
  20542. MeshPhongMaterial: MeshPhongMaterial,
  20543. MeshToonMaterial: MeshToonMaterial,
  20544. MeshNormalMaterial: MeshNormalMaterial,
  20545. MeshLambertMaterial: MeshLambertMaterial,
  20546. MeshDepthMaterial: MeshDepthMaterial,
  20547. MeshDistanceMaterial: MeshDistanceMaterial,
  20548. MeshBasicMaterial: MeshBasicMaterial,
  20549. MeshMatcapMaterial: MeshMatcapMaterial,
  20550. LineDashedMaterial: LineDashedMaterial,
  20551. LineBasicMaterial: LineBasicMaterial,
  20552. Material: Material
  20553. });
  20554. const AnimationUtils = {
  20555. // same as Array.prototype.slice, but also works on typed arrays
  20556. arraySlice: function ( array, from, to ) {
  20557. if ( AnimationUtils.isTypedArray( array ) ) {
  20558. // in ios9 array.subarray(from, undefined) will return empty array
  20559. // but array.subarray(from) or array.subarray(from, len) is correct
  20560. return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
  20561. }
  20562. return array.slice( from, to );
  20563. },
  20564. // converts an array to a specific type
  20565. convertArray: function ( array, type, forceClone ) {
  20566. if ( ! array || // let 'undefined' and 'null' pass
  20567. ! forceClone && array.constructor === type ) return array;
  20568. if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
  20569. return new type( array ); // create typed array
  20570. }
  20571. return Array.prototype.slice.call( array ); // create Array
  20572. },
  20573. isTypedArray: function ( object ) {
  20574. return ArrayBuffer.isView( object ) &&
  20575. ! ( object instanceof DataView );
  20576. },
  20577. // returns an array by which times and values can be sorted
  20578. getKeyframeOrder: function ( times ) {
  20579. function compareTime( i, j ) {
  20580. return times[ i ] - times[ j ];
  20581. }
  20582. const n = times.length;
  20583. const result = new Array( n );
  20584. for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
  20585. result.sort( compareTime );
  20586. return result;
  20587. },
  20588. // uses the array previously returned by 'getKeyframeOrder' to sort data
  20589. sortedArray: function ( values, stride, order ) {
  20590. const nValues = values.length;
  20591. const result = new values.constructor( nValues );
  20592. for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
  20593. const srcOffset = order[ i ] * stride;
  20594. for ( let j = 0; j !== stride; ++ j ) {
  20595. result[ dstOffset ++ ] = values[ srcOffset + j ];
  20596. }
  20597. }
  20598. return result;
  20599. },
  20600. // function for parsing AOS keyframe formats
  20601. flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
  20602. let i = 1, key = jsonKeys[ 0 ];
  20603. while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
  20604. key = jsonKeys[ i ++ ];
  20605. }
  20606. if ( key === undefined ) return; // no data
  20607. let value = key[ valuePropertyName ];
  20608. if ( value === undefined ) return; // no data
  20609. if ( Array.isArray( value ) ) {
  20610. do {
  20611. value = key[ valuePropertyName ];
  20612. if ( value !== undefined ) {
  20613. times.push( key.time );
  20614. values.push.apply( values, value ); // push all elements
  20615. }
  20616. key = jsonKeys[ i ++ ];
  20617. } while ( key !== undefined );
  20618. } else if ( value.toArray !== undefined ) {
  20619. // ...assume THREE.Math-ish
  20620. do {
  20621. value = key[ valuePropertyName ];
  20622. if ( value !== undefined ) {
  20623. times.push( key.time );
  20624. value.toArray( values, values.length );
  20625. }
  20626. key = jsonKeys[ i ++ ];
  20627. } while ( key !== undefined );
  20628. } else {
  20629. // otherwise push as-is
  20630. do {
  20631. value = key[ valuePropertyName ];
  20632. if ( value !== undefined ) {
  20633. times.push( key.time );
  20634. values.push( value );
  20635. }
  20636. key = jsonKeys[ i ++ ];
  20637. } while ( key !== undefined );
  20638. }
  20639. },
  20640. subclip: function ( sourceClip, name, startFrame, endFrame, fps = 30 ) {
  20641. const clip = sourceClip.clone();
  20642. clip.name = name;
  20643. const tracks = [];
  20644. for ( let i = 0; i < clip.tracks.length; ++ i ) {
  20645. const track = clip.tracks[ i ];
  20646. const valueSize = track.getValueSize();
  20647. const times = [];
  20648. const values = [];
  20649. for ( let j = 0; j < track.times.length; ++ j ) {
  20650. const frame = track.times[ j ] * fps;
  20651. if ( frame < startFrame || frame >= endFrame ) continue;
  20652. times.push( track.times[ j ] );
  20653. for ( let k = 0; k < valueSize; ++ k ) {
  20654. values.push( track.values[ j * valueSize + k ] );
  20655. }
  20656. }
  20657. if ( times.length === 0 ) continue;
  20658. track.times = AnimationUtils.convertArray( times, track.times.constructor );
  20659. track.values = AnimationUtils.convertArray( values, track.values.constructor );
  20660. tracks.push( track );
  20661. }
  20662. clip.tracks = tracks;
  20663. // find minimum .times value across all tracks in the trimmed clip
  20664. let minStartTime = Infinity;
  20665. for ( let i = 0; i < clip.tracks.length; ++ i ) {
  20666. if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
  20667. minStartTime = clip.tracks[ i ].times[ 0 ];
  20668. }
  20669. }
  20670. // shift all tracks such that clip begins at t=0
  20671. for ( let i = 0; i < clip.tracks.length; ++ i ) {
  20672. clip.tracks[ i ].shift( - 1 * minStartTime );
  20673. }
  20674. clip.resetDuration();
  20675. return clip;
  20676. },
  20677. makeClipAdditive: function ( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
  20678. if ( fps <= 0 ) fps = 30;
  20679. const numTracks = referenceClip.tracks.length;
  20680. const referenceTime = referenceFrame / fps;
  20681. // Make each track's values relative to the values at the reference frame
  20682. for ( let i = 0; i < numTracks; ++ i ) {
  20683. const referenceTrack = referenceClip.tracks[ i ];
  20684. const referenceTrackType = referenceTrack.ValueTypeName;
  20685. // Skip this track if it's non-numeric
  20686. if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
  20687. // Find the track in the target clip whose name and type matches the reference track
  20688. const targetTrack = targetClip.tracks.find( function ( track ) {
  20689. return track.name === referenceTrack.name
  20690. && track.ValueTypeName === referenceTrackType;
  20691. } );
  20692. if ( targetTrack === undefined ) continue;
  20693. let referenceOffset = 0;
  20694. const referenceValueSize = referenceTrack.getValueSize();
  20695. if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
  20696. referenceOffset = referenceValueSize / 3;
  20697. }
  20698. let targetOffset = 0;
  20699. const targetValueSize = targetTrack.getValueSize();
  20700. if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
  20701. targetOffset = targetValueSize / 3;
  20702. }
  20703. const lastIndex = referenceTrack.times.length - 1;
  20704. let referenceValue;
  20705. // Find the value to subtract out of the track
  20706. if ( referenceTime <= referenceTrack.times[ 0 ] ) {
  20707. // Reference frame is earlier than the first keyframe, so just use the first keyframe
  20708. const startIndex = referenceOffset;
  20709. const endIndex = referenceValueSize - referenceOffset;
  20710. referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
  20711. } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
  20712. // Reference frame is after the last keyframe, so just use the last keyframe
  20713. const startIndex = lastIndex * referenceValueSize + referenceOffset;
  20714. const endIndex = startIndex + referenceValueSize - referenceOffset;
  20715. referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
  20716. } else {
  20717. // Interpolate to the reference value
  20718. const interpolant = referenceTrack.createInterpolant();
  20719. const startIndex = referenceOffset;
  20720. const endIndex = referenceValueSize - referenceOffset;
  20721. interpolant.evaluate( referenceTime );
  20722. referenceValue = AnimationUtils.arraySlice( interpolant.resultBuffer, startIndex, endIndex );
  20723. }
  20724. // Conjugate the quaternion
  20725. if ( referenceTrackType === 'quaternion' ) {
  20726. const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
  20727. referenceQuat.toArray( referenceValue );
  20728. }
  20729. // Subtract the reference value from all of the track values
  20730. const numTimes = targetTrack.times.length;
  20731. for ( let j = 0; j < numTimes; ++ j ) {
  20732. const valueStart = j * targetValueSize + targetOffset;
  20733. if ( referenceTrackType === 'quaternion' ) {
  20734. // Multiply the conjugate for quaternion track types
  20735. Quaternion.multiplyQuaternionsFlat(
  20736. targetTrack.values,
  20737. valueStart,
  20738. referenceValue,
  20739. 0,
  20740. targetTrack.values,
  20741. valueStart
  20742. );
  20743. } else {
  20744. const valueEnd = targetValueSize - targetOffset * 2;
  20745. // Subtract each value for all other numeric track types
  20746. for ( let k = 0; k < valueEnd; ++ k ) {
  20747. targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
  20748. }
  20749. }
  20750. }
  20751. }
  20752. targetClip.blendMode = AdditiveAnimationBlendMode;
  20753. return targetClip;
  20754. }
  20755. };
  20756. /**
  20757. * Abstract base class of interpolants over parametric samples.
  20758. *
  20759. * The parameter domain is one dimensional, typically the time or a path
  20760. * along a curve defined by the data.
  20761. *
  20762. * The sample values can have any dimensionality and derived classes may
  20763. * apply special interpretations to the data.
  20764. *
  20765. * This class provides the interval seek in a Template Method, deferring
  20766. * the actual interpolation to derived classes.
  20767. *
  20768. * Time complexity is O(1) for linear access crossing at most two points
  20769. * and O(log N) for random access, where N is the number of positions.
  20770. *
  20771. * References:
  20772. *
  20773. * http://www.oodesign.com/template-method-pattern.html
  20774. *
  20775. */
  20776. function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
  20777. this.parameterPositions = parameterPositions;
  20778. this._cachedIndex = 0;
  20779. this.resultBuffer = resultBuffer !== undefined ?
  20780. resultBuffer : new sampleValues.constructor( sampleSize );
  20781. this.sampleValues = sampleValues;
  20782. this.valueSize = sampleSize;
  20783. }
  20784. Object.assign( Interpolant.prototype, {
  20785. evaluate: function ( t ) {
  20786. const pp = this.parameterPositions;
  20787. let i1 = this._cachedIndex,
  20788. t1 = pp[ i1 ],
  20789. t0 = pp[ i1 - 1 ];
  20790. validate_interval: {
  20791. seek: {
  20792. let right;
  20793. linear_scan: {
  20794. //- See http://jsperf.com/comparison-to-undefined/3
  20795. //- slower code:
  20796. //-
  20797. //- if ( t >= t1 || t1 === undefined ) {
  20798. forward_scan: if ( ! ( t < t1 ) ) {
  20799. for ( let giveUpAt = i1 + 2; ; ) {
  20800. if ( t1 === undefined ) {
  20801. if ( t < t0 ) break forward_scan;
  20802. // after end
  20803. i1 = pp.length;
  20804. this._cachedIndex = i1;
  20805. return this.afterEnd_( i1 - 1, t, t0 );
  20806. }
  20807. if ( i1 === giveUpAt ) break; // this loop
  20808. t0 = t1;
  20809. t1 = pp[ ++ i1 ];
  20810. if ( t < t1 ) {
  20811. // we have arrived at the sought interval
  20812. break seek;
  20813. }
  20814. }
  20815. // prepare binary search on the right side of the index
  20816. right = pp.length;
  20817. break linear_scan;
  20818. }
  20819. //- slower code:
  20820. //- if ( t < t0 || t0 === undefined ) {
  20821. if ( ! ( t >= t0 ) ) {
  20822. // looping?
  20823. const t1global = pp[ 1 ];
  20824. if ( t < t1global ) {
  20825. i1 = 2; // + 1, using the scan for the details
  20826. t0 = t1global;
  20827. }
  20828. // linear reverse scan
  20829. for ( let giveUpAt = i1 - 2; ; ) {
  20830. if ( t0 === undefined ) {
  20831. // before start
  20832. this._cachedIndex = 0;
  20833. return this.beforeStart_( 0, t, t1 );
  20834. }
  20835. if ( i1 === giveUpAt ) break; // this loop
  20836. t1 = t0;
  20837. t0 = pp[ -- i1 - 1 ];
  20838. if ( t >= t0 ) {
  20839. // we have arrived at the sought interval
  20840. break seek;
  20841. }
  20842. }
  20843. // prepare binary search on the left side of the index
  20844. right = i1;
  20845. i1 = 0;
  20846. break linear_scan;
  20847. }
  20848. // the interval is valid
  20849. break validate_interval;
  20850. } // linear scan
  20851. // binary search
  20852. while ( i1 < right ) {
  20853. const mid = ( i1 + right ) >>> 1;
  20854. if ( t < pp[ mid ] ) {
  20855. right = mid;
  20856. } else {
  20857. i1 = mid + 1;
  20858. }
  20859. }
  20860. t1 = pp[ i1 ];
  20861. t0 = pp[ i1 - 1 ];
  20862. // check boundary cases, again
  20863. if ( t0 === undefined ) {
  20864. this._cachedIndex = 0;
  20865. return this.beforeStart_( 0, t, t1 );
  20866. }
  20867. if ( t1 === undefined ) {
  20868. i1 = pp.length;
  20869. this._cachedIndex = i1;
  20870. return this.afterEnd_( i1 - 1, t0, t );
  20871. }
  20872. } // seek
  20873. this._cachedIndex = i1;
  20874. this.intervalChanged_( i1, t0, t1 );
  20875. } // validate_interval
  20876. return this.interpolate_( i1, t0, t, t1 );
  20877. },
  20878. settings: null, // optional, subclass-specific settings structure
  20879. // Note: The indirection allows central control of many interpolants.
  20880. // --- Protected interface
  20881. DefaultSettings_: {},
  20882. getSettings_: function () {
  20883. return this.settings || this.DefaultSettings_;
  20884. },
  20885. copySampleValue_: function ( index ) {
  20886. // copies a sample value to the result buffer
  20887. const result = this.resultBuffer,
  20888. values = this.sampleValues,
  20889. stride = this.valueSize,
  20890. offset = index * stride;
  20891. for ( let i = 0; i !== stride; ++ i ) {
  20892. result[ i ] = values[ offset + i ];
  20893. }
  20894. return result;
  20895. },
  20896. // Template methods for derived classes:
  20897. interpolate_: function ( /* i1, t0, t, t1 */ ) {
  20898. throw new Error( 'call to abstract method' );
  20899. // implementations shall return this.resultBuffer
  20900. },
  20901. intervalChanged_: function ( /* i1, t0, t1 */ ) {
  20902. // empty
  20903. }
  20904. } );
  20905. // DECLARE ALIAS AFTER assign prototype
  20906. Object.assign( Interpolant.prototype, {
  20907. //( 0, t, t0 ), returns this.resultBuffer
  20908. beforeStart_: Interpolant.prototype.copySampleValue_,
  20909. //( N-1, tN-1, t ), returns this.resultBuffer
  20910. afterEnd_: Interpolant.prototype.copySampleValue_,
  20911. } );
  20912. /**
  20913. * Fast and simple cubic spline interpolant.
  20914. *
  20915. * It was derived from a Hermitian construction setting the first derivative
  20916. * at each sample position to the linear slope between neighboring positions
  20917. * over their parameter interval.
  20918. */
  20919. function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
  20920. Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
  20921. this._weightPrev = - 0;
  20922. this._offsetPrev = - 0;
  20923. this._weightNext = - 0;
  20924. this._offsetNext = - 0;
  20925. }
  20926. CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
  20927. constructor: CubicInterpolant,
  20928. DefaultSettings_: {
  20929. endingStart: ZeroCurvatureEnding,
  20930. endingEnd: ZeroCurvatureEnding
  20931. },
  20932. intervalChanged_: function ( i1, t0, t1 ) {
  20933. const pp = this.parameterPositions;
  20934. let iPrev = i1 - 2,
  20935. iNext = i1 + 1,
  20936. tPrev = pp[ iPrev ],
  20937. tNext = pp[ iNext ];
  20938. if ( tPrev === undefined ) {
  20939. switch ( this.getSettings_().endingStart ) {
  20940. case ZeroSlopeEnding:
  20941. // f'(t0) = 0
  20942. iPrev = i1;
  20943. tPrev = 2 * t0 - t1;
  20944. break;
  20945. case WrapAroundEnding:
  20946. // use the other end of the curve
  20947. iPrev = pp.length - 2;
  20948. tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
  20949. break;
  20950. default: // ZeroCurvatureEnding
  20951. // f''(t0) = 0 a.k.a. Natural Spline
  20952. iPrev = i1;
  20953. tPrev = t1;
  20954. }
  20955. }
  20956. if ( tNext === undefined ) {
  20957. switch ( this.getSettings_().endingEnd ) {
  20958. case ZeroSlopeEnding:
  20959. // f'(tN) = 0
  20960. iNext = i1;
  20961. tNext = 2 * t1 - t0;
  20962. break;
  20963. case WrapAroundEnding:
  20964. // use the other end of the curve
  20965. iNext = 1;
  20966. tNext = t1 + pp[ 1 ] - pp[ 0 ];
  20967. break;
  20968. default: // ZeroCurvatureEnding
  20969. // f''(tN) = 0, a.k.a. Natural Spline
  20970. iNext = i1 - 1;
  20971. tNext = t0;
  20972. }
  20973. }
  20974. const halfDt = ( t1 - t0 ) * 0.5,
  20975. stride = this.valueSize;
  20976. this._weightPrev = halfDt / ( t0 - tPrev );
  20977. this._weightNext = halfDt / ( tNext - t1 );
  20978. this._offsetPrev = iPrev * stride;
  20979. this._offsetNext = iNext * stride;
  20980. },
  20981. interpolate_: function ( i1, t0, t, t1 ) {
  20982. const result = this.resultBuffer,
  20983. values = this.sampleValues,
  20984. stride = this.valueSize,
  20985. o1 = i1 * stride, o0 = o1 - stride,
  20986. oP = this._offsetPrev, oN = this._offsetNext,
  20987. wP = this._weightPrev, wN = this._weightNext,
  20988. p = ( t - t0 ) / ( t1 - t0 ),
  20989. pp = p * p,
  20990. ppp = pp * p;
  20991. // evaluate polynomials
  20992. const sP = - wP * ppp + 2 * wP * pp - wP * p;
  20993. const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
  20994. const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
  20995. const sN = wN * ppp - wN * pp;
  20996. // combine data linearly
  20997. for ( let i = 0; i !== stride; ++ i ) {
  20998. result[ i ] =
  20999. sP * values[ oP + i ] +
  21000. s0 * values[ o0 + i ] +
  21001. s1 * values[ o1 + i ] +
  21002. sN * values[ oN + i ];
  21003. }
  21004. return result;
  21005. }
  21006. } );
  21007. function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
  21008. Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
  21009. }
  21010. LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
  21011. constructor: LinearInterpolant,
  21012. interpolate_: function ( i1, t0, t, t1 ) {
  21013. const result = this.resultBuffer,
  21014. values = this.sampleValues,
  21015. stride = this.valueSize,
  21016. offset1 = i1 * stride,
  21017. offset0 = offset1 - stride,
  21018. weight1 = ( t - t0 ) / ( t1 - t0 ),
  21019. weight0 = 1 - weight1;
  21020. for ( let i = 0; i !== stride; ++ i ) {
  21021. result[ i ] =
  21022. values[ offset0 + i ] * weight0 +
  21023. values[ offset1 + i ] * weight1;
  21024. }
  21025. return result;
  21026. }
  21027. } );
  21028. /**
  21029. *
  21030. * Interpolant that evaluates to the sample value at the position preceeding
  21031. * the parameter.
  21032. */
  21033. function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
  21034. Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
  21035. }
  21036. DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
  21037. constructor: DiscreteInterpolant,
  21038. interpolate_: function ( i1 /*, t0, t, t1 */ ) {
  21039. return this.copySampleValue_( i1 - 1 );
  21040. }
  21041. } );
  21042. function KeyframeTrack( name, times, values, interpolation ) {
  21043. if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
  21044. if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
  21045. this.name = name;
  21046. this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
  21047. this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
  21048. this.setInterpolation( interpolation || this.DefaultInterpolation );
  21049. }
  21050. // Static methods
  21051. Object.assign( KeyframeTrack, {
  21052. // Serialization (in static context, because of constructor invocation
  21053. // and automatic invocation of .toJSON):
  21054. toJSON: function ( track ) {
  21055. const trackType = track.constructor;
  21056. let json;
  21057. // derived classes can define a static toJSON method
  21058. if ( trackType.toJSON !== undefined ) {
  21059. json = trackType.toJSON( track );
  21060. } else {
  21061. // by default, we assume the data can be serialized as-is
  21062. json = {
  21063. 'name': track.name,
  21064. 'times': AnimationUtils.convertArray( track.times, Array ),
  21065. 'values': AnimationUtils.convertArray( track.values, Array )
  21066. };
  21067. const interpolation = track.getInterpolation();
  21068. if ( interpolation !== track.DefaultInterpolation ) {
  21069. json.interpolation = interpolation;
  21070. }
  21071. }
  21072. json.type = track.ValueTypeName; // mandatory
  21073. return json;
  21074. }
  21075. } );
  21076. Object.assign( KeyframeTrack.prototype, {
  21077. constructor: KeyframeTrack,
  21078. TimeBufferType: Float32Array,
  21079. ValueBufferType: Float32Array,
  21080. DefaultInterpolation: InterpolateLinear,
  21081. InterpolantFactoryMethodDiscrete: function ( result ) {
  21082. return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
  21083. },
  21084. InterpolantFactoryMethodLinear: function ( result ) {
  21085. return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
  21086. },
  21087. InterpolantFactoryMethodSmooth: function ( result ) {
  21088. return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
  21089. },
  21090. setInterpolation: function ( interpolation ) {
  21091. let factoryMethod;
  21092. switch ( interpolation ) {
  21093. case InterpolateDiscrete:
  21094. factoryMethod = this.InterpolantFactoryMethodDiscrete;
  21095. break;
  21096. case InterpolateLinear:
  21097. factoryMethod = this.InterpolantFactoryMethodLinear;
  21098. break;
  21099. case InterpolateSmooth:
  21100. factoryMethod = this.InterpolantFactoryMethodSmooth;
  21101. break;
  21102. }
  21103. if ( factoryMethod === undefined ) {
  21104. const message = 'unsupported interpolation for ' +
  21105. this.ValueTypeName + ' keyframe track named ' + this.name;
  21106. if ( this.createInterpolant === undefined ) {
  21107. // fall back to default, unless the default itself is messed up
  21108. if ( interpolation !== this.DefaultInterpolation ) {
  21109. this.setInterpolation( this.DefaultInterpolation );
  21110. } else {
  21111. throw new Error( message ); // fatal, in this case
  21112. }
  21113. }
  21114. console.warn( 'THREE.KeyframeTrack:', message );
  21115. return this;
  21116. }
  21117. this.createInterpolant = factoryMethod;
  21118. return this;
  21119. },
  21120. getInterpolation: function () {
  21121. switch ( this.createInterpolant ) {
  21122. case this.InterpolantFactoryMethodDiscrete:
  21123. return InterpolateDiscrete;
  21124. case this.InterpolantFactoryMethodLinear:
  21125. return InterpolateLinear;
  21126. case this.InterpolantFactoryMethodSmooth:
  21127. return InterpolateSmooth;
  21128. }
  21129. },
  21130. getValueSize: function () {
  21131. return this.values.length / this.times.length;
  21132. },
  21133. // move all keyframes either forwards or backwards in time
  21134. shift: function ( timeOffset ) {
  21135. if ( timeOffset !== 0.0 ) {
  21136. const times = this.times;
  21137. for ( let i = 0, n = times.length; i !== n; ++ i ) {
  21138. times[ i ] += timeOffset;
  21139. }
  21140. }
  21141. return this;
  21142. },
  21143. // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
  21144. scale: function ( timeScale ) {
  21145. if ( timeScale !== 1.0 ) {
  21146. const times = this.times;
  21147. for ( let i = 0, n = times.length; i !== n; ++ i ) {
  21148. times[ i ] *= timeScale;
  21149. }
  21150. }
  21151. return this;
  21152. },
  21153. // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
  21154. // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
  21155. trim: function ( startTime, endTime ) {
  21156. const times = this.times,
  21157. nKeys = times.length;
  21158. let from = 0,
  21159. to = nKeys - 1;
  21160. while ( from !== nKeys && times[ from ] < startTime ) {
  21161. ++ from;
  21162. }
  21163. while ( to !== - 1 && times[ to ] > endTime ) {
  21164. -- to;
  21165. }
  21166. ++ to; // inclusive -> exclusive bound
  21167. if ( from !== 0 || to !== nKeys ) {
  21168. // empty tracks are forbidden, so keep at least one keyframe
  21169. if ( from >= to ) {
  21170. to = Math.max( to, 1 );
  21171. from = to - 1;
  21172. }
  21173. const stride = this.getValueSize();
  21174. this.times = AnimationUtils.arraySlice( times, from, to );
  21175. this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
  21176. }
  21177. return this;
  21178. },
  21179. // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
  21180. validate: function () {
  21181. let valid = true;
  21182. const valueSize = this.getValueSize();
  21183. if ( valueSize - Math.floor( valueSize ) !== 0 ) {
  21184. console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
  21185. valid = false;
  21186. }
  21187. const times = this.times,
  21188. values = this.values,
  21189. nKeys = times.length;
  21190. if ( nKeys === 0 ) {
  21191. console.error( 'THREE.KeyframeTrack: Track is empty.', this );
  21192. valid = false;
  21193. }
  21194. let prevTime = null;
  21195. for ( let i = 0; i !== nKeys; i ++ ) {
  21196. const currTime = times[ i ];
  21197. if ( typeof currTime === 'number' && isNaN( currTime ) ) {
  21198. console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
  21199. valid = false;
  21200. break;
  21201. }
  21202. if ( prevTime !== null && prevTime > currTime ) {
  21203. console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
  21204. valid = false;
  21205. break;
  21206. }
  21207. prevTime = currTime;
  21208. }
  21209. if ( values !== undefined ) {
  21210. if ( AnimationUtils.isTypedArray( values ) ) {
  21211. for ( let i = 0, n = values.length; i !== n; ++ i ) {
  21212. const value = values[ i ];
  21213. if ( isNaN( value ) ) {
  21214. console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
  21215. valid = false;
  21216. break;
  21217. }
  21218. }
  21219. }
  21220. }
  21221. return valid;
  21222. },
  21223. // removes equivalent sequential keys as common in morph target sequences
  21224. // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
  21225. optimize: function () {
  21226. // times or values may be shared with other tracks, so overwriting is unsafe
  21227. const times = AnimationUtils.arraySlice( this.times ),
  21228. values = AnimationUtils.arraySlice( this.values ),
  21229. stride = this.getValueSize(),
  21230. smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
  21231. lastIndex = times.length - 1;
  21232. let writeIndex = 1;
  21233. for ( let i = 1; i < lastIndex; ++ i ) {
  21234. let keep = false;
  21235. const time = times[ i ];
  21236. const timeNext = times[ i + 1 ];
  21237. // remove adjacent keyframes scheduled at the same time
  21238. if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
  21239. if ( ! smoothInterpolation ) {
  21240. // remove unnecessary keyframes same as their neighbors
  21241. const offset = i * stride,
  21242. offsetP = offset - stride,
  21243. offsetN = offset + stride;
  21244. for ( let j = 0; j !== stride; ++ j ) {
  21245. const value = values[ offset + j ];
  21246. if ( value !== values[ offsetP + j ] ||
  21247. value !== values[ offsetN + j ] ) {
  21248. keep = true;
  21249. break;
  21250. }
  21251. }
  21252. } else {
  21253. keep = true;
  21254. }
  21255. }
  21256. // in-place compaction
  21257. if ( keep ) {
  21258. if ( i !== writeIndex ) {
  21259. times[ writeIndex ] = times[ i ];
  21260. const readOffset = i * stride,
  21261. writeOffset = writeIndex * stride;
  21262. for ( let j = 0; j !== stride; ++ j ) {
  21263. values[ writeOffset + j ] = values[ readOffset + j ];
  21264. }
  21265. }
  21266. ++ writeIndex;
  21267. }
  21268. }
  21269. // flush last keyframe (compaction looks ahead)
  21270. if ( lastIndex > 0 ) {
  21271. times[ writeIndex ] = times[ lastIndex ];
  21272. for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
  21273. values[ writeOffset + j ] = values[ readOffset + j ];
  21274. }
  21275. ++ writeIndex;
  21276. }
  21277. if ( writeIndex !== times.length ) {
  21278. this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
  21279. this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
  21280. } else {
  21281. this.times = times;
  21282. this.values = values;
  21283. }
  21284. return this;
  21285. },
  21286. clone: function () {
  21287. const times = AnimationUtils.arraySlice( this.times, 0 );
  21288. const values = AnimationUtils.arraySlice( this.values, 0 );
  21289. const TypedKeyframeTrack = this.constructor;
  21290. const track = new TypedKeyframeTrack( this.name, times, values );
  21291. // Interpolant argument to constructor is not saved, so copy the factory method directly.
  21292. track.createInterpolant = this.createInterpolant;
  21293. return track;
  21294. }
  21295. } );
  21296. /**
  21297. * A Track of Boolean keyframe values.
  21298. */
  21299. function BooleanKeyframeTrack( name, times, values ) {
  21300. KeyframeTrack.call( this, name, times, values );
  21301. }
  21302. BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
  21303. constructor: BooleanKeyframeTrack,
  21304. ValueTypeName: 'bool',
  21305. ValueBufferType: Array,
  21306. DefaultInterpolation: InterpolateDiscrete,
  21307. InterpolantFactoryMethodLinear: undefined,
  21308. InterpolantFactoryMethodSmooth: undefined
  21309. // Note: Actually this track could have a optimized / compressed
  21310. // representation of a single value and a custom interpolant that
  21311. // computes "firstValue ^ isOdd( index )".
  21312. } );
  21313. /**
  21314. * A Track of keyframe values that represent color.
  21315. */
  21316. function ColorKeyframeTrack( name, times, values, interpolation ) {
  21317. KeyframeTrack.call( this, name, times, values, interpolation );
  21318. }
  21319. ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
  21320. constructor: ColorKeyframeTrack,
  21321. ValueTypeName: 'color'
  21322. // ValueBufferType is inherited
  21323. // DefaultInterpolation is inherited
  21324. // Note: Very basic implementation and nothing special yet.
  21325. // However, this is the place for color space parameterization.
  21326. } );
  21327. /**
  21328. * A Track of numeric keyframe values.
  21329. */
  21330. function NumberKeyframeTrack( name, times, values, interpolation ) {
  21331. KeyframeTrack.call( this, name, times, values, interpolation );
  21332. }
  21333. NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
  21334. constructor: NumberKeyframeTrack,
  21335. ValueTypeName: 'number'
  21336. // ValueBufferType is inherited
  21337. // DefaultInterpolation is inherited
  21338. } );
  21339. /**
  21340. * Spherical linear unit quaternion interpolant.
  21341. */
  21342. function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
  21343. Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
  21344. }
  21345. QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
  21346. constructor: QuaternionLinearInterpolant,
  21347. interpolate_: function ( i1, t0, t, t1 ) {
  21348. const result = this.resultBuffer,
  21349. values = this.sampleValues,
  21350. stride = this.valueSize,
  21351. alpha = ( t - t0 ) / ( t1 - t0 );
  21352. let offset = i1 * stride;
  21353. for ( let end = offset + stride; offset !== end; offset += 4 ) {
  21354. Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
  21355. }
  21356. return result;
  21357. }
  21358. } );
  21359. /**
  21360. * A Track of quaternion keyframe values.
  21361. */
  21362. function QuaternionKeyframeTrack( name, times, values, interpolation ) {
  21363. KeyframeTrack.call( this, name, times, values, interpolation );
  21364. }
  21365. QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
  21366. constructor: QuaternionKeyframeTrack,
  21367. ValueTypeName: 'quaternion',
  21368. // ValueBufferType is inherited
  21369. DefaultInterpolation: InterpolateLinear,
  21370. InterpolantFactoryMethodLinear: function ( result ) {
  21371. return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
  21372. },
  21373. InterpolantFactoryMethodSmooth: undefined // not yet implemented
  21374. } );
  21375. /**
  21376. * A Track that interpolates Strings
  21377. */
  21378. function StringKeyframeTrack( name, times, values, interpolation ) {
  21379. KeyframeTrack.call( this, name, times, values, interpolation );
  21380. }
  21381. StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
  21382. constructor: StringKeyframeTrack,
  21383. ValueTypeName: 'string',
  21384. ValueBufferType: Array,
  21385. DefaultInterpolation: InterpolateDiscrete,
  21386. InterpolantFactoryMethodLinear: undefined,
  21387. InterpolantFactoryMethodSmooth: undefined
  21388. } );
  21389. /**
  21390. * A Track of vectored keyframe values.
  21391. */
  21392. function VectorKeyframeTrack( name, times, values, interpolation ) {
  21393. KeyframeTrack.call( this, name, times, values, interpolation );
  21394. }
  21395. VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
  21396. constructor: VectorKeyframeTrack,
  21397. ValueTypeName: 'vector'
  21398. // ValueBufferType is inherited
  21399. // DefaultInterpolation is inherited
  21400. } );
  21401. function AnimationClip( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) {
  21402. this.name = name;
  21403. this.tracks = tracks;
  21404. this.duration = duration;
  21405. this.blendMode = blendMode;
  21406. this.uuid = MathUtils$1.generateUUID();
  21407. // this means it should figure out its duration by scanning the tracks
  21408. if ( this.duration < 0 ) {
  21409. this.resetDuration();
  21410. }
  21411. }
  21412. function getTrackTypeForValueTypeName( typeName ) {
  21413. switch ( typeName.toLowerCase() ) {
  21414. case 'scalar':
  21415. case 'double':
  21416. case 'float':
  21417. case 'number':
  21418. case 'integer':
  21419. return NumberKeyframeTrack;
  21420. case 'vector':
  21421. case 'vector2':
  21422. case 'vector3':
  21423. case 'vector4':
  21424. return VectorKeyframeTrack;
  21425. case 'color':
  21426. return ColorKeyframeTrack;
  21427. case 'quaternion':
  21428. return QuaternionKeyframeTrack;
  21429. case 'bool':
  21430. case 'boolean':
  21431. return BooleanKeyframeTrack;
  21432. case 'string':
  21433. return StringKeyframeTrack;
  21434. }
  21435. throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
  21436. }
  21437. function parseKeyframeTrack( json ) {
  21438. if ( json.type === undefined ) {
  21439. throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
  21440. }
  21441. const trackType = getTrackTypeForValueTypeName( json.type );
  21442. if ( json.times === undefined ) {
  21443. const times = [], values = [];
  21444. AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
  21445. json.times = times;
  21446. json.values = values;
  21447. }
  21448. // derived classes can define a static parse method
  21449. if ( trackType.parse !== undefined ) {
  21450. return trackType.parse( json );
  21451. } else {
  21452. // by default, we assume a constructor compatible with the base
  21453. return new trackType( json.name, json.times, json.values, json.interpolation );
  21454. }
  21455. }
  21456. Object.assign( AnimationClip, {
  21457. parse: function ( json ) {
  21458. const tracks = [],
  21459. jsonTracks = json.tracks,
  21460. frameTime = 1.0 / ( json.fps || 1.0 );
  21461. for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
  21462. tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
  21463. }
  21464. const clip = new AnimationClip( json.name, json.duration, tracks, json.blendMode );
  21465. clip.uuid = json.uuid;
  21466. return clip;
  21467. },
  21468. toJSON: function ( clip ) {
  21469. const tracks = [],
  21470. clipTracks = clip.tracks;
  21471. const json = {
  21472. 'name': clip.name,
  21473. 'duration': clip.duration,
  21474. 'tracks': tracks,
  21475. 'uuid': clip.uuid,
  21476. 'blendMode': clip.blendMode
  21477. };
  21478. for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
  21479. tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
  21480. }
  21481. return json;
  21482. },
  21483. CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
  21484. const numMorphTargets = morphTargetSequence.length;
  21485. const tracks = [];
  21486. for ( let i = 0; i < numMorphTargets; i ++ ) {
  21487. let times = [];
  21488. let values = [];
  21489. times.push(
  21490. ( i + numMorphTargets - 1 ) % numMorphTargets,
  21491. i,
  21492. ( i + 1 ) % numMorphTargets );
  21493. values.push( 0, 1, 0 );
  21494. const order = AnimationUtils.getKeyframeOrder( times );
  21495. times = AnimationUtils.sortedArray( times, 1, order );
  21496. values = AnimationUtils.sortedArray( values, 1, order );
  21497. // if there is a key at the first frame, duplicate it as the
  21498. // last frame as well for perfect loop.
  21499. if ( ! noLoop && times[ 0 ] === 0 ) {
  21500. times.push( numMorphTargets );
  21501. values.push( values[ 0 ] );
  21502. }
  21503. tracks.push(
  21504. new NumberKeyframeTrack(
  21505. '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
  21506. times, values
  21507. ).scale( 1.0 / fps ) );
  21508. }
  21509. return new AnimationClip( name, - 1, tracks );
  21510. },
  21511. findByName: function ( objectOrClipArray, name ) {
  21512. let clipArray = objectOrClipArray;
  21513. if ( ! Array.isArray( objectOrClipArray ) ) {
  21514. const o = objectOrClipArray;
  21515. clipArray = o.geometry && o.geometry.animations || o.animations;
  21516. }
  21517. for ( let i = 0; i < clipArray.length; i ++ ) {
  21518. if ( clipArray[ i ].name === name ) {
  21519. return clipArray[ i ];
  21520. }
  21521. }
  21522. return null;
  21523. },
  21524. CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
  21525. const animationToMorphTargets = {};
  21526. // tested with https://regex101.com/ on trick sequences
  21527. // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
  21528. const pattern = /^([\w-]*?)([\d]+)$/;
  21529. // sort morph target names into animation groups based
  21530. // patterns like Walk_001, Walk_002, Run_001, Run_002
  21531. for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
  21532. const morphTarget = morphTargets[ i ];
  21533. const parts = morphTarget.name.match( pattern );
  21534. if ( parts && parts.length > 1 ) {
  21535. const name = parts[ 1 ];
  21536. let animationMorphTargets = animationToMorphTargets[ name ];
  21537. if ( ! animationMorphTargets ) {
  21538. animationToMorphTargets[ name ] = animationMorphTargets = [];
  21539. }
  21540. animationMorphTargets.push( morphTarget );
  21541. }
  21542. }
  21543. const clips = [];
  21544. for ( const name in animationToMorphTargets ) {
  21545. clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
  21546. }
  21547. return clips;
  21548. },
  21549. // parse the animation.hierarchy format
  21550. parseAnimation: function ( animation, bones ) {
  21551. if ( ! animation ) {
  21552. console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
  21553. return null;
  21554. }
  21555. const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
  21556. // only return track if there are actually keys.
  21557. if ( animationKeys.length !== 0 ) {
  21558. const times = [];
  21559. const values = [];
  21560. AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
  21561. // empty keys are filtered out, so check again
  21562. if ( times.length !== 0 ) {
  21563. destTracks.push( new trackType( trackName, times, values ) );
  21564. }
  21565. }
  21566. };
  21567. const tracks = [];
  21568. const clipName = animation.name || 'default';
  21569. const fps = animation.fps || 30;
  21570. const blendMode = animation.blendMode;
  21571. // automatic length determination in AnimationClip.
  21572. let duration = animation.length || - 1;
  21573. const hierarchyTracks = animation.hierarchy || [];
  21574. for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
  21575. const animationKeys = hierarchyTracks[ h ].keys;
  21576. // skip empty tracks
  21577. if ( ! animationKeys || animationKeys.length === 0 ) continue;
  21578. // process morph targets
  21579. if ( animationKeys[ 0 ].morphTargets ) {
  21580. // figure out all morph targets used in this track
  21581. const morphTargetNames = {};
  21582. let k;
  21583. for ( k = 0; k < animationKeys.length; k ++ ) {
  21584. if ( animationKeys[ k ].morphTargets ) {
  21585. for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
  21586. morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
  21587. }
  21588. }
  21589. }
  21590. // create a track for each morph target with all zero
  21591. // morphTargetInfluences except for the keys in which
  21592. // the morphTarget is named.
  21593. for ( const morphTargetName in morphTargetNames ) {
  21594. const times = [];
  21595. const values = [];
  21596. for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
  21597. const animationKey = animationKeys[ k ];
  21598. times.push( animationKey.time );
  21599. values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
  21600. }
  21601. tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
  21602. }
  21603. duration = morphTargetNames.length * ( fps || 1.0 );
  21604. } else {
  21605. // ...assume skeletal animation
  21606. const boneName = '.bones[' + bones[ h ].name + ']';
  21607. addNonemptyTrack(
  21608. VectorKeyframeTrack, boneName + '.position',
  21609. animationKeys, 'pos', tracks );
  21610. addNonemptyTrack(
  21611. QuaternionKeyframeTrack, boneName + '.quaternion',
  21612. animationKeys, 'rot', tracks );
  21613. addNonemptyTrack(
  21614. VectorKeyframeTrack, boneName + '.scale',
  21615. animationKeys, 'scl', tracks );
  21616. }
  21617. }
  21618. if ( tracks.length === 0 ) {
  21619. return null;
  21620. }
  21621. const clip = new AnimationClip( clipName, duration, tracks, blendMode );
  21622. return clip;
  21623. }
  21624. } );
  21625. Object.assign( AnimationClip.prototype, {
  21626. resetDuration: function () {
  21627. const tracks = this.tracks;
  21628. let duration = 0;
  21629. for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
  21630. const track = this.tracks[ i ];
  21631. duration = Math.max( duration, track.times[ track.times.length - 1 ] );
  21632. }
  21633. this.duration = duration;
  21634. return this;
  21635. },
  21636. trim: function () {
  21637. for ( let i = 0; i < this.tracks.length; i ++ ) {
  21638. this.tracks[ i ].trim( 0, this.duration );
  21639. }
  21640. return this;
  21641. },
  21642. validate: function () {
  21643. let valid = true;
  21644. for ( let i = 0; i < this.tracks.length; i ++ ) {
  21645. valid = valid && this.tracks[ i ].validate();
  21646. }
  21647. return valid;
  21648. },
  21649. optimize: function () {
  21650. for ( let i = 0; i < this.tracks.length; i ++ ) {
  21651. this.tracks[ i ].optimize();
  21652. }
  21653. return this;
  21654. },
  21655. clone: function () {
  21656. const tracks = [];
  21657. for ( let i = 0; i < this.tracks.length; i ++ ) {
  21658. tracks.push( this.tracks[ i ].clone() );
  21659. }
  21660. return new AnimationClip( this.name, this.duration, tracks, this.blendMode );
  21661. },
  21662. toJSON: function () {
  21663. return AnimationClip.toJSON( this );
  21664. }
  21665. } );
  21666. const Cache = {
  21667. enabled: false,
  21668. files: {},
  21669. add: function ( key, file ) {
  21670. if ( this.enabled === false ) return;
  21671. // console.log( 'THREE.Cache', 'Adding key:', key );
  21672. this.files[ key ] = file;
  21673. },
  21674. get: function ( key ) {
  21675. if ( this.enabled === false ) return;
  21676. // console.log( 'THREE.Cache', 'Checking key:', key );
  21677. return this.files[ key ];
  21678. },
  21679. remove: function ( key ) {
  21680. delete this.files[ key ];
  21681. },
  21682. clear: function () {
  21683. this.files = {};
  21684. }
  21685. };
  21686. function LoadingManager( onLoad, onProgress, onError ) {
  21687. const scope = this;
  21688. let isLoading = false;
  21689. let itemsLoaded = 0;
  21690. let itemsTotal = 0;
  21691. let urlModifier = undefined;
  21692. const handlers = [];
  21693. // Refer to #5689 for the reason why we don't set .onStart
  21694. // in the constructor
  21695. this.onStart = undefined;
  21696. this.onLoad = onLoad;
  21697. this.onProgress = onProgress;
  21698. this.onError = onError;
  21699. this.itemStart = function ( url ) {
  21700. itemsTotal ++;
  21701. if ( isLoading === false ) {
  21702. if ( scope.onStart !== undefined ) {
  21703. scope.onStart( url, itemsLoaded, itemsTotal );
  21704. }
  21705. }
  21706. isLoading = true;
  21707. };
  21708. this.itemEnd = function ( url ) {
  21709. itemsLoaded ++;
  21710. if ( scope.onProgress !== undefined ) {
  21711. scope.onProgress( url, itemsLoaded, itemsTotal );
  21712. }
  21713. if ( itemsLoaded === itemsTotal ) {
  21714. isLoading = false;
  21715. if ( scope.onLoad !== undefined ) {
  21716. scope.onLoad();
  21717. }
  21718. }
  21719. };
  21720. this.itemError = function ( url ) {
  21721. if ( scope.onError !== undefined ) {
  21722. scope.onError( url );
  21723. }
  21724. };
  21725. this.resolveURL = function ( url ) {
  21726. if ( urlModifier ) {
  21727. return urlModifier( url );
  21728. }
  21729. return url;
  21730. };
  21731. this.setURLModifier = function ( transform ) {
  21732. urlModifier = transform;
  21733. return this;
  21734. };
  21735. this.addHandler = function ( regex, loader ) {
  21736. handlers.push( regex, loader );
  21737. return this;
  21738. };
  21739. this.removeHandler = function ( regex ) {
  21740. const index = handlers.indexOf( regex );
  21741. if ( index !== - 1 ) {
  21742. handlers.splice( index, 2 );
  21743. }
  21744. return this;
  21745. };
  21746. this.getHandler = function ( file ) {
  21747. for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
  21748. const regex = handlers[ i ];
  21749. const loader = handlers[ i + 1 ];
  21750. if ( regex.global ) regex.lastIndex = 0; // see #17920
  21751. if ( regex.test( file ) ) {
  21752. return loader;
  21753. }
  21754. }
  21755. return null;
  21756. };
  21757. }
  21758. const DefaultLoadingManager = new LoadingManager();
  21759. function Loader( manager ) {
  21760. this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
  21761. this.crossOrigin = 'anonymous';
  21762. this.withCredentials = false;
  21763. this.path = '';
  21764. this.resourcePath = '';
  21765. this.requestHeader = {};
  21766. }
  21767. Object.assign( Loader.prototype, {
  21768. load: function ( /* url, onLoad, onProgress, onError */ ) {},
  21769. loadAsync: function ( url, onProgress ) {
  21770. const scope = this;
  21771. return new Promise( function ( resolve, reject ) {
  21772. scope.load( url, resolve, onProgress, reject );
  21773. } );
  21774. },
  21775. parse: function ( /* data */ ) {},
  21776. setCrossOrigin: function ( crossOrigin ) {
  21777. this.crossOrigin = crossOrigin;
  21778. return this;
  21779. },
  21780. setWithCredentials: function ( value ) {
  21781. this.withCredentials = value;
  21782. return this;
  21783. },
  21784. setPath: function ( path ) {
  21785. this.path = path;
  21786. return this;
  21787. },
  21788. setResourcePath: function ( resourcePath ) {
  21789. this.resourcePath = resourcePath;
  21790. return this;
  21791. },
  21792. setRequestHeader: function ( requestHeader ) {
  21793. this.requestHeader = requestHeader;
  21794. return this;
  21795. }
  21796. } );
  21797. const loading = {};
  21798. function FileLoader( manager ) {
  21799. Loader.call( this, manager );
  21800. }
  21801. FileLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  21802. constructor: FileLoader,
  21803. load: function ( url, onLoad, onProgress, onError ) {
  21804. if ( url === undefined ) url = '';
  21805. if ( this.path !== undefined ) url = this.path + url;
  21806. url = this.manager.resolveURL( url );
  21807. const scope = this;
  21808. const cached = Cache.get( url );
  21809. if ( cached !== undefined ) {
  21810. scope.manager.itemStart( url );
  21811. setTimeout( function () {
  21812. if ( onLoad ) onLoad( cached );
  21813. scope.manager.itemEnd( url );
  21814. }, 0 );
  21815. return cached;
  21816. }
  21817. // Check if request is duplicate
  21818. if ( loading[ url ] !== undefined ) {
  21819. loading[ url ].push( {
  21820. onLoad: onLoad,
  21821. onProgress: onProgress,
  21822. onError: onError
  21823. } );
  21824. return;
  21825. }
  21826. // Check for data: URI
  21827. const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
  21828. const dataUriRegexResult = url.match( dataUriRegex );
  21829. let request;
  21830. // Safari can not handle Data URIs through XMLHttpRequest so process manually
  21831. if ( dataUriRegexResult ) {
  21832. const mimeType = dataUriRegexResult[ 1 ];
  21833. const isBase64 = !! dataUriRegexResult[ 2 ];
  21834. let data = dataUriRegexResult[ 3 ];
  21835. data = decodeURIComponent( data );
  21836. if ( isBase64 ) data = atob( data );
  21837. try {
  21838. let response;
  21839. const responseType = ( this.responseType || '' ).toLowerCase();
  21840. switch ( responseType ) {
  21841. case 'arraybuffer':
  21842. case 'blob':
  21843. const view = new Uint8Array( data.length );
  21844. for ( let i = 0; i < data.length; i ++ ) {
  21845. view[ i ] = data.charCodeAt( i );
  21846. }
  21847. if ( responseType === 'blob' ) {
  21848. response = new Blob( [ view.buffer ], { type: mimeType } );
  21849. } else {
  21850. response = view.buffer;
  21851. }
  21852. break;
  21853. case 'document':
  21854. const parser = new DOMParser();
  21855. response = parser.parseFromString( data, mimeType );
  21856. break;
  21857. case 'json':
  21858. response = JSON.parse( data );
  21859. break;
  21860. default: // 'text' or other
  21861. response = data;
  21862. break;
  21863. }
  21864. // Wait for next browser tick like standard XMLHttpRequest event dispatching does
  21865. setTimeout( function () {
  21866. if ( onLoad ) onLoad( response );
  21867. scope.manager.itemEnd( url );
  21868. }, 0 );
  21869. } catch ( error ) {
  21870. // Wait for next browser tick like standard XMLHttpRequest event dispatching does
  21871. setTimeout( function () {
  21872. if ( onError ) onError( error );
  21873. scope.manager.itemError( url );
  21874. scope.manager.itemEnd( url );
  21875. }, 0 );
  21876. }
  21877. } else {
  21878. // Initialise array for duplicate requests
  21879. loading[ url ] = [];
  21880. loading[ url ].push( {
  21881. onLoad: onLoad,
  21882. onProgress: onProgress,
  21883. onError: onError
  21884. } );
  21885. request = new XMLHttpRequest();
  21886. request.open( 'GET', url, true );
  21887. request.addEventListener( 'load', function ( event ) {
  21888. const response = this.response;
  21889. const callbacks = loading[ url ];
  21890. delete loading[ url ];
  21891. if ( this.status === 200 || this.status === 0 ) {
  21892. // Some browsers return HTTP Status 0 when using non-http protocol
  21893. // e.g. 'file://' or 'data://'. Handle as success.
  21894. if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
  21895. // Add to cache only on HTTP success, so that we do not cache
  21896. // error response bodies as proper responses to requests.
  21897. Cache.add( url, response );
  21898. for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
  21899. const callback = callbacks[ i ];
  21900. if ( callback.onLoad ) callback.onLoad( response );
  21901. }
  21902. scope.manager.itemEnd( url );
  21903. } else {
  21904. for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
  21905. const callback = callbacks[ i ];
  21906. if ( callback.onError ) callback.onError( event );
  21907. }
  21908. scope.manager.itemError( url );
  21909. scope.manager.itemEnd( url );
  21910. }
  21911. }, false );
  21912. request.addEventListener( 'progress', function ( event ) {
  21913. const callbacks = loading[ url ];
  21914. for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
  21915. const callback = callbacks[ i ];
  21916. if ( callback.onProgress ) callback.onProgress( event );
  21917. }
  21918. }, false );
  21919. request.addEventListener( 'error', function ( event ) {
  21920. const callbacks = loading[ url ];
  21921. delete loading[ url ];
  21922. for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
  21923. const callback = callbacks[ i ];
  21924. if ( callback.onError ) callback.onError( event );
  21925. }
  21926. scope.manager.itemError( url );
  21927. scope.manager.itemEnd( url );
  21928. }, false );
  21929. request.addEventListener( 'abort', function ( event ) {
  21930. const callbacks = loading[ url ];
  21931. delete loading[ url ];
  21932. for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
  21933. const callback = callbacks[ i ];
  21934. if ( callback.onError ) callback.onError( event );
  21935. }
  21936. scope.manager.itemError( url );
  21937. scope.manager.itemEnd( url );
  21938. }, false );
  21939. if ( this.responseType !== undefined ) request.responseType = this.responseType;
  21940. if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
  21941. if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
  21942. for ( const header in this.requestHeader ) {
  21943. request.setRequestHeader( header, this.requestHeader[ header ] );
  21944. }
  21945. request.send( null );
  21946. }
  21947. scope.manager.itemStart( url );
  21948. return request;
  21949. },
  21950. setResponseType: function ( value ) {
  21951. this.responseType = value;
  21952. return this;
  21953. },
  21954. setMimeType: function ( value ) {
  21955. this.mimeType = value;
  21956. return this;
  21957. }
  21958. } );
  21959. function AnimationLoader( manager ) {
  21960. Loader.call( this, manager );
  21961. }
  21962. AnimationLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  21963. constructor: AnimationLoader,
  21964. load: function ( url, onLoad, onProgress, onError ) {
  21965. const scope = this;
  21966. const loader = new FileLoader( scope.manager );
  21967. loader.setPath( scope.path );
  21968. loader.setRequestHeader( scope.requestHeader );
  21969. loader.setWithCredentials( scope.withCredentials );
  21970. loader.load( url, function ( text ) {
  21971. try {
  21972. onLoad( scope.parse( JSON.parse( text ) ) );
  21973. } catch ( e ) {
  21974. if ( onError ) {
  21975. onError( e );
  21976. } else {
  21977. console.error( e );
  21978. }
  21979. scope.manager.itemError( url );
  21980. }
  21981. }, onProgress, onError );
  21982. },
  21983. parse: function ( json ) {
  21984. const animations = [];
  21985. for ( let i = 0; i < json.length; i ++ ) {
  21986. const clip = AnimationClip.parse( json[ i ] );
  21987. animations.push( clip );
  21988. }
  21989. return animations;
  21990. }
  21991. } );
  21992. /**
  21993. * Abstract Base class to block based textures loader (dds, pvr, ...)
  21994. *
  21995. * Sub classes have to implement the parse() method which will be used in load().
  21996. */
  21997. function CompressedTextureLoader( manager ) {
  21998. Loader.call( this, manager );
  21999. }
  22000. CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  22001. constructor: CompressedTextureLoader,
  22002. load: function ( url, onLoad, onProgress, onError ) {
  22003. const scope = this;
  22004. const images = [];
  22005. const texture = new CompressedTexture();
  22006. const loader = new FileLoader( this.manager );
  22007. loader.setPath( this.path );
  22008. loader.setResponseType( 'arraybuffer' );
  22009. loader.setRequestHeader( this.requestHeader );
  22010. loader.setWithCredentials( scope.withCredentials );
  22011. let loaded = 0;
  22012. function loadTexture( i ) {
  22013. loader.load( url[ i ], function ( buffer ) {
  22014. const texDatas = scope.parse( buffer, true );
  22015. images[ i ] = {
  22016. width: texDatas.width,
  22017. height: texDatas.height,
  22018. format: texDatas.format,
  22019. mipmaps: texDatas.mipmaps
  22020. };
  22021. loaded += 1;
  22022. if ( loaded === 6 ) {
  22023. if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
  22024. texture.image = images;
  22025. texture.format = texDatas.format;
  22026. texture.needsUpdate = true;
  22027. if ( onLoad ) onLoad( texture );
  22028. }
  22029. }, onProgress, onError );
  22030. }
  22031. if ( Array.isArray( url ) ) {
  22032. for ( let i = 0, il = url.length; i < il; ++ i ) {
  22033. loadTexture( i );
  22034. }
  22035. } else {
  22036. // compressed cubemap texture stored in a single DDS file
  22037. loader.load( url, function ( buffer ) {
  22038. const texDatas = scope.parse( buffer, true );
  22039. if ( texDatas.isCubemap ) {
  22040. const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
  22041. for ( let f = 0; f < faces; f ++ ) {
  22042. images[ f ] = { mipmaps: [] };
  22043. for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
  22044. images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
  22045. images[ f ].format = texDatas.format;
  22046. images[ f ].width = texDatas.width;
  22047. images[ f ].height = texDatas.height;
  22048. }
  22049. }
  22050. texture.image = images;
  22051. } else {
  22052. texture.image.width = texDatas.width;
  22053. texture.image.height = texDatas.height;
  22054. texture.mipmaps = texDatas.mipmaps;
  22055. }
  22056. if ( texDatas.mipmapCount === 1 ) {
  22057. texture.minFilter = LinearFilter;
  22058. }
  22059. texture.format = texDatas.format;
  22060. texture.needsUpdate = true;
  22061. if ( onLoad ) onLoad( texture );
  22062. }, onProgress, onError );
  22063. }
  22064. return texture;
  22065. }
  22066. } );
  22067. function ImageLoader( manager ) {
  22068. Loader.call( this, manager );
  22069. }
  22070. ImageLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  22071. constructor: ImageLoader,
  22072. load: function ( url, onLoad, onProgress, onError ) {
  22073. if ( this.path !== undefined ) url = this.path + url;
  22074. url = this.manager.resolveURL( url );
  22075. const scope = this;
  22076. const cached = Cache.get( url );
  22077. if ( cached !== undefined ) {
  22078. scope.manager.itemStart( url );
  22079. setTimeout( function () {
  22080. if ( onLoad ) onLoad( cached );
  22081. scope.manager.itemEnd( url );
  22082. }, 0 );
  22083. return cached;
  22084. }
  22085. const image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
  22086. function onImageLoad() {
  22087. image.removeEventListener( 'load', onImageLoad, false );
  22088. image.removeEventListener( 'error', onImageError, false );
  22089. Cache.add( url, this );
  22090. if ( onLoad ) onLoad( this );
  22091. scope.manager.itemEnd( url );
  22092. }
  22093. function onImageError( event ) {
  22094. image.removeEventListener( 'load', onImageLoad, false );
  22095. image.removeEventListener( 'error', onImageError, false );
  22096. if ( onError ) onError( event );
  22097. scope.manager.itemError( url );
  22098. scope.manager.itemEnd( url );
  22099. }
  22100. image.addEventListener( 'load', onImageLoad, false );
  22101. image.addEventListener( 'error', onImageError, false );
  22102. if ( url.substr( 0, 5 ) !== 'data:' ) {
  22103. if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
  22104. }
  22105. scope.manager.itemStart( url );
  22106. image.src = url;
  22107. return image;
  22108. }
  22109. } );
  22110. function CubeTextureLoader( manager ) {
  22111. Loader.call( this, manager );
  22112. }
  22113. CubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  22114. constructor: CubeTextureLoader,
  22115. load: function ( urls, onLoad, onProgress, onError ) {
  22116. const texture = new CubeTexture();
  22117. const loader = new ImageLoader( this.manager );
  22118. loader.setCrossOrigin( this.crossOrigin );
  22119. loader.setPath( this.path );
  22120. let loaded = 0;
  22121. function loadTexture( i ) {
  22122. loader.load( urls[ i ], function ( image ) {
  22123. texture.images[ i ] = image;
  22124. loaded ++;
  22125. if ( loaded === 6 ) {
  22126. texture.needsUpdate = true;
  22127. if ( onLoad ) onLoad( texture );
  22128. }
  22129. }, undefined, onError );
  22130. }
  22131. for ( let i = 0; i < urls.length; ++ i ) {
  22132. loadTexture( i );
  22133. }
  22134. return texture;
  22135. }
  22136. } );
  22137. /**
  22138. * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
  22139. *
  22140. * Sub classes have to implement the parse() method which will be used in load().
  22141. */
  22142. function DataTextureLoader( manager ) {
  22143. Loader.call( this, manager );
  22144. }
  22145. DataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  22146. constructor: DataTextureLoader,
  22147. load: function ( url, onLoad, onProgress, onError ) {
  22148. const scope = this;
  22149. const texture = new DataTexture();
  22150. const loader = new FileLoader( this.manager );
  22151. loader.setResponseType( 'arraybuffer' );
  22152. loader.setRequestHeader( this.requestHeader );
  22153. loader.setPath( this.path );
  22154. loader.setWithCredentials( scope.withCredentials );
  22155. loader.load( url, function ( buffer ) {
  22156. const texData = scope.parse( buffer );
  22157. if ( ! texData ) return;
  22158. if ( texData.image !== undefined ) {
  22159. texture.image = texData.image;
  22160. } else if ( texData.data !== undefined ) {
  22161. texture.image.width = texData.width;
  22162. texture.image.height = texData.height;
  22163. texture.image.data = texData.data;
  22164. }
  22165. texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
  22166. texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
  22167. texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
  22168. texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
  22169. texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
  22170. if ( texData.format !== undefined ) {
  22171. texture.format = texData.format;
  22172. }
  22173. if ( texData.type !== undefined ) {
  22174. texture.type = texData.type;
  22175. }
  22176. if ( texData.mipmaps !== undefined ) {
  22177. texture.mipmaps = texData.mipmaps;
  22178. texture.minFilter = LinearMipmapLinearFilter; // presumably...
  22179. }
  22180. if ( texData.mipmapCount === 1 ) {
  22181. texture.minFilter = LinearFilter;
  22182. }
  22183. texture.needsUpdate = true;
  22184. if ( onLoad ) onLoad( texture, texData );
  22185. }, onProgress, onError );
  22186. return texture;
  22187. }
  22188. } );
  22189. function TextureLoader( manager ) {
  22190. Loader.call( this, manager );
  22191. }
  22192. TextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  22193. constructor: TextureLoader,
  22194. load: function ( url, onLoad, onProgress, onError ) {
  22195. const texture = new Texture();
  22196. const loader = new ImageLoader( this.manager );
  22197. loader.setCrossOrigin( this.crossOrigin );
  22198. loader.setPath( this.path );
  22199. loader.load( url, function ( image ) {
  22200. texture.image = image;
  22201. // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
  22202. const isJPEG = url.search( /\.jpe?g($|\?)/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
  22203. texture.format = isJPEG ? RGBFormat : RGBAFormat;
  22204. texture.needsUpdate = true;
  22205. if ( onLoad !== undefined ) {
  22206. onLoad( texture );
  22207. }
  22208. }, onProgress, onError );
  22209. return texture;
  22210. }
  22211. } );
  22212. /**
  22213. * Extensible curve object.
  22214. *
  22215. * Some common of curve methods:
  22216. * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
  22217. * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
  22218. * .getPoints(), .getSpacedPoints()
  22219. * .getLength()
  22220. * .updateArcLengths()
  22221. *
  22222. * This following curves inherit from THREE.Curve:
  22223. *
  22224. * -- 2D curves --
  22225. * THREE.ArcCurve
  22226. * THREE.CubicBezierCurve
  22227. * THREE.EllipseCurve
  22228. * THREE.LineCurve
  22229. * THREE.QuadraticBezierCurve
  22230. * THREE.SplineCurve
  22231. *
  22232. * -- 3D curves --
  22233. * THREE.CatmullRomCurve3
  22234. * THREE.CubicBezierCurve3
  22235. * THREE.LineCurve3
  22236. * THREE.QuadraticBezierCurve3
  22237. *
  22238. * A series of curves can be represented as a THREE.CurvePath.
  22239. *
  22240. **/
  22241. function Curve() {
  22242. this.type = 'Curve';
  22243. this.arcLengthDivisions = 200;
  22244. }
  22245. Object.assign( Curve.prototype, {
  22246. // Virtual base class method to overwrite and implement in subclasses
  22247. // - t [0 .. 1]
  22248. getPoint: function ( /* t, optionalTarget */ ) {
  22249. console.warn( 'THREE.Curve: .getPoint() not implemented.' );
  22250. return null;
  22251. },
  22252. // Get point at relative position in curve according to arc length
  22253. // - u [0 .. 1]
  22254. getPointAt: function ( u, optionalTarget ) {
  22255. const t = this.getUtoTmapping( u );
  22256. return this.getPoint( t, optionalTarget );
  22257. },
  22258. // Get sequence of points using getPoint( t )
  22259. getPoints: function ( divisions = 5 ) {
  22260. const points = [];
  22261. for ( let d = 0; d <= divisions; d ++ ) {
  22262. points.push( this.getPoint( d / divisions ) );
  22263. }
  22264. return points;
  22265. },
  22266. // Get sequence of points using getPointAt( u )
  22267. getSpacedPoints: function ( divisions = 5 ) {
  22268. const points = [];
  22269. for ( let d = 0; d <= divisions; d ++ ) {
  22270. points.push( this.getPointAt( d / divisions ) );
  22271. }
  22272. return points;
  22273. },
  22274. // Get total curve arc length
  22275. getLength: function () {
  22276. const lengths = this.getLengths();
  22277. return lengths[ lengths.length - 1 ];
  22278. },
  22279. // Get list of cumulative segment lengths
  22280. getLengths: function ( divisions ) {
  22281. if ( divisions === undefined ) divisions = this.arcLengthDivisions;
  22282. if ( this.cacheArcLengths &&
  22283. ( this.cacheArcLengths.length === divisions + 1 ) &&
  22284. ! this.needsUpdate ) {
  22285. return this.cacheArcLengths;
  22286. }
  22287. this.needsUpdate = false;
  22288. const cache = [];
  22289. let current, last = this.getPoint( 0 );
  22290. let sum = 0;
  22291. cache.push( 0 );
  22292. for ( let p = 1; p <= divisions; p ++ ) {
  22293. current = this.getPoint( p / divisions );
  22294. sum += current.distanceTo( last );
  22295. cache.push( sum );
  22296. last = current;
  22297. }
  22298. this.cacheArcLengths = cache;
  22299. return cache; // { sums: cache, sum: sum }; Sum is in the last element.
  22300. },
  22301. updateArcLengths: function () {
  22302. this.needsUpdate = true;
  22303. this.getLengths();
  22304. },
  22305. // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
  22306. getUtoTmapping: function ( u, distance ) {
  22307. const arcLengths = this.getLengths();
  22308. let i = 0;
  22309. const il = arcLengths.length;
  22310. let targetArcLength; // The targeted u distance value to get
  22311. if ( distance ) {
  22312. targetArcLength = distance;
  22313. } else {
  22314. targetArcLength = u * arcLengths[ il - 1 ];
  22315. }
  22316. // binary search for the index with largest value smaller than target u distance
  22317. let low = 0, high = il - 1, comparison;
  22318. while ( low <= high ) {
  22319. 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
  22320. comparison = arcLengths[ i ] - targetArcLength;
  22321. if ( comparison < 0 ) {
  22322. low = i + 1;
  22323. } else if ( comparison > 0 ) {
  22324. high = i - 1;
  22325. } else {
  22326. high = i;
  22327. break;
  22328. // DONE
  22329. }
  22330. }
  22331. i = high;
  22332. if ( arcLengths[ i ] === targetArcLength ) {
  22333. return i / ( il - 1 );
  22334. }
  22335. // we could get finer grain at lengths, or use simple interpolation between two points
  22336. const lengthBefore = arcLengths[ i ];
  22337. const lengthAfter = arcLengths[ i + 1 ];
  22338. const segmentLength = lengthAfter - lengthBefore;
  22339. // determine where we are between the 'before' and 'after' points
  22340. const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
  22341. // add that fractional amount to t
  22342. const t = ( i + segmentFraction ) / ( il - 1 );
  22343. return t;
  22344. },
  22345. // Returns a unit vector tangent at t
  22346. // In case any sub curve does not implement its tangent derivation,
  22347. // 2 points a small delta apart will be used to find its gradient
  22348. // which seems to give a reasonable approximation
  22349. getTangent: function ( t, optionalTarget ) {
  22350. const delta = 0.0001;
  22351. let t1 = t - delta;
  22352. let t2 = t + delta;
  22353. // Capping in case of danger
  22354. if ( t1 < 0 ) t1 = 0;
  22355. if ( t2 > 1 ) t2 = 1;
  22356. const pt1 = this.getPoint( t1 );
  22357. const pt2 = this.getPoint( t2 );
  22358. const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
  22359. tangent.copy( pt2 ).sub( pt1 ).normalize();
  22360. return tangent;
  22361. },
  22362. getTangentAt: function ( u, optionalTarget ) {
  22363. const t = this.getUtoTmapping( u );
  22364. return this.getTangent( t, optionalTarget );
  22365. },
  22366. computeFrenetFrames: function ( segments, closed ) {
  22367. // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
  22368. const normal = new Vector3();
  22369. const tangents = [];
  22370. const normals = [];
  22371. const binormals = [];
  22372. const vec = new Vector3();
  22373. const mat = new Matrix4();
  22374. // compute the tangent vectors for each segment on the curve
  22375. for ( let i = 0; i <= segments; i ++ ) {
  22376. const u = i / segments;
  22377. tangents[ i ] = this.getTangentAt( u, new Vector3() );
  22378. tangents[ i ].normalize();
  22379. }
  22380. // select an initial normal vector perpendicular to the first tangent vector,
  22381. // and in the direction of the minimum tangent xyz component
  22382. normals[ 0 ] = new Vector3();
  22383. binormals[ 0 ] = new Vector3();
  22384. let min = Number.MAX_VALUE;
  22385. const tx = Math.abs( tangents[ 0 ].x );
  22386. const ty = Math.abs( tangents[ 0 ].y );
  22387. const tz = Math.abs( tangents[ 0 ].z );
  22388. if ( tx <= min ) {
  22389. min = tx;
  22390. normal.set( 1, 0, 0 );
  22391. }
  22392. if ( ty <= min ) {
  22393. min = ty;
  22394. normal.set( 0, 1, 0 );
  22395. }
  22396. if ( tz <= min ) {
  22397. normal.set( 0, 0, 1 );
  22398. }
  22399. vec.crossVectors( tangents[ 0 ], normal ).normalize();
  22400. normals[ 0 ].crossVectors( tangents[ 0 ], vec );
  22401. binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
  22402. // compute the slowly-varying normal and binormal vectors for each segment on the curve
  22403. for ( let i = 1; i <= segments; i ++ ) {
  22404. normals[ i ] = normals[ i - 1 ].clone();
  22405. binormals[ i ] = binormals[ i - 1 ].clone();
  22406. vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
  22407. if ( vec.length() > Number.EPSILON ) {
  22408. vec.normalize();
  22409. const theta = Math.acos( MathUtils$1.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
  22410. normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
  22411. }
  22412. binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
  22413. }
  22414. // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
  22415. if ( closed === true ) {
  22416. let theta = Math.acos( MathUtils$1.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
  22417. theta /= segments;
  22418. if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
  22419. theta = - theta;
  22420. }
  22421. for ( let i = 1; i <= segments; i ++ ) {
  22422. // twist a little...
  22423. normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
  22424. binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
  22425. }
  22426. }
  22427. return {
  22428. tangents: tangents,
  22429. normals: normals,
  22430. binormals: binormals
  22431. };
  22432. },
  22433. clone: function () {
  22434. return new this.constructor().copy( this );
  22435. },
  22436. copy: function ( source ) {
  22437. this.arcLengthDivisions = source.arcLengthDivisions;
  22438. return this;
  22439. },
  22440. toJSON: function () {
  22441. const data = {
  22442. metadata: {
  22443. version: 4.5,
  22444. type: 'Curve',
  22445. generator: 'Curve.toJSON'
  22446. }
  22447. };
  22448. data.arcLengthDivisions = this.arcLengthDivisions;
  22449. data.type = this.type;
  22450. return data;
  22451. },
  22452. fromJSON: function ( json ) {
  22453. this.arcLengthDivisions = json.arcLengthDivisions;
  22454. return this;
  22455. }
  22456. } );
  22457. function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
  22458. Curve.call( this );
  22459. this.type = 'EllipseCurve';
  22460. this.aX = aX || 0;
  22461. this.aY = aY || 0;
  22462. this.xRadius = xRadius || 1;
  22463. this.yRadius = yRadius || 1;
  22464. this.aStartAngle = aStartAngle || 0;
  22465. this.aEndAngle = aEndAngle || 2 * Math.PI;
  22466. this.aClockwise = aClockwise || false;
  22467. this.aRotation = aRotation || 0;
  22468. }
  22469. EllipseCurve.prototype = Object.create( Curve.prototype );
  22470. EllipseCurve.prototype.constructor = EllipseCurve;
  22471. EllipseCurve.prototype.isEllipseCurve = true;
  22472. EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
  22473. const point = optionalTarget || new Vector2();
  22474. const twoPi = Math.PI * 2;
  22475. let deltaAngle = this.aEndAngle - this.aStartAngle;
  22476. const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
  22477. // ensures that deltaAngle is 0 .. 2 PI
  22478. while ( deltaAngle < 0 ) deltaAngle += twoPi;
  22479. while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
  22480. if ( deltaAngle < Number.EPSILON ) {
  22481. if ( samePoints ) {
  22482. deltaAngle = 0;
  22483. } else {
  22484. deltaAngle = twoPi;
  22485. }
  22486. }
  22487. if ( this.aClockwise === true && ! samePoints ) {
  22488. if ( deltaAngle === twoPi ) {
  22489. deltaAngle = - twoPi;
  22490. } else {
  22491. deltaAngle = deltaAngle - twoPi;
  22492. }
  22493. }
  22494. const angle = this.aStartAngle + t * deltaAngle;
  22495. let x = this.aX + this.xRadius * Math.cos( angle );
  22496. let y = this.aY + this.yRadius * Math.sin( angle );
  22497. if ( this.aRotation !== 0 ) {
  22498. const cos = Math.cos( this.aRotation );
  22499. const sin = Math.sin( this.aRotation );
  22500. const tx = x - this.aX;
  22501. const ty = y - this.aY;
  22502. // Rotate the point about the center of the ellipse.
  22503. x = tx * cos - ty * sin + this.aX;
  22504. y = tx * sin + ty * cos + this.aY;
  22505. }
  22506. return point.set( x, y );
  22507. };
  22508. EllipseCurve.prototype.copy = function ( source ) {
  22509. Curve.prototype.copy.call( this, source );
  22510. this.aX = source.aX;
  22511. this.aY = source.aY;
  22512. this.xRadius = source.xRadius;
  22513. this.yRadius = source.yRadius;
  22514. this.aStartAngle = source.aStartAngle;
  22515. this.aEndAngle = source.aEndAngle;
  22516. this.aClockwise = source.aClockwise;
  22517. this.aRotation = source.aRotation;
  22518. return this;
  22519. };
  22520. EllipseCurve.prototype.toJSON = function () {
  22521. const data = Curve.prototype.toJSON.call( this );
  22522. data.aX = this.aX;
  22523. data.aY = this.aY;
  22524. data.xRadius = this.xRadius;
  22525. data.yRadius = this.yRadius;
  22526. data.aStartAngle = this.aStartAngle;
  22527. data.aEndAngle = this.aEndAngle;
  22528. data.aClockwise = this.aClockwise;
  22529. data.aRotation = this.aRotation;
  22530. return data;
  22531. };
  22532. EllipseCurve.prototype.fromJSON = function ( json ) {
  22533. Curve.prototype.fromJSON.call( this, json );
  22534. this.aX = json.aX;
  22535. this.aY = json.aY;
  22536. this.xRadius = json.xRadius;
  22537. this.yRadius = json.yRadius;
  22538. this.aStartAngle = json.aStartAngle;
  22539. this.aEndAngle = json.aEndAngle;
  22540. this.aClockwise = json.aClockwise;
  22541. this.aRotation = json.aRotation;
  22542. return this;
  22543. };
  22544. function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
  22545. EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
  22546. this.type = 'ArcCurve';
  22547. }
  22548. ArcCurve.prototype = Object.create( EllipseCurve.prototype );
  22549. ArcCurve.prototype.constructor = ArcCurve;
  22550. ArcCurve.prototype.isArcCurve = true;
  22551. /**
  22552. * Centripetal CatmullRom Curve - which is useful for avoiding
  22553. * cusps and self-intersections in non-uniform catmull rom curves.
  22554. * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
  22555. *
  22556. * curve.type accepts centripetal(default), chordal and catmullrom
  22557. * curve.tension is used for catmullrom which defaults to 0.5
  22558. */
  22559. /*
  22560. Based on an optimized c++ solution in
  22561. - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
  22562. - http://ideone.com/NoEbVM
  22563. This CubicPoly class could be used for reusing some variables and calculations,
  22564. but for three.js curve use, it could be possible inlined and flatten into a single function call
  22565. which can be placed in CurveUtils.
  22566. */
  22567. function CubicPoly() {
  22568. let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
  22569. /*
  22570. * Compute coefficients for a cubic polynomial
  22571. * p(s) = c0 + c1*s + c2*s^2 + c3*s^3
  22572. * such that
  22573. * p(0) = x0, p(1) = x1
  22574. * and
  22575. * p'(0) = t0, p'(1) = t1.
  22576. */
  22577. function init( x0, x1, t0, t1 ) {
  22578. c0 = x0;
  22579. c1 = t0;
  22580. c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
  22581. c3 = 2 * x0 - 2 * x1 + t0 + t1;
  22582. }
  22583. return {
  22584. initCatmullRom: function ( x0, x1, x2, x3, tension ) {
  22585. init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
  22586. },
  22587. initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
  22588. // compute tangents when parameterized in [t1,t2]
  22589. let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
  22590. let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
  22591. // rescale tangents for parametrization in [0,1]
  22592. t1 *= dt1;
  22593. t2 *= dt1;
  22594. init( x1, x2, t1, t2 );
  22595. },
  22596. calc: function ( t ) {
  22597. const t2 = t * t;
  22598. const t3 = t2 * t;
  22599. return c0 + c1 * t + c2 * t2 + c3 * t3;
  22600. }
  22601. };
  22602. }
  22603. //
  22604. const tmp = new Vector3();
  22605. const px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();
  22606. function CatmullRomCurve3( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
  22607. Curve.call( this );
  22608. this.type = 'CatmullRomCurve3';
  22609. this.points = points;
  22610. this.closed = closed;
  22611. this.curveType = curveType;
  22612. this.tension = tension;
  22613. }
  22614. CatmullRomCurve3.prototype = Object.create( Curve.prototype );
  22615. CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
  22616. CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
  22617. CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
  22618. const point = optionalTarget;
  22619. const points = this.points;
  22620. const l = points.length;
  22621. const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
  22622. let intPoint = Math.floor( p );
  22623. let weight = p - intPoint;
  22624. if ( this.closed ) {
  22625. intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
  22626. } else if ( weight === 0 && intPoint === l - 1 ) {
  22627. intPoint = l - 2;
  22628. weight = 1;
  22629. }
  22630. let p0, p3; // 4 points (p1 & p2 defined below)
  22631. if ( this.closed || intPoint > 0 ) {
  22632. p0 = points[ ( intPoint - 1 ) % l ];
  22633. } else {
  22634. // extrapolate first point
  22635. tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
  22636. p0 = tmp;
  22637. }
  22638. const p1 = points[ intPoint % l ];
  22639. const p2 = points[ ( intPoint + 1 ) % l ];
  22640. if ( this.closed || intPoint + 2 < l ) {
  22641. p3 = points[ ( intPoint + 2 ) % l ];
  22642. } else {
  22643. // extrapolate last point
  22644. tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
  22645. p3 = tmp;
  22646. }
  22647. if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
  22648. // init Centripetal / Chordal Catmull-Rom
  22649. const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
  22650. let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
  22651. let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
  22652. let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
  22653. // safety check for repeated points
  22654. if ( dt1 < 1e-4 ) dt1 = 1.0;
  22655. if ( dt0 < 1e-4 ) dt0 = dt1;
  22656. if ( dt2 < 1e-4 ) dt2 = dt1;
  22657. px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
  22658. py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
  22659. pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
  22660. } else if ( this.curveType === 'catmullrom' ) {
  22661. px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
  22662. py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
  22663. pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
  22664. }
  22665. point.set(
  22666. px.calc( weight ),
  22667. py.calc( weight ),
  22668. pz.calc( weight )
  22669. );
  22670. return point;
  22671. };
  22672. CatmullRomCurve3.prototype.copy = function ( source ) {
  22673. Curve.prototype.copy.call( this, source );
  22674. this.points = [];
  22675. for ( let i = 0, l = source.points.length; i < l; i ++ ) {
  22676. const point = source.points[ i ];
  22677. this.points.push( point.clone() );
  22678. }
  22679. this.closed = source.closed;
  22680. this.curveType = source.curveType;
  22681. this.tension = source.tension;
  22682. return this;
  22683. };
  22684. CatmullRomCurve3.prototype.toJSON = function () {
  22685. const data = Curve.prototype.toJSON.call( this );
  22686. data.points = [];
  22687. for ( let i = 0, l = this.points.length; i < l; i ++ ) {
  22688. const point = this.points[ i ];
  22689. data.points.push( point.toArray() );
  22690. }
  22691. data.closed = this.closed;
  22692. data.curveType = this.curveType;
  22693. data.tension = this.tension;
  22694. return data;
  22695. };
  22696. CatmullRomCurve3.prototype.fromJSON = function ( json ) {
  22697. Curve.prototype.fromJSON.call( this, json );
  22698. this.points = [];
  22699. for ( let i = 0, l = json.points.length; i < l; i ++ ) {
  22700. const point = json.points[ i ];
  22701. this.points.push( new Vector3().fromArray( point ) );
  22702. }
  22703. this.closed = json.closed;
  22704. this.curveType = json.curveType;
  22705. this.tension = json.tension;
  22706. return this;
  22707. };
  22708. /**
  22709. * Bezier Curves formulas obtained from
  22710. * http://en.wikipedia.org/wiki/Bézier_curve
  22711. */
  22712. function CatmullRom( t, p0, p1, p2, p3 ) {
  22713. const v0 = ( p2 - p0 ) * 0.5;
  22714. const v1 = ( p3 - p1 ) * 0.5;
  22715. const t2 = t * t;
  22716. const t3 = t * t2;
  22717. return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
  22718. }
  22719. //
  22720. function QuadraticBezierP0( t, p ) {
  22721. const k = 1 - t;
  22722. return k * k * p;
  22723. }
  22724. function QuadraticBezierP1( t, p ) {
  22725. return 2 * ( 1 - t ) * t * p;
  22726. }
  22727. function QuadraticBezierP2( t, p ) {
  22728. return t * t * p;
  22729. }
  22730. function QuadraticBezier( t, p0, p1, p2 ) {
  22731. return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
  22732. QuadraticBezierP2( t, p2 );
  22733. }
  22734. //
  22735. function CubicBezierP0( t, p ) {
  22736. const k = 1 - t;
  22737. return k * k * k * p;
  22738. }
  22739. function CubicBezierP1( t, p ) {
  22740. const k = 1 - t;
  22741. return 3 * k * k * t * p;
  22742. }
  22743. function CubicBezierP2( t, p ) {
  22744. return 3 * ( 1 - t ) * t * t * p;
  22745. }
  22746. function CubicBezierP3( t, p ) {
  22747. return t * t * t * p;
  22748. }
  22749. function CubicBezier( t, p0, p1, p2, p3 ) {
  22750. return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
  22751. CubicBezierP3( t, p3 );
  22752. }
  22753. function CubicBezierCurve( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
  22754. Curve.call( this );
  22755. this.type = 'CubicBezierCurve';
  22756. this.v0 = v0;
  22757. this.v1 = v1;
  22758. this.v2 = v2;
  22759. this.v3 = v3;
  22760. }
  22761. CubicBezierCurve.prototype = Object.create( Curve.prototype );
  22762. CubicBezierCurve.prototype.constructor = CubicBezierCurve;
  22763. CubicBezierCurve.prototype.isCubicBezierCurve = true;
  22764. CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
  22765. const point = optionalTarget;
  22766. const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
  22767. point.set(
  22768. CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
  22769. CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
  22770. );
  22771. return point;
  22772. };
  22773. CubicBezierCurve.prototype.copy = function ( source ) {
  22774. Curve.prototype.copy.call( this, source );
  22775. this.v0.copy( source.v0 );
  22776. this.v1.copy( source.v1 );
  22777. this.v2.copy( source.v2 );
  22778. this.v3.copy( source.v3 );
  22779. return this;
  22780. };
  22781. CubicBezierCurve.prototype.toJSON = function () {
  22782. const data = Curve.prototype.toJSON.call( this );
  22783. data.v0 = this.v0.toArray();
  22784. data.v1 = this.v1.toArray();
  22785. data.v2 = this.v2.toArray();
  22786. data.v3 = this.v3.toArray();
  22787. return data;
  22788. };
  22789. CubicBezierCurve.prototype.fromJSON = function ( json ) {
  22790. Curve.prototype.fromJSON.call( this, json );
  22791. this.v0.fromArray( json.v0 );
  22792. this.v1.fromArray( json.v1 );
  22793. this.v2.fromArray( json.v2 );
  22794. this.v3.fromArray( json.v3 );
  22795. return this;
  22796. };
  22797. function CubicBezierCurve3( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
  22798. Curve.call( this );
  22799. this.type = 'CubicBezierCurve3';
  22800. this.v0 = v0;
  22801. this.v1 = v1;
  22802. this.v2 = v2;
  22803. this.v3 = v3;
  22804. }
  22805. CubicBezierCurve3.prototype = Object.create( Curve.prototype );
  22806. CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
  22807. CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
  22808. CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
  22809. const point = optionalTarget;
  22810. const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
  22811. point.set(
  22812. CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
  22813. CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
  22814. CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
  22815. );
  22816. return point;
  22817. };
  22818. CubicBezierCurve3.prototype.copy = function ( source ) {
  22819. Curve.prototype.copy.call( this, source );
  22820. this.v0.copy( source.v0 );
  22821. this.v1.copy( source.v1 );
  22822. this.v2.copy( source.v2 );
  22823. this.v3.copy( source.v3 );
  22824. return this;
  22825. };
  22826. CubicBezierCurve3.prototype.toJSON = function () {
  22827. const data = Curve.prototype.toJSON.call( this );
  22828. data.v0 = this.v0.toArray();
  22829. data.v1 = this.v1.toArray();
  22830. data.v2 = this.v2.toArray();
  22831. data.v3 = this.v3.toArray();
  22832. return data;
  22833. };
  22834. CubicBezierCurve3.prototype.fromJSON = function ( json ) {
  22835. Curve.prototype.fromJSON.call( this, json );
  22836. this.v0.fromArray( json.v0 );
  22837. this.v1.fromArray( json.v1 );
  22838. this.v2.fromArray( json.v2 );
  22839. this.v3.fromArray( json.v3 );
  22840. return this;
  22841. };
  22842. function LineCurve( v1 = new Vector2(), v2 = new Vector2() ) {
  22843. Curve.call( this );
  22844. this.type = 'LineCurve';
  22845. this.v1 = v1;
  22846. this.v2 = v2;
  22847. }
  22848. LineCurve.prototype = Object.create( Curve.prototype );
  22849. LineCurve.prototype.constructor = LineCurve;
  22850. LineCurve.prototype.isLineCurve = true;
  22851. LineCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
  22852. const point = optionalTarget;
  22853. if ( t === 1 ) {
  22854. point.copy( this.v2 );
  22855. } else {
  22856. point.copy( this.v2 ).sub( this.v1 );
  22857. point.multiplyScalar( t ).add( this.v1 );
  22858. }
  22859. return point;
  22860. };
  22861. // Line curve is linear, so we can overwrite default getPointAt
  22862. LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
  22863. return this.getPoint( u, optionalTarget );
  22864. };
  22865. LineCurve.prototype.getTangent = function ( t, optionalTarget ) {
  22866. const tangent = optionalTarget || new Vector2();
  22867. tangent.copy( this.v2 ).sub( this.v1 ).normalize();
  22868. return tangent;
  22869. };
  22870. LineCurve.prototype.copy = function ( source ) {
  22871. Curve.prototype.copy.call( this, source );
  22872. this.v1.copy( source.v1 );
  22873. this.v2.copy( source.v2 );
  22874. return this;
  22875. };
  22876. LineCurve.prototype.toJSON = function () {
  22877. const data = Curve.prototype.toJSON.call( this );
  22878. data.v1 = this.v1.toArray();
  22879. data.v2 = this.v2.toArray();
  22880. return data;
  22881. };
  22882. LineCurve.prototype.fromJSON = function ( json ) {
  22883. Curve.prototype.fromJSON.call( this, json );
  22884. this.v1.fromArray( json.v1 );
  22885. this.v2.fromArray( json.v2 );
  22886. return this;
  22887. };
  22888. function LineCurve3( v1 = new Vector3(), v2 = new Vector3() ) {
  22889. Curve.call( this );
  22890. this.type = 'LineCurve3';
  22891. this.v1 = v1;
  22892. this.v2 = v2;
  22893. }
  22894. LineCurve3.prototype = Object.create( Curve.prototype );
  22895. LineCurve3.prototype.constructor = LineCurve3;
  22896. LineCurve3.prototype.isLineCurve3 = true;
  22897. LineCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
  22898. const point = optionalTarget;
  22899. if ( t === 1 ) {
  22900. point.copy( this.v2 );
  22901. } else {
  22902. point.copy( this.v2 ).sub( this.v1 );
  22903. point.multiplyScalar( t ).add( this.v1 );
  22904. }
  22905. return point;
  22906. };
  22907. // Line curve is linear, so we can overwrite default getPointAt
  22908. LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
  22909. return this.getPoint( u, optionalTarget );
  22910. };
  22911. LineCurve3.prototype.copy = function ( source ) {
  22912. Curve.prototype.copy.call( this, source );
  22913. this.v1.copy( source.v1 );
  22914. this.v2.copy( source.v2 );
  22915. return this;
  22916. };
  22917. LineCurve3.prototype.toJSON = function () {
  22918. const data = Curve.prototype.toJSON.call( this );
  22919. data.v1 = this.v1.toArray();
  22920. data.v2 = this.v2.toArray();
  22921. return data;
  22922. };
  22923. LineCurve3.prototype.fromJSON = function ( json ) {
  22924. Curve.prototype.fromJSON.call( this, json );
  22925. this.v1.fromArray( json.v1 );
  22926. this.v2.fromArray( json.v2 );
  22927. return this;
  22928. };
  22929. function QuadraticBezierCurve( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
  22930. Curve.call( this );
  22931. this.type = 'QuadraticBezierCurve';
  22932. this.v0 = v0;
  22933. this.v1 = v1;
  22934. this.v2 = v2;
  22935. }
  22936. QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
  22937. QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
  22938. QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
  22939. QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
  22940. const point = optionalTarget;
  22941. const v0 = this.v0, v1 = this.v1, v2 = this.v2;
  22942. point.set(
  22943. QuadraticBezier( t, v0.x, v1.x, v2.x ),
  22944. QuadraticBezier( t, v0.y, v1.y, v2.y )
  22945. );
  22946. return point;
  22947. };
  22948. QuadraticBezierCurve.prototype.copy = function ( source ) {
  22949. Curve.prototype.copy.call( this, source );
  22950. this.v0.copy( source.v0 );
  22951. this.v1.copy( source.v1 );
  22952. this.v2.copy( source.v2 );
  22953. return this;
  22954. };
  22955. QuadraticBezierCurve.prototype.toJSON = function () {
  22956. const data = Curve.prototype.toJSON.call( this );
  22957. data.v0 = this.v0.toArray();
  22958. data.v1 = this.v1.toArray();
  22959. data.v2 = this.v2.toArray();
  22960. return data;
  22961. };
  22962. QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
  22963. Curve.prototype.fromJSON.call( this, json );
  22964. this.v0.fromArray( json.v0 );
  22965. this.v1.fromArray( json.v1 );
  22966. this.v2.fromArray( json.v2 );
  22967. return this;
  22968. };
  22969. function QuadraticBezierCurve3( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
  22970. Curve.call( this );
  22971. this.type = 'QuadraticBezierCurve3';
  22972. this.v0 = v0;
  22973. this.v1 = v1;
  22974. this.v2 = v2;
  22975. }
  22976. QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
  22977. QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
  22978. QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
  22979. QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
  22980. const point = optionalTarget;
  22981. const v0 = this.v0, v1 = this.v1, v2 = this.v2;
  22982. point.set(
  22983. QuadraticBezier( t, v0.x, v1.x, v2.x ),
  22984. QuadraticBezier( t, v0.y, v1.y, v2.y ),
  22985. QuadraticBezier( t, v0.z, v1.z, v2.z )
  22986. );
  22987. return point;
  22988. };
  22989. QuadraticBezierCurve3.prototype.copy = function ( source ) {
  22990. Curve.prototype.copy.call( this, source );
  22991. this.v0.copy( source.v0 );
  22992. this.v1.copy( source.v1 );
  22993. this.v2.copy( source.v2 );
  22994. return this;
  22995. };
  22996. QuadraticBezierCurve3.prototype.toJSON = function () {
  22997. const data = Curve.prototype.toJSON.call( this );
  22998. data.v0 = this.v0.toArray();
  22999. data.v1 = this.v1.toArray();
  23000. data.v2 = this.v2.toArray();
  23001. return data;
  23002. };
  23003. QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
  23004. Curve.prototype.fromJSON.call( this, json );
  23005. this.v0.fromArray( json.v0 );
  23006. this.v1.fromArray( json.v1 );
  23007. this.v2.fromArray( json.v2 );
  23008. return this;
  23009. };
  23010. function SplineCurve( points = [] ) {
  23011. Curve.call( this );
  23012. this.type = 'SplineCurve';
  23013. this.points = points;
  23014. }
  23015. SplineCurve.prototype = Object.create( Curve.prototype );
  23016. SplineCurve.prototype.constructor = SplineCurve;
  23017. SplineCurve.prototype.isSplineCurve = true;
  23018. SplineCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
  23019. const point = optionalTarget;
  23020. const points = this.points;
  23021. const p = ( points.length - 1 ) * t;
  23022. const intPoint = Math.floor( p );
  23023. const weight = p - intPoint;
  23024. const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
  23025. const p1 = points[ intPoint ];
  23026. const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
  23027. const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
  23028. point.set(
  23029. CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
  23030. CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
  23031. );
  23032. return point;
  23033. };
  23034. SplineCurve.prototype.copy = function ( source ) {
  23035. Curve.prototype.copy.call( this, source );
  23036. this.points = [];
  23037. for ( let i = 0, l = source.points.length; i < l; i ++ ) {
  23038. const point = source.points[ i ];
  23039. this.points.push( point.clone() );
  23040. }
  23041. return this;
  23042. };
  23043. SplineCurve.prototype.toJSON = function () {
  23044. const data = Curve.prototype.toJSON.call( this );
  23045. data.points = [];
  23046. for ( let i = 0, l = this.points.length; i < l; i ++ ) {
  23047. const point = this.points[ i ];
  23048. data.points.push( point.toArray() );
  23049. }
  23050. return data;
  23051. };
  23052. SplineCurve.prototype.fromJSON = function ( json ) {
  23053. Curve.prototype.fromJSON.call( this, json );
  23054. this.points = [];
  23055. for ( let i = 0, l = json.points.length; i < l; i ++ ) {
  23056. const point = json.points[ i ];
  23057. this.points.push( new Vector2().fromArray( point ) );
  23058. }
  23059. return this;
  23060. };
  23061. var Curves = /*#__PURE__*/Object.freeze({
  23062. __proto__: null,
  23063. ArcCurve: ArcCurve,
  23064. CatmullRomCurve3: CatmullRomCurve3,
  23065. CubicBezierCurve: CubicBezierCurve,
  23066. CubicBezierCurve3: CubicBezierCurve3,
  23067. EllipseCurve: EllipseCurve,
  23068. LineCurve: LineCurve,
  23069. LineCurve3: LineCurve3,
  23070. QuadraticBezierCurve: QuadraticBezierCurve,
  23071. QuadraticBezierCurve3: QuadraticBezierCurve3,
  23072. SplineCurve: SplineCurve
  23073. });
  23074. /**************************************************************
  23075. * Curved Path - a curve path is simply a array of connected
  23076. * curves, but retains the api of a curve
  23077. **************************************************************/
  23078. function CurvePath() {
  23079. Curve.call( this );
  23080. this.type = 'CurvePath';
  23081. this.curves = [];
  23082. this.autoClose = false; // Automatically closes the path
  23083. }
  23084. CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
  23085. constructor: CurvePath,
  23086. add: function ( curve ) {
  23087. this.curves.push( curve );
  23088. },
  23089. closePath: function () {
  23090. // Add a line curve if start and end of lines are not connected
  23091. const startPoint = this.curves[ 0 ].getPoint( 0 );
  23092. const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
  23093. if ( ! startPoint.equals( endPoint ) ) {
  23094. this.curves.push( new LineCurve( endPoint, startPoint ) );
  23095. }
  23096. },
  23097. // To get accurate point with reference to
  23098. // entire path distance at time t,
  23099. // following has to be done:
  23100. // 1. Length of each sub path have to be known
  23101. // 2. Locate and identify type of curve
  23102. // 3. Get t for the curve
  23103. // 4. Return curve.getPointAt(t')
  23104. getPoint: function ( t ) {
  23105. const d = t * this.getLength();
  23106. const curveLengths = this.getCurveLengths();
  23107. let i = 0;
  23108. // To think about boundaries points.
  23109. while ( i < curveLengths.length ) {
  23110. if ( curveLengths[ i ] >= d ) {
  23111. const diff = curveLengths[ i ] - d;
  23112. const curve = this.curves[ i ];
  23113. const segmentLength = curve.getLength();
  23114. const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
  23115. return curve.getPointAt( u );
  23116. }
  23117. i ++;
  23118. }
  23119. return null;
  23120. // loop where sum != 0, sum > d , sum+1 <d
  23121. },
  23122. // We cannot use the default THREE.Curve getPoint() with getLength() because in
  23123. // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
  23124. // getPoint() depends on getLength
  23125. getLength: function () {
  23126. const lens = this.getCurveLengths();
  23127. return lens[ lens.length - 1 ];
  23128. },
  23129. // cacheLengths must be recalculated.
  23130. updateArcLengths: function () {
  23131. this.needsUpdate = true;
  23132. this.cacheLengths = null;
  23133. this.getCurveLengths();
  23134. },
  23135. // Compute lengths and cache them
  23136. // We cannot overwrite getLengths() because UtoT mapping uses it.
  23137. getCurveLengths: function () {
  23138. // We use cache values if curves and cache array are same length
  23139. if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
  23140. return this.cacheLengths;
  23141. }
  23142. // Get length of sub-curve
  23143. // Push sums into cached array
  23144. const lengths = [];
  23145. let sums = 0;
  23146. for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
  23147. sums += this.curves[ i ].getLength();
  23148. lengths.push( sums );
  23149. }
  23150. this.cacheLengths = lengths;
  23151. return lengths;
  23152. },
  23153. getSpacedPoints: function ( divisions = 40 ) {
  23154. const points = [];
  23155. for ( let i = 0; i <= divisions; i ++ ) {
  23156. points.push( this.getPoint( i / divisions ) );
  23157. }
  23158. if ( this.autoClose ) {
  23159. points.push( points[ 0 ] );
  23160. }
  23161. return points;
  23162. },
  23163. getPoints: function ( divisions = 12 ) {
  23164. const points = [];
  23165. let last;
  23166. for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
  23167. const curve = curves[ i ];
  23168. const resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
  23169. : ( curve && ( curve.isLineCurve || curve.isLineCurve3 ) ) ? 1
  23170. : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
  23171. : divisions;
  23172. const pts = curve.getPoints( resolution );
  23173. for ( let j = 0; j < pts.length; j ++ ) {
  23174. const point = pts[ j ];
  23175. if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
  23176. points.push( point );
  23177. last = point;
  23178. }
  23179. }
  23180. if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
  23181. points.push( points[ 0 ] );
  23182. }
  23183. return points;
  23184. },
  23185. copy: function ( source ) {
  23186. Curve.prototype.copy.call( this, source );
  23187. this.curves = [];
  23188. for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
  23189. const curve = source.curves[ i ];
  23190. this.curves.push( curve.clone() );
  23191. }
  23192. this.autoClose = source.autoClose;
  23193. return this;
  23194. },
  23195. toJSON: function () {
  23196. const data = Curve.prototype.toJSON.call( this );
  23197. data.autoClose = this.autoClose;
  23198. data.curves = [];
  23199. for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
  23200. const curve = this.curves[ i ];
  23201. data.curves.push( curve.toJSON() );
  23202. }
  23203. return data;
  23204. },
  23205. fromJSON: function ( json ) {
  23206. Curve.prototype.fromJSON.call( this, json );
  23207. this.autoClose = json.autoClose;
  23208. this.curves = [];
  23209. for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
  23210. const curve = json.curves[ i ];
  23211. this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
  23212. }
  23213. return this;
  23214. }
  23215. } );
  23216. function Path( points ) {
  23217. CurvePath.call( this );
  23218. this.type = 'Path';
  23219. this.currentPoint = new Vector2();
  23220. if ( points ) {
  23221. this.setFromPoints( points );
  23222. }
  23223. }
  23224. Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
  23225. constructor: Path,
  23226. setFromPoints: function ( points ) {
  23227. this.moveTo( points[ 0 ].x, points[ 0 ].y );
  23228. for ( let i = 1, l = points.length; i < l; i ++ ) {
  23229. this.lineTo( points[ i ].x, points[ i ].y );
  23230. }
  23231. return this;
  23232. },
  23233. moveTo: function ( x, y ) {
  23234. this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
  23235. return this;
  23236. },
  23237. lineTo: function ( x, y ) {
  23238. const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
  23239. this.curves.push( curve );
  23240. this.currentPoint.set( x, y );
  23241. return this;
  23242. },
  23243. quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
  23244. const curve = new QuadraticBezierCurve(
  23245. this.currentPoint.clone(),
  23246. new Vector2( aCPx, aCPy ),
  23247. new Vector2( aX, aY )
  23248. );
  23249. this.curves.push( curve );
  23250. this.currentPoint.set( aX, aY );
  23251. return this;
  23252. },
  23253. bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
  23254. const curve = new CubicBezierCurve(
  23255. this.currentPoint.clone(),
  23256. new Vector2( aCP1x, aCP1y ),
  23257. new Vector2( aCP2x, aCP2y ),
  23258. new Vector2( aX, aY )
  23259. );
  23260. this.curves.push( curve );
  23261. this.currentPoint.set( aX, aY );
  23262. return this;
  23263. },
  23264. splineThru: function ( pts /*Array of Vector*/ ) {
  23265. const npts = [ this.currentPoint.clone() ].concat( pts );
  23266. const curve = new SplineCurve( npts );
  23267. this.curves.push( curve );
  23268. this.currentPoint.copy( pts[ pts.length - 1 ] );
  23269. return this;
  23270. },
  23271. arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
  23272. const x0 = this.currentPoint.x;
  23273. const y0 = this.currentPoint.y;
  23274. this.absarc( aX + x0, aY + y0, aRadius,
  23275. aStartAngle, aEndAngle, aClockwise );
  23276. return this;
  23277. },
  23278. absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
  23279. this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
  23280. return this;
  23281. },
  23282. ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
  23283. const x0 = this.currentPoint.x;
  23284. const y0 = this.currentPoint.y;
  23285. this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
  23286. return this;
  23287. },
  23288. absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
  23289. const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
  23290. if ( this.curves.length > 0 ) {
  23291. // if a previous curve is present, attempt to join
  23292. const firstPoint = curve.getPoint( 0 );
  23293. if ( ! firstPoint.equals( this.currentPoint ) ) {
  23294. this.lineTo( firstPoint.x, firstPoint.y );
  23295. }
  23296. }
  23297. this.curves.push( curve );
  23298. const lastPoint = curve.getPoint( 1 );
  23299. this.currentPoint.copy( lastPoint );
  23300. return this;
  23301. },
  23302. copy: function ( source ) {
  23303. CurvePath.prototype.copy.call( this, source );
  23304. this.currentPoint.copy( source.currentPoint );
  23305. return this;
  23306. },
  23307. toJSON: function () {
  23308. const data = CurvePath.prototype.toJSON.call( this );
  23309. data.currentPoint = this.currentPoint.toArray();
  23310. return data;
  23311. },
  23312. fromJSON: function ( json ) {
  23313. CurvePath.prototype.fromJSON.call( this, json );
  23314. this.currentPoint.fromArray( json.currentPoint );
  23315. return this;
  23316. }
  23317. } );
  23318. function Shape( points ) {
  23319. Path.call( this, points );
  23320. this.uuid = MathUtils$1.generateUUID();
  23321. this.type = 'Shape';
  23322. this.holes = [];
  23323. }
  23324. Shape.prototype = Object.assign( Object.create( Path.prototype ), {
  23325. constructor: Shape,
  23326. getPointsHoles: function ( divisions ) {
  23327. const holesPts = [];
  23328. for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
  23329. holesPts[ i ] = this.holes[ i ].getPoints( divisions );
  23330. }
  23331. return holesPts;
  23332. },
  23333. // get points of shape and holes (keypoints based on segments parameter)
  23334. extractPoints: function ( divisions ) {
  23335. return {
  23336. shape: this.getPoints( divisions ),
  23337. holes: this.getPointsHoles( divisions )
  23338. };
  23339. },
  23340. copy: function ( source ) {
  23341. Path.prototype.copy.call( this, source );
  23342. this.holes = [];
  23343. for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
  23344. const hole = source.holes[ i ];
  23345. this.holes.push( hole.clone() );
  23346. }
  23347. return this;
  23348. },
  23349. toJSON: function () {
  23350. const data = Path.prototype.toJSON.call( this );
  23351. data.uuid = this.uuid;
  23352. data.holes = [];
  23353. for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
  23354. const hole = this.holes[ i ];
  23355. data.holes.push( hole.toJSON() );
  23356. }
  23357. return data;
  23358. },
  23359. fromJSON: function ( json ) {
  23360. Path.prototype.fromJSON.call( this, json );
  23361. this.uuid = json.uuid;
  23362. this.holes = [];
  23363. for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
  23364. const hole = json.holes[ i ];
  23365. this.holes.push( new Path().fromJSON( hole ) );
  23366. }
  23367. return this;
  23368. }
  23369. } );
  23370. function Light( color, intensity = 1 ) {
  23371. Object3D.call( this );
  23372. this.type = 'Light';
  23373. this.color = new Color( color );
  23374. this.intensity = intensity;
  23375. }
  23376. Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
  23377. constructor: Light,
  23378. isLight: true,
  23379. copy: function ( source ) {
  23380. Object3D.prototype.copy.call( this, source );
  23381. this.color.copy( source.color );
  23382. this.intensity = source.intensity;
  23383. return this;
  23384. },
  23385. toJSON: function ( meta ) {
  23386. const data = Object3D.prototype.toJSON.call( this, meta );
  23387. data.object.color = this.color.getHex();
  23388. data.object.intensity = this.intensity;
  23389. if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
  23390. if ( this.distance !== undefined ) data.object.distance = this.distance;
  23391. if ( this.angle !== undefined ) data.object.angle = this.angle;
  23392. if ( this.decay !== undefined ) data.object.decay = this.decay;
  23393. if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
  23394. if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
  23395. return data;
  23396. }
  23397. } );
  23398. function HemisphereLight( skyColor, groundColor, intensity ) {
  23399. Light.call( this, skyColor, intensity );
  23400. this.type = 'HemisphereLight';
  23401. this.position.copy( Object3D.DefaultUp );
  23402. this.updateMatrix();
  23403. this.groundColor = new Color( groundColor );
  23404. }
  23405. HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
  23406. constructor: HemisphereLight,
  23407. isHemisphereLight: true,
  23408. copy: function ( source ) {
  23409. Light.prototype.copy.call( this, source );
  23410. this.groundColor.copy( source.groundColor );
  23411. return this;
  23412. }
  23413. } );
  23414. function LightShadow( camera ) {
  23415. this.camera = camera;
  23416. this.bias = 0;
  23417. this.normalBias = 0;
  23418. this.radius = 1;
  23419. this.mapSize = new Vector2( 512, 512 );
  23420. this.map = null;
  23421. this.mapPass = null;
  23422. this.matrix = new Matrix4();
  23423. this.autoUpdate = true;
  23424. this.needsUpdate = false;
  23425. this._frustum = new Frustum();
  23426. this._frameExtents = new Vector2( 1, 1 );
  23427. this._viewportCount = 1;
  23428. this._viewports = [
  23429. new Vector4( 0, 0, 1, 1 )
  23430. ];
  23431. }
  23432. Object.assign( LightShadow.prototype, {
  23433. _projScreenMatrix: new Matrix4(),
  23434. _lightPositionWorld: new Vector3(),
  23435. _lookTarget: new Vector3(),
  23436. getViewportCount: function () {
  23437. return this._viewportCount;
  23438. },
  23439. getFrustum: function () {
  23440. return this._frustum;
  23441. },
  23442. updateMatrices: function ( light ) {
  23443. const shadowCamera = this.camera,
  23444. shadowMatrix = this.matrix,
  23445. projScreenMatrix = this._projScreenMatrix,
  23446. lookTarget = this._lookTarget,
  23447. lightPositionWorld = this._lightPositionWorld;
  23448. lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
  23449. shadowCamera.position.copy( lightPositionWorld );
  23450. lookTarget.setFromMatrixPosition( light.target.matrixWorld );
  23451. shadowCamera.lookAt( lookTarget );
  23452. shadowCamera.updateMatrixWorld();
  23453. projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
  23454. this._frustum.setFromProjectionMatrix( projScreenMatrix );
  23455. shadowMatrix.set(
  23456. 0.5, 0.0, 0.0, 0.5,
  23457. 0.0, 0.5, 0.0, 0.5,
  23458. 0.0, 0.0, 0.5, 0.5,
  23459. 0.0, 0.0, 0.0, 1.0
  23460. );
  23461. shadowMatrix.multiply( shadowCamera.projectionMatrix );
  23462. shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
  23463. },
  23464. getViewport: function ( viewportIndex ) {
  23465. return this._viewports[ viewportIndex ];
  23466. },
  23467. getFrameExtents: function () {
  23468. return this._frameExtents;
  23469. },
  23470. copy: function ( source ) {
  23471. this.camera = source.camera.clone();
  23472. this.bias = source.bias;
  23473. this.radius = source.radius;
  23474. this.mapSize.copy( source.mapSize );
  23475. return this;
  23476. },
  23477. clone: function () {
  23478. return new this.constructor().copy( this );
  23479. },
  23480. toJSON: function () {
  23481. const object = {};
  23482. if ( this.bias !== 0 ) object.bias = this.bias;
  23483. if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
  23484. if ( this.radius !== 1 ) object.radius = this.radius;
  23485. if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
  23486. object.camera = this.camera.toJSON( false ).object;
  23487. delete object.camera.matrix;
  23488. return object;
  23489. }
  23490. } );
  23491. function SpotLightShadow() {
  23492. LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
  23493. this.focus = 1;
  23494. }
  23495. SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
  23496. constructor: SpotLightShadow,
  23497. isSpotLightShadow: true,
  23498. updateMatrices: function ( light ) {
  23499. const camera = this.camera;
  23500. const fov = MathUtils$1.RAD2DEG * 2 * light.angle * this.focus;
  23501. const aspect = this.mapSize.width / this.mapSize.height;
  23502. const far = light.distance || camera.far;
  23503. if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
  23504. camera.fov = fov;
  23505. camera.aspect = aspect;
  23506. camera.far = far;
  23507. camera.updateProjectionMatrix();
  23508. }
  23509. LightShadow.prototype.updateMatrices.call( this, light );
  23510. }
  23511. } );
  23512. function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
  23513. Light.call( this, color, intensity );
  23514. this.type = 'SpotLight';
  23515. this.position.copy( Object3D.DefaultUp );
  23516. this.updateMatrix();
  23517. this.target = new Object3D();
  23518. Object.defineProperty( this, 'power', {
  23519. get: function () {
  23520. // intensity = power per solid angle.
  23521. // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  23522. return this.intensity * Math.PI;
  23523. },
  23524. set: function ( power ) {
  23525. // intensity = power per solid angle.
  23526. // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  23527. this.intensity = power / Math.PI;
  23528. }
  23529. } );
  23530. this.distance = ( distance !== undefined ) ? distance : 0;
  23531. this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
  23532. this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
  23533. this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
  23534. this.shadow = new SpotLightShadow();
  23535. }
  23536. SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
  23537. constructor: SpotLight,
  23538. isSpotLight: true,
  23539. copy: function ( source ) {
  23540. Light.prototype.copy.call( this, source );
  23541. this.distance = source.distance;
  23542. this.angle = source.angle;
  23543. this.penumbra = source.penumbra;
  23544. this.decay = source.decay;
  23545. this.target = source.target.clone();
  23546. this.shadow = source.shadow.clone();
  23547. return this;
  23548. }
  23549. } );
  23550. function PointLightShadow() {
  23551. LightShadow.call( this, new PerspectiveCamera( 90, 1, 0.5, 500 ) );
  23552. this._frameExtents = new Vector2( 4, 2 );
  23553. this._viewportCount = 6;
  23554. this._viewports = [
  23555. // These viewports map a cube-map onto a 2D texture with the
  23556. // following orientation:
  23557. //
  23558. // xzXZ
  23559. // y Y
  23560. //
  23561. // X - Positive x direction
  23562. // x - Negative x direction
  23563. // Y - Positive y direction
  23564. // y - Negative y direction
  23565. // Z - Positive z direction
  23566. // z - Negative z direction
  23567. // positive X
  23568. new Vector4( 2, 1, 1, 1 ),
  23569. // negative X
  23570. new Vector4( 0, 1, 1, 1 ),
  23571. // positive Z
  23572. new Vector4( 3, 1, 1, 1 ),
  23573. // negative Z
  23574. new Vector4( 1, 1, 1, 1 ),
  23575. // positive Y
  23576. new Vector4( 3, 0, 1, 1 ),
  23577. // negative Y
  23578. new Vector4( 1, 0, 1, 1 )
  23579. ];
  23580. this._cubeDirections = [
  23581. new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
  23582. new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
  23583. ];
  23584. this._cubeUps = [
  23585. new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
  23586. new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
  23587. ];
  23588. }
  23589. PointLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
  23590. constructor: PointLightShadow,
  23591. isPointLightShadow: true,
  23592. updateMatrices: function ( light, viewportIndex = 0 ) {
  23593. const camera = this.camera,
  23594. shadowMatrix = this.matrix,
  23595. lightPositionWorld = this._lightPositionWorld,
  23596. lookTarget = this._lookTarget,
  23597. projScreenMatrix = this._projScreenMatrix;
  23598. lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
  23599. camera.position.copy( lightPositionWorld );
  23600. lookTarget.copy( camera.position );
  23601. lookTarget.add( this._cubeDirections[ viewportIndex ] );
  23602. camera.up.copy( this._cubeUps[ viewportIndex ] );
  23603. camera.lookAt( lookTarget );
  23604. camera.updateMatrixWorld();
  23605. shadowMatrix.makeTranslation( - lightPositionWorld.x, - lightPositionWorld.y, - lightPositionWorld.z );
  23606. projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
  23607. this._frustum.setFromProjectionMatrix( projScreenMatrix );
  23608. }
  23609. } );
  23610. function PointLight( color, intensity, distance, decay ) {
  23611. Light.call( this, color, intensity );
  23612. this.type = 'PointLight';
  23613. Object.defineProperty( this, 'power', {
  23614. get: function () {
  23615. // intensity = power per solid angle.
  23616. // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  23617. return this.intensity * 4 * Math.PI;
  23618. },
  23619. set: function ( power ) {
  23620. // intensity = power per solid angle.
  23621. // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  23622. this.intensity = power / ( 4 * Math.PI );
  23623. }
  23624. } );
  23625. this.distance = ( distance !== undefined ) ? distance : 0;
  23626. this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
  23627. this.shadow = new PointLightShadow();
  23628. }
  23629. PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
  23630. constructor: PointLight,
  23631. isPointLight: true,
  23632. copy: function ( source ) {
  23633. Light.prototype.copy.call( this, source );
  23634. this.distance = source.distance;
  23635. this.decay = source.decay;
  23636. this.shadow = source.shadow.clone();
  23637. return this;
  23638. }
  23639. } );
  23640. function OrthographicCamera( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
  23641. Camera.call( this );
  23642. this.type = 'OrthographicCamera';
  23643. this.zoom = 1;
  23644. this.view = null;
  23645. this.left = left;
  23646. this.right = right;
  23647. this.top = top;
  23648. this.bottom = bottom;
  23649. this.near = near;
  23650. this.far = far;
  23651. this.updateProjectionMatrix();
  23652. }
  23653. OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
  23654. constructor: OrthographicCamera,
  23655. isOrthographicCamera: true,
  23656. copy: function ( source, recursive ) {
  23657. Camera.prototype.copy.call( this, source, recursive );
  23658. this.left = source.left;
  23659. this.right = source.right;
  23660. this.top = source.top;
  23661. this.bottom = source.bottom;
  23662. this.near = source.near;
  23663. this.far = source.far;
  23664. this.zoom = source.zoom;
  23665. this.view = source.view === null ? null : Object.assign( {}, source.view );
  23666. return this;
  23667. },
  23668. setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
  23669. if ( this.view === null ) {
  23670. this.view = {
  23671. enabled: true,
  23672. fullWidth: 1,
  23673. fullHeight: 1,
  23674. offsetX: 0,
  23675. offsetY: 0,
  23676. width: 1,
  23677. height: 1
  23678. };
  23679. }
  23680. this.view.enabled = true;
  23681. this.view.fullWidth = fullWidth;
  23682. this.view.fullHeight = fullHeight;
  23683. this.view.offsetX = x;
  23684. this.view.offsetY = y;
  23685. this.view.width = width;
  23686. this.view.height = height;
  23687. this.updateProjectionMatrix();
  23688. },
  23689. clearViewOffset: function () {
  23690. if ( this.view !== null ) {
  23691. this.view.enabled = false;
  23692. }
  23693. this.updateProjectionMatrix();
  23694. },
  23695. updateProjectionMatrix: function () {
  23696. const dx = ( this.right - this.left ) / ( 2 * this.zoom );
  23697. const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
  23698. const cx = ( this.right + this.left ) / 2;
  23699. const cy = ( this.top + this.bottom ) / 2;
  23700. let left = cx - dx;
  23701. let right = cx + dx;
  23702. let top = cy + dy;
  23703. let bottom = cy - dy;
  23704. if ( this.view !== null && this.view.enabled ) {
  23705. const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
  23706. const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
  23707. left += scaleW * this.view.offsetX;
  23708. right = left + scaleW * this.view.width;
  23709. top -= scaleH * this.view.offsetY;
  23710. bottom = top - scaleH * this.view.height;
  23711. }
  23712. this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
  23713. this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
  23714. },
  23715. toJSON: function ( meta ) {
  23716. const data = Object3D.prototype.toJSON.call( this, meta );
  23717. data.object.zoom = this.zoom;
  23718. data.object.left = this.left;
  23719. data.object.right = this.right;
  23720. data.object.top = this.top;
  23721. data.object.bottom = this.bottom;
  23722. data.object.near = this.near;
  23723. data.object.far = this.far;
  23724. if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
  23725. return data;
  23726. }
  23727. } );
  23728. function DirectionalLightShadow() {
  23729. LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
  23730. }
  23731. DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
  23732. constructor: DirectionalLightShadow,
  23733. isDirectionalLightShadow: true,
  23734. updateMatrices: function ( light ) {
  23735. LightShadow.prototype.updateMatrices.call( this, light );
  23736. }
  23737. } );
  23738. function DirectionalLight( color, intensity ) {
  23739. Light.call( this, color, intensity );
  23740. this.type = 'DirectionalLight';
  23741. this.position.copy( Object3D.DefaultUp );
  23742. this.updateMatrix();
  23743. this.target = new Object3D();
  23744. this.shadow = new DirectionalLightShadow();
  23745. }
  23746. DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
  23747. constructor: DirectionalLight,
  23748. isDirectionalLight: true,
  23749. copy: function ( source ) {
  23750. Light.prototype.copy.call( this, source );
  23751. this.target = source.target.clone();
  23752. this.shadow = source.shadow.clone();
  23753. return this;
  23754. }
  23755. } );
  23756. function AmbientLight( color, intensity ) {
  23757. Light.call( this, color, intensity );
  23758. this.type = 'AmbientLight';
  23759. }
  23760. AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
  23761. constructor: AmbientLight,
  23762. isAmbientLight: true
  23763. } );
  23764. function RectAreaLight( color, intensity, width, height ) {
  23765. Light.call( this, color, intensity );
  23766. this.type = 'RectAreaLight';
  23767. this.width = ( width !== undefined ) ? width : 10;
  23768. this.height = ( height !== undefined ) ? height : 10;
  23769. }
  23770. RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
  23771. constructor: RectAreaLight,
  23772. isRectAreaLight: true,
  23773. copy: function ( source ) {
  23774. Light.prototype.copy.call( this, source );
  23775. this.width = source.width;
  23776. this.height = source.height;
  23777. return this;
  23778. },
  23779. toJSON: function ( meta ) {
  23780. const data = Light.prototype.toJSON.call( this, meta );
  23781. data.object.width = this.width;
  23782. data.object.height = this.height;
  23783. return data;
  23784. }
  23785. } );
  23786. /**
  23787. * Primary reference:
  23788. * https://graphics.stanford.edu/papers/envmap/envmap.pdf
  23789. *
  23790. * Secondary reference:
  23791. * https://www.ppsloan.org/publications/StupidSH36.pdf
  23792. */
  23793. // 3-band SH defined by 9 coefficients
  23794. class SphericalHarmonics3 {
  23795. constructor() {
  23796. Object.defineProperty( this, 'isSphericalHarmonics3', { value: true } );
  23797. this.coefficients = [];
  23798. for ( let i = 0; i < 9; i ++ ) {
  23799. this.coefficients.push( new Vector3() );
  23800. }
  23801. }
  23802. set( coefficients ) {
  23803. for ( let i = 0; i < 9; i ++ ) {
  23804. this.coefficients[ i ].copy( coefficients[ i ] );
  23805. }
  23806. return this;
  23807. }
  23808. zero() {
  23809. for ( let i = 0; i < 9; i ++ ) {
  23810. this.coefficients[ i ].set( 0, 0, 0 );
  23811. }
  23812. return this;
  23813. }
  23814. // get the radiance in the direction of the normal
  23815. // target is a Vector3
  23816. getAt( normal, target ) {
  23817. // normal is assumed to be unit length
  23818. const x = normal.x, y = normal.y, z = normal.z;
  23819. const coeff = this.coefficients;
  23820. // band 0
  23821. target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
  23822. // band 1
  23823. target.addScaledVector( coeff[ 1 ], 0.488603 * y );
  23824. target.addScaledVector( coeff[ 2 ], 0.488603 * z );
  23825. target.addScaledVector( coeff[ 3 ], 0.488603 * x );
  23826. // band 2
  23827. target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
  23828. target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
  23829. target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
  23830. target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
  23831. target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
  23832. return target;
  23833. }
  23834. // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
  23835. // target is a Vector3
  23836. // https://graphics.stanford.edu/papers/envmap/envmap.pdf
  23837. getIrradianceAt( normal, target ) {
  23838. // normal is assumed to be unit length
  23839. const x = normal.x, y = normal.y, z = normal.z;
  23840. const coeff = this.coefficients;
  23841. // band 0
  23842. target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095
  23843. // band 1
  23844. target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603
  23845. target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
  23846. target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
  23847. // band 2
  23848. target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548
  23849. target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
  23850. target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
  23851. target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
  23852. target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274
  23853. return target;
  23854. }
  23855. add( sh ) {
  23856. for ( let i = 0; i < 9; i ++ ) {
  23857. this.coefficients[ i ].add( sh.coefficients[ i ] );
  23858. }
  23859. return this;
  23860. }
  23861. addScaledSH( sh, s ) {
  23862. for ( let i = 0; i < 9; i ++ ) {
  23863. this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
  23864. }
  23865. return this;
  23866. }
  23867. scale( s ) {
  23868. for ( let i = 0; i < 9; i ++ ) {
  23869. this.coefficients[ i ].multiplyScalar( s );
  23870. }
  23871. return this;
  23872. }
  23873. lerp( sh, alpha ) {
  23874. for ( let i = 0; i < 9; i ++ ) {
  23875. this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
  23876. }
  23877. return this;
  23878. }
  23879. equals( sh ) {
  23880. for ( let i = 0; i < 9; i ++ ) {
  23881. if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
  23882. return false;
  23883. }
  23884. }
  23885. return true;
  23886. }
  23887. copy( sh ) {
  23888. return this.set( sh.coefficients );
  23889. }
  23890. clone() {
  23891. return new this.constructor().copy( this );
  23892. }
  23893. fromArray( array, offset = 0 ) {
  23894. const coefficients = this.coefficients;
  23895. for ( let i = 0; i < 9; i ++ ) {
  23896. coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
  23897. }
  23898. return this;
  23899. }
  23900. toArray( array = [], offset = 0 ) {
  23901. const coefficients = this.coefficients;
  23902. for ( let i = 0; i < 9; i ++ ) {
  23903. coefficients[ i ].toArray( array, offset + ( i * 3 ) );
  23904. }
  23905. return array;
  23906. }
  23907. // evaluate the basis functions
  23908. // shBasis is an Array[ 9 ]
  23909. static getBasisAt( normal, shBasis ) {
  23910. // normal is assumed to be unit length
  23911. const x = normal.x, y = normal.y, z = normal.z;
  23912. // band 0
  23913. shBasis[ 0 ] = 0.282095;
  23914. // band 1
  23915. shBasis[ 1 ] = 0.488603 * y;
  23916. shBasis[ 2 ] = 0.488603 * z;
  23917. shBasis[ 3 ] = 0.488603 * x;
  23918. // band 2
  23919. shBasis[ 4 ] = 1.092548 * x * y;
  23920. shBasis[ 5 ] = 1.092548 * y * z;
  23921. shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
  23922. shBasis[ 7 ] = 1.092548 * x * z;
  23923. shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
  23924. }
  23925. }
  23926. function LightProbe( sh, intensity ) {
  23927. Light.call( this, undefined, intensity );
  23928. this.type = 'LightProbe';
  23929. this.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();
  23930. }
  23931. LightProbe.prototype = Object.assign( Object.create( Light.prototype ), {
  23932. constructor: LightProbe,
  23933. isLightProbe: true,
  23934. copy: function ( source ) {
  23935. Light.prototype.copy.call( this, source );
  23936. this.sh.copy( source.sh );
  23937. return this;
  23938. },
  23939. fromJSON: function ( json ) {
  23940. this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
  23941. this.sh.fromArray( json.sh );
  23942. return this;
  23943. },
  23944. toJSON: function ( meta ) {
  23945. const data = Light.prototype.toJSON.call( this, meta );
  23946. data.object.sh = this.sh.toArray();
  23947. return data;
  23948. }
  23949. } );
  23950. function MaterialLoader( manager ) {
  23951. Loader.call( this, manager );
  23952. this.textures = {};
  23953. }
  23954. MaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  23955. constructor: MaterialLoader,
  23956. load: function ( url, onLoad, onProgress, onError ) {
  23957. const scope = this;
  23958. const loader = new FileLoader( scope.manager );
  23959. loader.setPath( scope.path );
  23960. loader.setRequestHeader( scope.requestHeader );
  23961. loader.setWithCredentials( scope.withCredentials );
  23962. loader.load( url, function ( text ) {
  23963. try {
  23964. onLoad( scope.parse( JSON.parse( text ) ) );
  23965. } catch ( e ) {
  23966. if ( onError ) {
  23967. onError( e );
  23968. } else {
  23969. console.error( e );
  23970. }
  23971. scope.manager.itemError( url );
  23972. }
  23973. }, onProgress, onError );
  23974. },
  23975. parse: function ( json ) {
  23976. const textures = this.textures;
  23977. function getTexture( name ) {
  23978. if ( textures[ name ] === undefined ) {
  23979. console.warn( 'THREE.MaterialLoader: Undefined texture', name );
  23980. }
  23981. return textures[ name ];
  23982. }
  23983. const material = new Materials[ json.type ]();
  23984. if ( json.uuid !== undefined ) material.uuid = json.uuid;
  23985. if ( json.name !== undefined ) material.name = json.name;
  23986. if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
  23987. if ( json.roughness !== undefined ) material.roughness = json.roughness;
  23988. if ( json.metalness !== undefined ) material.metalness = json.metalness;
  23989. if ( json.sheen !== undefined ) material.sheen = new Color().setHex( json.sheen );
  23990. if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
  23991. if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
  23992. if ( json.shininess !== undefined ) material.shininess = json.shininess;
  23993. if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
  23994. if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
  23995. if ( json.fog !== undefined ) material.fog = json.fog;
  23996. if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
  23997. if ( json.blending !== undefined ) material.blending = json.blending;
  23998. if ( json.combine !== undefined ) material.combine = json.combine;
  23999. if ( json.side !== undefined ) material.side = json.side;
  24000. if ( json.opacity !== undefined ) material.opacity = json.opacity;
  24001. if ( json.transparent !== undefined ) material.transparent = json.transparent;
  24002. if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
  24003. if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
  24004. if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
  24005. if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
  24006. if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
  24007. if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
  24008. if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
  24009. if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
  24010. if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
  24011. if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
  24012. if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
  24013. if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
  24014. if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
  24015. if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
  24016. if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
  24017. if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
  24018. if ( json.rotation !== undefined ) material.rotation = json.rotation;
  24019. if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
  24020. if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
  24021. if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
  24022. if ( json.scale !== undefined ) material.scale = json.scale;
  24023. if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
  24024. if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
  24025. if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
  24026. if ( json.skinning !== undefined ) material.skinning = json.skinning;
  24027. if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
  24028. if ( json.morphNormals !== undefined ) material.morphNormals = json.morphNormals;
  24029. if ( json.dithering !== undefined ) material.dithering = json.dithering;
  24030. if ( json.vertexTangents !== undefined ) material.vertexTangents = json.vertexTangents;
  24031. if ( json.visible !== undefined ) material.visible = json.visible;
  24032. if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
  24033. if ( json.userData !== undefined ) material.userData = json.userData;
  24034. if ( json.vertexColors !== undefined ) {
  24035. if ( typeof json.vertexColors === 'number' ) {
  24036. material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
  24037. } else {
  24038. material.vertexColors = json.vertexColors;
  24039. }
  24040. }
  24041. // Shader Material
  24042. if ( json.uniforms !== undefined ) {
  24043. for ( const name in json.uniforms ) {
  24044. const uniform = json.uniforms[ name ];
  24045. material.uniforms[ name ] = {};
  24046. switch ( uniform.type ) {
  24047. case 't':
  24048. material.uniforms[ name ].value = getTexture( uniform.value );
  24049. break;
  24050. case 'c':
  24051. material.uniforms[ name ].value = new Color().setHex( uniform.value );
  24052. break;
  24053. case 'v2':
  24054. material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
  24055. break;
  24056. case 'v3':
  24057. material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
  24058. break;
  24059. case 'v4':
  24060. material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
  24061. break;
  24062. case 'm3':
  24063. material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
  24064. break;
  24065. case 'm4':
  24066. material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
  24067. break;
  24068. default:
  24069. material.uniforms[ name ].value = uniform.value;
  24070. }
  24071. }
  24072. }
  24073. if ( json.defines !== undefined ) material.defines = json.defines;
  24074. if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
  24075. if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
  24076. if ( json.extensions !== undefined ) {
  24077. for ( const key in json.extensions ) {
  24078. material.extensions[ key ] = json.extensions[ key ];
  24079. }
  24080. }
  24081. // Deprecated
  24082. if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
  24083. // for PointsMaterial
  24084. if ( json.size !== undefined ) material.size = json.size;
  24085. if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
  24086. // maps
  24087. if ( json.map !== undefined ) material.map = getTexture( json.map );
  24088. if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
  24089. if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
  24090. if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
  24091. if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
  24092. if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
  24093. if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
  24094. if ( json.normalScale !== undefined ) {
  24095. let normalScale = json.normalScale;
  24096. if ( Array.isArray( normalScale ) === false ) {
  24097. // Blender exporter used to export a scalar. See #7459
  24098. normalScale = [ normalScale, normalScale ];
  24099. }
  24100. material.normalScale = new Vector2().fromArray( normalScale );
  24101. }
  24102. if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
  24103. if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
  24104. if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
  24105. if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
  24106. if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
  24107. if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
  24108. if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
  24109. if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
  24110. if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
  24111. if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
  24112. if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
  24113. if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
  24114. if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
  24115. if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
  24116. if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
  24117. if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
  24118. if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
  24119. if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
  24120. if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
  24121. if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
  24122. if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
  24123. if ( json.transmission !== undefined ) material.transmission = json.transmission;
  24124. if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
  24125. return material;
  24126. },
  24127. setTextures: function ( value ) {
  24128. this.textures = value;
  24129. return this;
  24130. }
  24131. } );
  24132. const LoaderUtils = {
  24133. decodeText: function ( array ) {
  24134. if ( typeof TextDecoder !== 'undefined' ) {
  24135. return new TextDecoder().decode( array );
  24136. }
  24137. // Avoid the String.fromCharCode.apply(null, array) shortcut, which
  24138. // throws a "maximum call stack size exceeded" error for large arrays.
  24139. let s = '';
  24140. for ( let i = 0, il = array.length; i < il; i ++ ) {
  24141. // Implicitly assumes little-endian.
  24142. s += String.fromCharCode( array[ i ] );
  24143. }
  24144. try {
  24145. // merges multi-byte utf-8 characters.
  24146. return decodeURIComponent( escape( s ) );
  24147. } catch ( e ) { // see #16358
  24148. return s;
  24149. }
  24150. },
  24151. extractUrlBase: function ( url ) {
  24152. const index = url.lastIndexOf( '/' );
  24153. if ( index === - 1 ) return './';
  24154. return url.substr( 0, index + 1 );
  24155. }
  24156. };
  24157. function InstancedBufferGeometry() {
  24158. BufferGeometry.call( this );
  24159. this.type = 'InstancedBufferGeometry';
  24160. this.instanceCount = Infinity;
  24161. }
  24162. InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
  24163. constructor: InstancedBufferGeometry,
  24164. isInstancedBufferGeometry: true,
  24165. copy: function ( source ) {
  24166. BufferGeometry.prototype.copy.call( this, source );
  24167. this.instanceCount = source.instanceCount;
  24168. return this;
  24169. },
  24170. clone: function () {
  24171. return new this.constructor().copy( this );
  24172. },
  24173. toJSON: function () {
  24174. const data = BufferGeometry.prototype.toJSON.call( this );
  24175. data.instanceCount = this.instanceCount;
  24176. data.isInstancedBufferGeometry = true;
  24177. return data;
  24178. }
  24179. } );
  24180. function InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {
  24181. if ( typeof ( normalized ) === 'number' ) {
  24182. meshPerAttribute = normalized;
  24183. normalized = false;
  24184. console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );
  24185. }
  24186. BufferAttribute.call( this, array, itemSize, normalized );
  24187. this.meshPerAttribute = meshPerAttribute || 1;
  24188. }
  24189. InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
  24190. constructor: InstancedBufferAttribute,
  24191. isInstancedBufferAttribute: true,
  24192. copy: function ( source ) {
  24193. BufferAttribute.prototype.copy.call( this, source );
  24194. this.meshPerAttribute = source.meshPerAttribute;
  24195. return this;
  24196. },
  24197. toJSON: function () {
  24198. const data = BufferAttribute.prototype.toJSON.call( this );
  24199. data.meshPerAttribute = this.meshPerAttribute;
  24200. data.isInstancedBufferAttribute = true;
  24201. return data;
  24202. }
  24203. } );
  24204. function BufferGeometryLoader( manager ) {
  24205. Loader.call( this, manager );
  24206. }
  24207. BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  24208. constructor: BufferGeometryLoader,
  24209. load: function ( url, onLoad, onProgress, onError ) {
  24210. const scope = this;
  24211. const loader = new FileLoader( scope.manager );
  24212. loader.setPath( scope.path );
  24213. loader.setRequestHeader( scope.requestHeader );
  24214. loader.setWithCredentials( scope.withCredentials );
  24215. loader.load( url, function ( text ) {
  24216. try {
  24217. onLoad( scope.parse( JSON.parse( text ) ) );
  24218. } catch ( e ) {
  24219. if ( onError ) {
  24220. onError( e );
  24221. } else {
  24222. console.error( e );
  24223. }
  24224. scope.manager.itemError( url );
  24225. }
  24226. }, onProgress, onError );
  24227. },
  24228. parse: function ( json ) {
  24229. const interleavedBufferMap = {};
  24230. const arrayBufferMap = {};
  24231. function getInterleavedBuffer( json, uuid ) {
  24232. if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
  24233. const interleavedBuffers = json.interleavedBuffers;
  24234. const interleavedBuffer = interleavedBuffers[ uuid ];
  24235. const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
  24236. const array = getTypedArray( interleavedBuffer.type, buffer );
  24237. const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
  24238. ib.uuid = interleavedBuffer.uuid;
  24239. interleavedBufferMap[ uuid ] = ib;
  24240. return ib;
  24241. }
  24242. function getArrayBuffer( json, uuid ) {
  24243. if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
  24244. const arrayBuffers = json.arrayBuffers;
  24245. const arrayBuffer = arrayBuffers[ uuid ];
  24246. const ab = new Uint32Array( arrayBuffer ).buffer;
  24247. arrayBufferMap[ uuid ] = ab;
  24248. return ab;
  24249. }
  24250. const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
  24251. const index = json.data.index;
  24252. if ( index !== undefined ) {
  24253. const typedArray = getTypedArray( index.type, index.array );
  24254. geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
  24255. }
  24256. const attributes = json.data.attributes;
  24257. for ( const key in attributes ) {
  24258. const attribute = attributes[ key ];
  24259. let bufferAttribute;
  24260. if ( attribute.isInterleavedBufferAttribute ) {
  24261. const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
  24262. bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
  24263. } else {
  24264. const typedArray = getTypedArray( attribute.type, attribute.array );
  24265. const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
  24266. bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
  24267. }
  24268. if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
  24269. geometry.setAttribute( key, bufferAttribute );
  24270. }
  24271. const morphAttributes = json.data.morphAttributes;
  24272. if ( morphAttributes ) {
  24273. for ( const key in morphAttributes ) {
  24274. const attributeArray = morphAttributes[ key ];
  24275. const array = [];
  24276. for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
  24277. const attribute = attributeArray[ i ];
  24278. let bufferAttribute;
  24279. if ( attribute.isInterleavedBufferAttribute ) {
  24280. const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
  24281. bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
  24282. } else {
  24283. const typedArray = getTypedArray( attribute.type, attribute.array );
  24284. bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
  24285. }
  24286. if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
  24287. array.push( bufferAttribute );
  24288. }
  24289. geometry.morphAttributes[ key ] = array;
  24290. }
  24291. }
  24292. const morphTargetsRelative = json.data.morphTargetsRelative;
  24293. if ( morphTargetsRelative ) {
  24294. geometry.morphTargetsRelative = true;
  24295. }
  24296. const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
  24297. if ( groups !== undefined ) {
  24298. for ( let i = 0, n = groups.length; i !== n; ++ i ) {
  24299. const group = groups[ i ];
  24300. geometry.addGroup( group.start, group.count, group.materialIndex );
  24301. }
  24302. }
  24303. const boundingSphere = json.data.boundingSphere;
  24304. if ( boundingSphere !== undefined ) {
  24305. const center = new Vector3();
  24306. if ( boundingSphere.center !== undefined ) {
  24307. center.fromArray( boundingSphere.center );
  24308. }
  24309. geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
  24310. }
  24311. if ( json.name ) geometry.name = json.name;
  24312. if ( json.userData ) geometry.userData = json.userData;
  24313. return geometry;
  24314. }
  24315. } );
  24316. class ObjectLoader extends Loader {
  24317. constructor( manager ) {
  24318. super( manager );
  24319. }
  24320. load( url, onLoad, onProgress, onError ) {
  24321. const scope = this;
  24322. const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
  24323. this.resourcePath = this.resourcePath || path;
  24324. const loader = new FileLoader( this.manager );
  24325. loader.setPath( this.path );
  24326. loader.setRequestHeader( this.requestHeader );
  24327. loader.setWithCredentials( this.withCredentials );
  24328. loader.load( url, function ( text ) {
  24329. let json = null;
  24330. try {
  24331. json = JSON.parse( text );
  24332. } catch ( error ) {
  24333. if ( onError !== undefined ) onError( error );
  24334. console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
  24335. return;
  24336. }
  24337. const metadata = json.metadata;
  24338. if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
  24339. console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
  24340. return;
  24341. }
  24342. scope.parse( json, onLoad );
  24343. }, onProgress, onError );
  24344. }
  24345. parse( json, onLoad ) {
  24346. const animations = this.parseAnimations( json.animations );
  24347. const shapes = this.parseShapes( json.shapes );
  24348. const geometries = this.parseGeometries( json.geometries, shapes );
  24349. const images = this.parseImages( json.images, function () {
  24350. if ( onLoad !== undefined ) onLoad( object );
  24351. } );
  24352. const textures = this.parseTextures( json.textures, images );
  24353. const materials = this.parseMaterials( json.materials, textures );
  24354. const object = this.parseObject( json.object, geometries, materials, animations );
  24355. const skeletons = this.parseSkeletons( json.skeletons, object );
  24356. this.bindSkeletons( object, skeletons );
  24357. //
  24358. if ( onLoad !== undefined ) {
  24359. let hasImages = false;
  24360. for ( const uuid in images ) {
  24361. if ( images[ uuid ] instanceof HTMLImageElement ) {
  24362. hasImages = true;
  24363. break;
  24364. }
  24365. }
  24366. if ( hasImages === false ) onLoad( object );
  24367. }
  24368. return object;
  24369. }
  24370. parseShapes( json ) {
  24371. const shapes = {};
  24372. if ( json !== undefined ) {
  24373. for ( let i = 0, l = json.length; i < l; i ++ ) {
  24374. const shape = new Shape().fromJSON( json[ i ] );
  24375. shapes[ shape.uuid ] = shape;
  24376. }
  24377. }
  24378. return shapes;
  24379. }
  24380. parseSkeletons( json, object ) {
  24381. const skeletons = {};
  24382. const bones = {};
  24383. // generate bone lookup table
  24384. object.traverse( function ( child ) {
  24385. if ( child.isBone ) bones[ child.uuid ] = child;
  24386. } );
  24387. // create skeletons
  24388. if ( json !== undefined ) {
  24389. for ( let i = 0, l = json.length; i < l; i ++ ) {
  24390. const skeleton = new Skeleton().fromJSON( json[ i ], bones );
  24391. skeletons[ skeleton.uuid ] = skeleton;
  24392. }
  24393. }
  24394. return skeletons;
  24395. }
  24396. parseGeometries( json, shapes ) {
  24397. const geometries = {};
  24398. let geometryShapes;
  24399. if ( json !== undefined ) {
  24400. const bufferGeometryLoader = new BufferGeometryLoader();
  24401. for ( let i = 0, l = json.length; i < l; i ++ ) {
  24402. let geometry;
  24403. const data = json[ i ];
  24404. switch ( data.type ) {
  24405. case 'PlaneGeometry':
  24406. case 'PlaneBufferGeometry':
  24407. geometry = new Geometries[ data.type ](
  24408. data.width,
  24409. data.height,
  24410. data.widthSegments,
  24411. data.heightSegments
  24412. );
  24413. break;
  24414. case 'BoxGeometry':
  24415. case 'BoxBufferGeometry':
  24416. case 'CubeGeometry': // backwards compatible
  24417. geometry = new Geometries[ data.type ](
  24418. data.width,
  24419. data.height,
  24420. data.depth,
  24421. data.widthSegments,
  24422. data.heightSegments,
  24423. data.depthSegments
  24424. );
  24425. break;
  24426. case 'CircleGeometry':
  24427. case 'CircleBufferGeometry':
  24428. geometry = new Geometries[ data.type ](
  24429. data.radius,
  24430. data.segments,
  24431. data.thetaStart,
  24432. data.thetaLength
  24433. );
  24434. break;
  24435. case 'CylinderGeometry':
  24436. case 'CylinderBufferGeometry':
  24437. geometry = new Geometries[ data.type ](
  24438. data.radiusTop,
  24439. data.radiusBottom,
  24440. data.height,
  24441. data.radialSegments,
  24442. data.heightSegments,
  24443. data.openEnded,
  24444. data.thetaStart,
  24445. data.thetaLength
  24446. );
  24447. break;
  24448. case 'ConeGeometry':
  24449. case 'ConeBufferGeometry':
  24450. geometry = new Geometries[ data.type ](
  24451. data.radius,
  24452. data.height,
  24453. data.radialSegments,
  24454. data.heightSegments,
  24455. data.openEnded,
  24456. data.thetaStart,
  24457. data.thetaLength
  24458. );
  24459. break;
  24460. case 'SphereGeometry':
  24461. case 'SphereBufferGeometry':
  24462. geometry = new Geometries[ data.type ](
  24463. data.radius,
  24464. data.widthSegments,
  24465. data.heightSegments,
  24466. data.phiStart,
  24467. data.phiLength,
  24468. data.thetaStart,
  24469. data.thetaLength
  24470. );
  24471. break;
  24472. case 'DodecahedronGeometry':
  24473. case 'DodecahedronBufferGeometry':
  24474. case 'IcosahedronGeometry':
  24475. case 'IcosahedronBufferGeometry':
  24476. case 'OctahedronGeometry':
  24477. case 'OctahedronBufferGeometry':
  24478. case 'TetrahedronGeometry':
  24479. case 'TetrahedronBufferGeometry':
  24480. geometry = new Geometries[ data.type ](
  24481. data.radius,
  24482. data.detail
  24483. );
  24484. break;
  24485. case 'RingGeometry':
  24486. case 'RingBufferGeometry':
  24487. geometry = new Geometries[ data.type ](
  24488. data.innerRadius,
  24489. data.outerRadius,
  24490. data.thetaSegments,
  24491. data.phiSegments,
  24492. data.thetaStart,
  24493. data.thetaLength
  24494. );
  24495. break;
  24496. case 'TorusGeometry':
  24497. case 'TorusBufferGeometry':
  24498. geometry = new Geometries[ data.type ](
  24499. data.radius,
  24500. data.tube,
  24501. data.radialSegments,
  24502. data.tubularSegments,
  24503. data.arc
  24504. );
  24505. break;
  24506. case 'TorusKnotGeometry':
  24507. case 'TorusKnotBufferGeometry':
  24508. geometry = new Geometries[ data.type ](
  24509. data.radius,
  24510. data.tube,
  24511. data.tubularSegments,
  24512. data.radialSegments,
  24513. data.p,
  24514. data.q
  24515. );
  24516. break;
  24517. case 'TubeGeometry':
  24518. case 'TubeBufferGeometry':
  24519. // This only works for built-in curves (e.g. CatmullRomCurve3).
  24520. // User defined curves or instances of CurvePath will not be deserialized.
  24521. geometry = new Geometries[ data.type ](
  24522. new Curves[ data.path.type ]().fromJSON( data.path ),
  24523. data.tubularSegments,
  24524. data.radius,
  24525. data.radialSegments,
  24526. data.closed
  24527. );
  24528. break;
  24529. case 'LatheGeometry':
  24530. case 'LatheBufferGeometry':
  24531. geometry = new Geometries[ data.type ](
  24532. data.points,
  24533. data.segments,
  24534. data.phiStart,
  24535. data.phiLength
  24536. );
  24537. break;
  24538. case 'PolyhedronGeometry':
  24539. case 'PolyhedronBufferGeometry':
  24540. geometry = new Geometries[ data.type ](
  24541. data.vertices,
  24542. data.indices,
  24543. data.radius,
  24544. data.details
  24545. );
  24546. break;
  24547. case 'ShapeGeometry':
  24548. case 'ShapeBufferGeometry':
  24549. geometryShapes = [];
  24550. for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
  24551. const shape = shapes[ data.shapes[ j ] ];
  24552. geometryShapes.push( shape );
  24553. }
  24554. geometry = new Geometries[ data.type ](
  24555. geometryShapes,
  24556. data.curveSegments
  24557. );
  24558. break;
  24559. case 'ExtrudeGeometry':
  24560. case 'ExtrudeBufferGeometry':
  24561. geometryShapes = [];
  24562. for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
  24563. const shape = shapes[ data.shapes[ j ] ];
  24564. geometryShapes.push( shape );
  24565. }
  24566. const extrudePath = data.options.extrudePath;
  24567. if ( extrudePath !== undefined ) {
  24568. data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
  24569. }
  24570. geometry = new Geometries[ data.type ](
  24571. geometryShapes,
  24572. data.options
  24573. );
  24574. break;
  24575. case 'BufferGeometry':
  24576. case 'InstancedBufferGeometry':
  24577. geometry = bufferGeometryLoader.parse( data );
  24578. break;
  24579. case 'Geometry':
  24580. console.error( 'THREE.ObjectLoader: Loading "Geometry" is not supported anymore.' );
  24581. break;
  24582. default:
  24583. console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
  24584. continue;
  24585. }
  24586. geometry.uuid = data.uuid;
  24587. if ( data.name !== undefined ) geometry.name = data.name;
  24588. if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData;
  24589. geometries[ data.uuid ] = geometry;
  24590. }
  24591. }
  24592. return geometries;
  24593. }
  24594. parseMaterials( json, textures ) {
  24595. const cache = {}; // MultiMaterial
  24596. const materials = {};
  24597. if ( json !== undefined ) {
  24598. const loader = new MaterialLoader();
  24599. loader.setTextures( textures );
  24600. for ( let i = 0, l = json.length; i < l; i ++ ) {
  24601. const data = json[ i ];
  24602. if ( data.type === 'MultiMaterial' ) {
  24603. // Deprecated
  24604. const array = [];
  24605. for ( let j = 0; j < data.materials.length; j ++ ) {
  24606. const material = data.materials[ j ];
  24607. if ( cache[ material.uuid ] === undefined ) {
  24608. cache[ material.uuid ] = loader.parse( material );
  24609. }
  24610. array.push( cache[ material.uuid ] );
  24611. }
  24612. materials[ data.uuid ] = array;
  24613. } else {
  24614. if ( cache[ data.uuid ] === undefined ) {
  24615. cache[ data.uuid ] = loader.parse( data );
  24616. }
  24617. materials[ data.uuid ] = cache[ data.uuid ];
  24618. }
  24619. }
  24620. }
  24621. return materials;
  24622. }
  24623. parseAnimations( json ) {
  24624. const animations = {};
  24625. if ( json !== undefined ) {
  24626. for ( let i = 0; i < json.length; i ++ ) {
  24627. const data = json[ i ];
  24628. const clip = AnimationClip.parse( data );
  24629. animations[ clip.uuid ] = clip;
  24630. }
  24631. }
  24632. return animations;
  24633. }
  24634. parseImages( json, onLoad ) {
  24635. const scope = this;
  24636. const images = {};
  24637. let loader;
  24638. function loadImage( url ) {
  24639. scope.manager.itemStart( url );
  24640. return loader.load( url, function () {
  24641. scope.manager.itemEnd( url );
  24642. }, undefined, function () {
  24643. scope.manager.itemError( url );
  24644. scope.manager.itemEnd( url );
  24645. } );
  24646. }
  24647. function deserializeImage( image ) {
  24648. if ( typeof image === 'string' ) {
  24649. const url = image;
  24650. const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
  24651. return loadImage( path );
  24652. } else {
  24653. if ( image.data ) {
  24654. return {
  24655. data: getTypedArray( image.type, image.data ),
  24656. width: image.width,
  24657. height: image.height
  24658. };
  24659. } else {
  24660. return null;
  24661. }
  24662. }
  24663. }
  24664. if ( json !== undefined && json.length > 0 ) {
  24665. const manager = new LoadingManager( onLoad );
  24666. loader = new ImageLoader( manager );
  24667. loader.setCrossOrigin( this.crossOrigin );
  24668. for ( let i = 0, il = json.length; i < il; i ++ ) {
  24669. const image = json[ i ];
  24670. const url = image.url;
  24671. if ( Array.isArray( url ) ) {
  24672. // load array of images e.g CubeTexture
  24673. images[ image.uuid ] = [];
  24674. for ( let j = 0, jl = url.length; j < jl; j ++ ) {
  24675. const currentUrl = url[ j ];
  24676. const deserializedImage = deserializeImage( currentUrl );
  24677. if ( deserializedImage !== null ) {
  24678. if ( deserializedImage instanceof HTMLImageElement ) {
  24679. images[ image.uuid ].push( deserializedImage );
  24680. } else {
  24681. // special case: handle array of data textures for cube textures
  24682. images[ image.uuid ].push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
  24683. }
  24684. }
  24685. }
  24686. } else {
  24687. // load single image
  24688. const deserializedImage = deserializeImage( image.url );
  24689. if ( deserializedImage !== null ) {
  24690. images[ image.uuid ] = deserializedImage;
  24691. }
  24692. }
  24693. }
  24694. }
  24695. return images;
  24696. }
  24697. parseTextures( json, images ) {
  24698. function parseConstant( value, type ) {
  24699. if ( typeof value === 'number' ) return value;
  24700. console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
  24701. return type[ value ];
  24702. }
  24703. const textures = {};
  24704. if ( json !== undefined ) {
  24705. for ( let i = 0, l = json.length; i < l; i ++ ) {
  24706. const data = json[ i ];
  24707. if ( data.image === undefined ) {
  24708. console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
  24709. }
  24710. if ( images[ data.image ] === undefined ) {
  24711. console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
  24712. }
  24713. let texture;
  24714. const image = images[ data.image ];
  24715. if ( Array.isArray( image ) ) {
  24716. texture = new CubeTexture( image );
  24717. if ( image.length === 6 ) texture.needsUpdate = true;
  24718. } else {
  24719. if ( image && image.data ) {
  24720. texture = new DataTexture( image.data, image.width, image.height );
  24721. } else {
  24722. texture = new Texture( image );
  24723. }
  24724. if ( image ) texture.needsUpdate = true; // textures can have undefined image data
  24725. }
  24726. texture.uuid = data.uuid;
  24727. if ( data.name !== undefined ) texture.name = data.name;
  24728. if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
  24729. if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
  24730. if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
  24731. if ( data.center !== undefined ) texture.center.fromArray( data.center );
  24732. if ( data.rotation !== undefined ) texture.rotation = data.rotation;
  24733. if ( data.wrap !== undefined ) {
  24734. texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
  24735. texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
  24736. }
  24737. if ( data.format !== undefined ) texture.format = data.format;
  24738. if ( data.type !== undefined ) texture.type = data.type;
  24739. if ( data.encoding !== undefined ) texture.encoding = data.encoding;
  24740. if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
  24741. if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
  24742. if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
  24743. if ( data.flipY !== undefined ) texture.flipY = data.flipY;
  24744. if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
  24745. if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
  24746. textures[ data.uuid ] = texture;
  24747. }
  24748. }
  24749. return textures;
  24750. }
  24751. parseObject( data, geometries, materials, animations ) {
  24752. let object;
  24753. function getGeometry( name ) {
  24754. if ( geometries[ name ] === undefined ) {
  24755. console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
  24756. }
  24757. return geometries[ name ];
  24758. }
  24759. function getMaterial( name ) {
  24760. if ( name === undefined ) return undefined;
  24761. if ( Array.isArray( name ) ) {
  24762. const array = [];
  24763. for ( let i = 0, l = name.length; i < l; i ++ ) {
  24764. const uuid = name[ i ];
  24765. if ( materials[ uuid ] === undefined ) {
  24766. console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
  24767. }
  24768. array.push( materials[ uuid ] );
  24769. }
  24770. return array;
  24771. }
  24772. if ( materials[ name ] === undefined ) {
  24773. console.warn( 'THREE.ObjectLoader: Undefined material', name );
  24774. }
  24775. return materials[ name ];
  24776. }
  24777. let geometry, material;
  24778. switch ( data.type ) {
  24779. case 'Scene':
  24780. object = new Scene();
  24781. if ( data.background !== undefined ) {
  24782. if ( Number.isInteger( data.background ) ) {
  24783. object.background = new Color( data.background );
  24784. }
  24785. }
  24786. if ( data.fog !== undefined ) {
  24787. if ( data.fog.type === 'Fog' ) {
  24788. object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
  24789. } else if ( data.fog.type === 'FogExp2' ) {
  24790. object.fog = new FogExp2( data.fog.color, data.fog.density );
  24791. }
  24792. }
  24793. break;
  24794. case 'PerspectiveCamera':
  24795. object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
  24796. if ( data.focus !== undefined ) object.focus = data.focus;
  24797. if ( data.zoom !== undefined ) object.zoom = data.zoom;
  24798. if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
  24799. if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
  24800. if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
  24801. break;
  24802. case 'OrthographicCamera':
  24803. object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
  24804. if ( data.zoom !== undefined ) object.zoom = data.zoom;
  24805. if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
  24806. break;
  24807. case 'AmbientLight':
  24808. object = new AmbientLight( data.color, data.intensity );
  24809. break;
  24810. case 'DirectionalLight':
  24811. object = new DirectionalLight( data.color, data.intensity );
  24812. break;
  24813. case 'PointLight':
  24814. object = new PointLight( data.color, data.intensity, data.distance, data.decay );
  24815. break;
  24816. case 'RectAreaLight':
  24817. object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
  24818. break;
  24819. case 'SpotLight':
  24820. object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
  24821. break;
  24822. case 'HemisphereLight':
  24823. object = new HemisphereLight( data.color, data.groundColor, data.intensity );
  24824. break;
  24825. case 'LightProbe':
  24826. object = new LightProbe().fromJSON( data );
  24827. break;
  24828. case 'SkinnedMesh':
  24829. geometry = getGeometry( data.geometry );
  24830. material = getMaterial( data.material );
  24831. object = new SkinnedMesh( geometry, material );
  24832. if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
  24833. if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
  24834. if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
  24835. break;
  24836. case 'Mesh':
  24837. geometry = getGeometry( data.geometry );
  24838. material = getMaterial( data.material );
  24839. object = new Mesh( geometry, material );
  24840. break;
  24841. case 'InstancedMesh':
  24842. geometry = getGeometry( data.geometry );
  24843. material = getMaterial( data.material );
  24844. const count = data.count;
  24845. const instanceMatrix = data.instanceMatrix;
  24846. object = new InstancedMesh( geometry, material, count );
  24847. object.instanceMatrix = new BufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
  24848. break;
  24849. case 'LOD':
  24850. object = new LOD();
  24851. break;
  24852. case 'Line':
  24853. object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
  24854. break;
  24855. case 'LineLoop':
  24856. object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
  24857. break;
  24858. case 'LineSegments':
  24859. object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
  24860. break;
  24861. case 'PointCloud':
  24862. case 'Points':
  24863. object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
  24864. break;
  24865. case 'Sprite':
  24866. object = new Sprite$1( getMaterial( data.material ) );
  24867. break;
  24868. case 'Group':
  24869. object = new Group();
  24870. break;
  24871. case 'Bone':
  24872. object = new Bone();
  24873. break;
  24874. default:
  24875. object = new Object3D();
  24876. }
  24877. object.uuid = data.uuid;
  24878. if ( data.name !== undefined ) object.name = data.name;
  24879. if ( data.matrix !== undefined ) {
  24880. object.matrix.fromArray( data.matrix );
  24881. if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
  24882. if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
  24883. } else {
  24884. if ( data.position !== undefined ) object.position.fromArray( data.position );
  24885. if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
  24886. if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
  24887. if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
  24888. }
  24889. if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
  24890. if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
  24891. if ( data.shadow ) {
  24892. if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
  24893. if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
  24894. if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
  24895. if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
  24896. if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
  24897. }
  24898. if ( data.visible !== undefined ) object.visible = data.visible;
  24899. if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
  24900. if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
  24901. if ( data.userData !== undefined ) object.userData = data.userData;
  24902. if ( data.layers !== undefined ) object.layers.mask = data.layers;
  24903. if ( data.children !== undefined ) {
  24904. const children = data.children;
  24905. for ( let i = 0; i < children.length; i ++ ) {
  24906. object.add( this.parseObject( children[ i ], geometries, materials, animations ) );
  24907. }
  24908. }
  24909. if ( data.animations !== undefined ) {
  24910. const objectAnimations = data.animations;
  24911. for ( let i = 0; i < objectAnimations.length; i ++ ) {
  24912. const uuid = objectAnimations[ i ];
  24913. object.animations.push( animations[ uuid ] );
  24914. }
  24915. }
  24916. if ( data.type === 'LOD' ) {
  24917. if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
  24918. const levels = data.levels;
  24919. for ( let l = 0; l < levels.length; l ++ ) {
  24920. const level = levels[ l ];
  24921. const child = object.getObjectByProperty( 'uuid', level.object );
  24922. if ( child !== undefined ) {
  24923. object.addLevel( child, level.distance );
  24924. }
  24925. }
  24926. }
  24927. return object;
  24928. }
  24929. bindSkeletons( object, skeletons ) {
  24930. if ( Object.keys( skeletons ).length === 0 ) return;
  24931. object.traverse( function ( child ) {
  24932. if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
  24933. const skeleton = skeletons[ child.skeleton ];
  24934. if ( skeleton === undefined ) {
  24935. console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton );
  24936. } else {
  24937. child.bind( skeleton, child.bindMatrix );
  24938. }
  24939. }
  24940. } );
  24941. }
  24942. /* DEPRECATED */
  24943. setTexturePath( value ) {
  24944. console.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );
  24945. return this.setResourcePath( value );
  24946. }
  24947. }
  24948. const TEXTURE_MAPPING = {
  24949. UVMapping: UVMapping,
  24950. CubeReflectionMapping: CubeReflectionMapping,
  24951. CubeRefractionMapping: CubeRefractionMapping,
  24952. EquirectangularReflectionMapping: EquirectangularReflectionMapping,
  24953. EquirectangularRefractionMapping: EquirectangularRefractionMapping,
  24954. CubeUVReflectionMapping: CubeUVReflectionMapping,
  24955. CubeUVRefractionMapping: CubeUVRefractionMapping
  24956. };
  24957. const TEXTURE_WRAPPING = {
  24958. RepeatWrapping: RepeatWrapping,
  24959. ClampToEdgeWrapping: ClampToEdgeWrapping,
  24960. MirroredRepeatWrapping: MirroredRepeatWrapping
  24961. };
  24962. const TEXTURE_FILTER = {
  24963. NearestFilter: NearestFilter,
  24964. NearestMipmapNearestFilter: NearestMipmapNearestFilter,
  24965. NearestMipmapLinearFilter: NearestMipmapLinearFilter,
  24966. LinearFilter: LinearFilter,
  24967. LinearMipmapNearestFilter: LinearMipmapNearestFilter,
  24968. LinearMipmapLinearFilter: LinearMipmapLinearFilter
  24969. };
  24970. function ImageBitmapLoader( manager ) {
  24971. if ( typeof createImageBitmap === 'undefined' ) {
  24972. console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
  24973. }
  24974. if ( typeof fetch === 'undefined' ) {
  24975. console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
  24976. }
  24977. Loader.call( this, manager );
  24978. this.options = { premultiplyAlpha: 'none' };
  24979. }
  24980. ImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  24981. constructor: ImageBitmapLoader,
  24982. isImageBitmapLoader: true,
  24983. setOptions: function setOptions( options ) {
  24984. this.options = options;
  24985. return this;
  24986. },
  24987. load: function ( url, onLoad, onProgress, onError ) {
  24988. if ( url === undefined ) url = '';
  24989. if ( this.path !== undefined ) url = this.path + url;
  24990. url = this.manager.resolveURL( url );
  24991. const scope = this;
  24992. const cached = Cache.get( url );
  24993. if ( cached !== undefined ) {
  24994. scope.manager.itemStart( url );
  24995. setTimeout( function () {
  24996. if ( onLoad ) onLoad( cached );
  24997. scope.manager.itemEnd( url );
  24998. }, 0 );
  24999. return cached;
  25000. }
  25001. const fetchOptions = {};
  25002. fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
  25003. fetch( url, fetchOptions ).then( function ( res ) {
  25004. return res.blob();
  25005. } ).then( function ( blob ) {
  25006. //console.log('getBlob', url )
  25007. return createImageBitmap( blob, scope.options );
  25008. } ).then( function ( imageBitmap ) {
  25009. Cache.add( url, imageBitmap );
  25010. if ( onLoad ) onLoad( imageBitmap );
  25011. scope.manager.itemEnd( url );
  25012. } ).catch( function ( e ) {
  25013. //console.log('error', url, e)
  25014. if ( onError ) onError( e, url );
  25015. scope.manager.itemError( url );
  25016. scope.manager.itemEnd( url );
  25017. } );
  25018. scope.manager.itemStart( url );
  25019. }
  25020. } );
  25021. function ShapePath() {
  25022. this.type = 'ShapePath';
  25023. this.color = new Color();
  25024. this.subPaths = [];
  25025. this.currentPath = null;
  25026. }
  25027. Object.assign( ShapePath.prototype, {
  25028. moveTo: function ( x, y ) {
  25029. this.currentPath = new Path();
  25030. this.subPaths.push( this.currentPath );
  25031. this.currentPath.moveTo( x, y );
  25032. return this;
  25033. },
  25034. lineTo: function ( x, y ) {
  25035. this.currentPath.lineTo( x, y );
  25036. return this;
  25037. },
  25038. quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
  25039. this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
  25040. return this;
  25041. },
  25042. bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
  25043. this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
  25044. return this;
  25045. },
  25046. splineThru: function ( pts ) {
  25047. this.currentPath.splineThru( pts );
  25048. return this;
  25049. },
  25050. toShapes: function ( isCCW, noHoles ) {
  25051. function toShapesNoHoles( inSubpaths ) {
  25052. const shapes = [];
  25053. for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
  25054. const tmpPath = inSubpaths[ i ];
  25055. const tmpShape = new Shape();
  25056. tmpShape.curves = tmpPath.curves;
  25057. shapes.push( tmpShape );
  25058. }
  25059. return shapes;
  25060. }
  25061. function isPointInsidePolygon( inPt, inPolygon ) {
  25062. const polyLen = inPolygon.length;
  25063. // inPt on polygon contour => immediate success or
  25064. // toggling of inside/outside at every single! intersection point of an edge
  25065. // with the horizontal line through inPt, left of inPt
  25066. // not counting lowerY endpoints of edges and whole edges on that line
  25067. let inside = false;
  25068. for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
  25069. let edgeLowPt = inPolygon[ p ];
  25070. let edgeHighPt = inPolygon[ q ];
  25071. let edgeDx = edgeHighPt.x - edgeLowPt.x;
  25072. let edgeDy = edgeHighPt.y - edgeLowPt.y;
  25073. if ( Math.abs( edgeDy ) > Number.EPSILON ) {
  25074. // not parallel
  25075. if ( edgeDy < 0 ) {
  25076. edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
  25077. edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
  25078. }
  25079. if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
  25080. if ( inPt.y === edgeLowPt.y ) {
  25081. if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ?
  25082. // continue; // no intersection or edgeLowPt => doesn't count !!!
  25083. } else {
  25084. const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
  25085. if ( perpEdge === 0 ) return true; // inPt is on contour ?
  25086. if ( perpEdge < 0 ) continue;
  25087. inside = ! inside; // true intersection left of inPt
  25088. }
  25089. } else {
  25090. // parallel or collinear
  25091. if ( inPt.y !== edgeLowPt.y ) continue; // parallel
  25092. // edge lies on the same horizontal line as inPt
  25093. if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
  25094. ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
  25095. // continue;
  25096. }
  25097. }
  25098. return inside;
  25099. }
  25100. const isClockWise = ShapeUtils.isClockWise;
  25101. const subPaths = this.subPaths;
  25102. if ( subPaths.length === 0 ) return [];
  25103. if ( noHoles === true ) return toShapesNoHoles( subPaths );
  25104. let solid, tmpPath, tmpShape;
  25105. const shapes = [];
  25106. if ( subPaths.length === 1 ) {
  25107. tmpPath = subPaths[ 0 ];
  25108. tmpShape = new Shape();
  25109. tmpShape.curves = tmpPath.curves;
  25110. shapes.push( tmpShape );
  25111. return shapes;
  25112. }
  25113. let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
  25114. holesFirst = isCCW ? ! holesFirst : holesFirst;
  25115. // console.log("Holes first", holesFirst);
  25116. const betterShapeHoles = [];
  25117. const newShapes = [];
  25118. let newShapeHoles = [];
  25119. let mainIdx = 0;
  25120. let tmpPoints;
  25121. newShapes[ mainIdx ] = undefined;
  25122. newShapeHoles[ mainIdx ] = [];
  25123. for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
  25124. tmpPath = subPaths[ i ];
  25125. tmpPoints = tmpPath.getPoints();
  25126. solid = isClockWise( tmpPoints );
  25127. solid = isCCW ? ! solid : solid;
  25128. if ( solid ) {
  25129. if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++;
  25130. newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
  25131. newShapes[ mainIdx ].s.curves = tmpPath.curves;
  25132. if ( holesFirst ) mainIdx ++;
  25133. newShapeHoles[ mainIdx ] = [];
  25134. //console.log('cw', i);
  25135. } else {
  25136. newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
  25137. //console.log('ccw', i);
  25138. }
  25139. }
  25140. // only Holes? -> probably all Shapes with wrong orientation
  25141. if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths );
  25142. if ( newShapes.length > 1 ) {
  25143. let ambiguous = false;
  25144. const toChange = [];
  25145. for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
  25146. betterShapeHoles[ sIdx ] = [];
  25147. }
  25148. for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
  25149. const sho = newShapeHoles[ sIdx ];
  25150. for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
  25151. const ho = sho[ hIdx ];
  25152. let hole_unassigned = true;
  25153. for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
  25154. if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
  25155. if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
  25156. if ( hole_unassigned ) {
  25157. hole_unassigned = false;
  25158. betterShapeHoles[ s2Idx ].push( ho );
  25159. } else {
  25160. ambiguous = true;
  25161. }
  25162. }
  25163. }
  25164. if ( hole_unassigned ) {
  25165. betterShapeHoles[ sIdx ].push( ho );
  25166. }
  25167. }
  25168. }
  25169. // console.log("ambiguous: ", ambiguous);
  25170. if ( toChange.length > 0 ) {
  25171. // console.log("to change: ", toChange);
  25172. if ( ! ambiguous ) newShapeHoles = betterShapeHoles;
  25173. }
  25174. }
  25175. let tmpHoles;
  25176. for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
  25177. tmpShape = newShapes[ i ].s;
  25178. shapes.push( tmpShape );
  25179. tmpHoles = newShapeHoles[ i ];
  25180. for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
  25181. tmpShape.holes.push( tmpHoles[ j ].h );
  25182. }
  25183. }
  25184. //console.log("shape", shapes);
  25185. return shapes;
  25186. }
  25187. } );
  25188. function Font( data ) {
  25189. this.type = 'Font';
  25190. this.data = data;
  25191. }
  25192. Object.assign( Font.prototype, {
  25193. isFont: true,
  25194. generateShapes: function ( text, size = 100 ) {
  25195. const shapes = [];
  25196. const paths = createPaths( text, size, this.data );
  25197. for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
  25198. Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
  25199. }
  25200. return shapes;
  25201. }
  25202. } );
  25203. function createPaths( text, size, data ) {
  25204. const chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // workaround for IE11, see #13988
  25205. const scale = size / data.resolution;
  25206. const line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
  25207. const paths = [];
  25208. let offsetX = 0, offsetY = 0;
  25209. for ( let i = 0; i < chars.length; i ++ ) {
  25210. const char = chars[ i ];
  25211. if ( char === '\n' ) {
  25212. offsetX = 0;
  25213. offsetY -= line_height;
  25214. } else {
  25215. const ret = createPath( char, scale, offsetX, offsetY, data );
  25216. offsetX += ret.offsetX;
  25217. paths.push( ret.path );
  25218. }
  25219. }
  25220. return paths;
  25221. }
  25222. function createPath( char, scale, offsetX, offsetY, data ) {
  25223. const glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
  25224. if ( ! glyph ) {
  25225. console.error( 'THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.' );
  25226. return;
  25227. }
  25228. const path = new ShapePath();
  25229. let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
  25230. if ( glyph.o ) {
  25231. const outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
  25232. for ( let i = 0, l = outline.length; i < l; ) {
  25233. const action = outline[ i ++ ];
  25234. switch ( action ) {
  25235. case 'm': // moveTo
  25236. x = outline[ i ++ ] * scale + offsetX;
  25237. y = outline[ i ++ ] * scale + offsetY;
  25238. path.moveTo( x, y );
  25239. break;
  25240. case 'l': // lineTo
  25241. x = outline[ i ++ ] * scale + offsetX;
  25242. y = outline[ i ++ ] * scale + offsetY;
  25243. path.lineTo( x, y );
  25244. break;
  25245. case 'q': // quadraticCurveTo
  25246. cpx = outline[ i ++ ] * scale + offsetX;
  25247. cpy = outline[ i ++ ] * scale + offsetY;
  25248. cpx1 = outline[ i ++ ] * scale + offsetX;
  25249. cpy1 = outline[ i ++ ] * scale + offsetY;
  25250. path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
  25251. break;
  25252. case 'b': // bezierCurveTo
  25253. cpx = outline[ i ++ ] * scale + offsetX;
  25254. cpy = outline[ i ++ ] * scale + offsetY;
  25255. cpx1 = outline[ i ++ ] * scale + offsetX;
  25256. cpy1 = outline[ i ++ ] * scale + offsetY;
  25257. cpx2 = outline[ i ++ ] * scale + offsetX;
  25258. cpy2 = outline[ i ++ ] * scale + offsetY;
  25259. path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
  25260. break;
  25261. }
  25262. }
  25263. }
  25264. return { offsetX: glyph.ha * scale, path: path };
  25265. }
  25266. function FontLoader( manager ) {
  25267. Loader.call( this, manager );
  25268. }
  25269. FontLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  25270. constructor: FontLoader,
  25271. load: function ( url, onLoad, onProgress, onError ) {
  25272. const scope = this;
  25273. const loader = new FileLoader( this.manager );
  25274. loader.setPath( this.path );
  25275. loader.setRequestHeader( this.requestHeader );
  25276. loader.setWithCredentials( scope.withCredentials );
  25277. loader.load( url, function ( text ) {
  25278. let json;
  25279. try {
  25280. json = JSON.parse( text );
  25281. } catch ( e ) {
  25282. console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
  25283. json = JSON.parse( text.substring( 65, text.length - 2 ) );
  25284. }
  25285. const font = scope.parse( json );
  25286. if ( onLoad ) onLoad( font );
  25287. }, onProgress, onError );
  25288. },
  25289. parse: function ( json ) {
  25290. return new Font( json );
  25291. }
  25292. } );
  25293. let _context;
  25294. const AudioContext = {
  25295. getContext: function () {
  25296. if ( _context === undefined ) {
  25297. _context = new ( window.AudioContext || window.webkitAudioContext )();
  25298. }
  25299. return _context;
  25300. },
  25301. setContext: function ( value ) {
  25302. _context = value;
  25303. }
  25304. };
  25305. function AudioLoader( manager ) {
  25306. Loader.call( this, manager );
  25307. }
  25308. AudioLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  25309. constructor: AudioLoader,
  25310. load: function ( url, onLoad, onProgress, onError ) {
  25311. const scope = this;
  25312. const loader = new FileLoader( scope.manager );
  25313. loader.setResponseType( 'arraybuffer' );
  25314. loader.setPath( scope.path );
  25315. loader.setRequestHeader( scope.requestHeader );
  25316. loader.setWithCredentials( scope.withCredentials );
  25317. loader.load( url, function ( buffer ) {
  25318. try {
  25319. // Create a copy of the buffer. The `decodeAudioData` method
  25320. // detaches the buffer when complete, preventing reuse.
  25321. const bufferCopy = buffer.slice( 0 );
  25322. const context = AudioContext.getContext();
  25323. context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
  25324. onLoad( audioBuffer );
  25325. } );
  25326. } catch ( e ) {
  25327. if ( onError ) {
  25328. onError( e );
  25329. } else {
  25330. console.error( e );
  25331. }
  25332. scope.manager.itemError( url );
  25333. }
  25334. }, onProgress, onError );
  25335. }
  25336. } );
  25337. function HemisphereLightProbe( skyColor, groundColor, intensity ) {
  25338. LightProbe.call( this, undefined, intensity );
  25339. const color1 = new Color().set( skyColor );
  25340. const color2 = new Color().set( groundColor );
  25341. const sky = new Vector3( color1.r, color1.g, color1.b );
  25342. const ground = new Vector3( color2.r, color2.g, color2.b );
  25343. // without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
  25344. const c0 = Math.sqrt( Math.PI );
  25345. const c1 = c0 * Math.sqrt( 0.75 );
  25346. this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
  25347. this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
  25348. }
  25349. HemisphereLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
  25350. constructor: HemisphereLightProbe,
  25351. isHemisphereLightProbe: true,
  25352. copy: function ( source ) { // modifying colors not currently supported
  25353. LightProbe.prototype.copy.call( this, source );
  25354. return this;
  25355. },
  25356. toJSON: function ( meta ) {
  25357. const data = LightProbe.prototype.toJSON.call( this, meta );
  25358. // data.sh = this.sh.toArray(); // todo
  25359. return data;
  25360. }
  25361. } );
  25362. function AmbientLightProbe( color, intensity ) {
  25363. LightProbe.call( this, undefined, intensity );
  25364. const color1 = new Color().set( color );
  25365. // without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
  25366. this.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
  25367. }
  25368. AmbientLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
  25369. constructor: AmbientLightProbe,
  25370. isAmbientLightProbe: true,
  25371. copy: function ( source ) { // modifying color not currently supported
  25372. LightProbe.prototype.copy.call( this, source );
  25373. return this;
  25374. },
  25375. toJSON: function ( meta ) {
  25376. const data = LightProbe.prototype.toJSON.call( this, meta );
  25377. // data.sh = this.sh.toArray(); // todo
  25378. return data;
  25379. }
  25380. } );
  25381. const _eyeRight = new Matrix4();
  25382. const _eyeLeft = new Matrix4();
  25383. function StereoCamera() {
  25384. this.type = 'StereoCamera';
  25385. this.aspect = 1;
  25386. this.eyeSep = 0.064;
  25387. this.cameraL = new PerspectiveCamera();
  25388. this.cameraL.layers.enable( 1 );
  25389. this.cameraL.matrixAutoUpdate = false;
  25390. this.cameraR = new PerspectiveCamera();
  25391. this.cameraR.layers.enable( 2 );
  25392. this.cameraR.matrixAutoUpdate = false;
  25393. this._cache = {
  25394. focus: null,
  25395. fov: null,
  25396. aspect: null,
  25397. near: null,
  25398. far: null,
  25399. zoom: null,
  25400. eyeSep: null
  25401. };
  25402. }
  25403. Object.assign( StereoCamera.prototype, {
  25404. update: function ( camera ) {
  25405. const cache = this._cache;
  25406. const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
  25407. cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
  25408. cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
  25409. if ( needsUpdate ) {
  25410. cache.focus = camera.focus;
  25411. cache.fov = camera.fov;
  25412. cache.aspect = camera.aspect * this.aspect;
  25413. cache.near = camera.near;
  25414. cache.far = camera.far;
  25415. cache.zoom = camera.zoom;
  25416. cache.eyeSep = this.eyeSep;
  25417. // Off-axis stereoscopic effect based on
  25418. // http://paulbourke.net/stereographics/stereorender/
  25419. const projectionMatrix = camera.projectionMatrix.clone();
  25420. const eyeSepHalf = cache.eyeSep / 2;
  25421. const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
  25422. const ymax = ( cache.near * Math.tan( MathUtils$1.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
  25423. let xmin, xmax;
  25424. // translate xOffset
  25425. _eyeLeft.elements[ 12 ] = - eyeSepHalf;
  25426. _eyeRight.elements[ 12 ] = eyeSepHalf;
  25427. // for left eye
  25428. xmin = - ymax * cache.aspect + eyeSepOnProjection;
  25429. xmax = ymax * cache.aspect + eyeSepOnProjection;
  25430. projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
  25431. projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
  25432. this.cameraL.projectionMatrix.copy( projectionMatrix );
  25433. // for right eye
  25434. xmin = - ymax * cache.aspect - eyeSepOnProjection;
  25435. xmax = ymax * cache.aspect - eyeSepOnProjection;
  25436. projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
  25437. projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
  25438. this.cameraR.projectionMatrix.copy( projectionMatrix );
  25439. }
  25440. this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
  25441. this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
  25442. }
  25443. } );
  25444. class Clock {
  25445. constructor( autoStart ) {
  25446. this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
  25447. this.startTime = 0;
  25448. this.oldTime = 0;
  25449. this.elapsedTime = 0;
  25450. this.running = false;
  25451. }
  25452. start() {
  25453. this.startTime = now();
  25454. this.oldTime = this.startTime;
  25455. this.elapsedTime = 0;
  25456. this.running = true;
  25457. }
  25458. stop() {
  25459. this.getElapsedTime();
  25460. this.running = false;
  25461. this.autoStart = false;
  25462. }
  25463. getElapsedTime() {
  25464. this.getDelta();
  25465. return this.elapsedTime;
  25466. }
  25467. getDelta() {
  25468. let diff = 0;
  25469. if ( this.autoStart && ! this.running ) {
  25470. this.start();
  25471. return 0;
  25472. }
  25473. if ( this.running ) {
  25474. const newTime = now();
  25475. diff = ( newTime - this.oldTime ) / 1000;
  25476. this.oldTime = newTime;
  25477. this.elapsedTime += diff;
  25478. }
  25479. return diff;
  25480. }
  25481. }
  25482. function now() {
  25483. return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
  25484. }
  25485. const _position$2 = /*@__PURE__*/ new Vector3();
  25486. const _quaternion$3 = /*@__PURE__*/ new Quaternion();
  25487. const _scale$1 = /*@__PURE__*/ new Vector3();
  25488. const _orientation = /*@__PURE__*/ new Vector3();
  25489. class AudioListener extends Object3D {
  25490. constructor() {
  25491. super();
  25492. this.type = 'AudioListener';
  25493. this.context = AudioContext.getContext();
  25494. this.gain = this.context.createGain();
  25495. this.gain.connect( this.context.destination );
  25496. this.filter = null;
  25497. this.timeDelta = 0;
  25498. // private
  25499. this._clock = new Clock();
  25500. }
  25501. getInput() {
  25502. return this.gain;
  25503. }
  25504. removeFilter() {
  25505. if ( this.filter !== null ) {
  25506. this.gain.disconnect( this.filter );
  25507. this.filter.disconnect( this.context.destination );
  25508. this.gain.connect( this.context.destination );
  25509. this.filter = null;
  25510. }
  25511. return this;
  25512. }
  25513. getFilter() {
  25514. return this.filter;
  25515. }
  25516. setFilter( value ) {
  25517. if ( this.filter !== null ) {
  25518. this.gain.disconnect( this.filter );
  25519. this.filter.disconnect( this.context.destination );
  25520. } else {
  25521. this.gain.disconnect( this.context.destination );
  25522. }
  25523. this.filter = value;
  25524. this.gain.connect( this.filter );
  25525. this.filter.connect( this.context.destination );
  25526. return this;
  25527. }
  25528. getMasterVolume() {
  25529. return this.gain.gain.value;
  25530. }
  25531. setMasterVolume( value ) {
  25532. this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
  25533. return this;
  25534. }
  25535. updateMatrixWorld( force ) {
  25536. super.updateMatrixWorld( force );
  25537. const listener = this.context.listener;
  25538. const up = this.up;
  25539. this.timeDelta = this._clock.getDelta();
  25540. this.matrixWorld.decompose( _position$2, _quaternion$3, _scale$1 );
  25541. _orientation.set( 0, 0, - 1 ).applyQuaternion( _quaternion$3 );
  25542. if ( listener.positionX ) {
  25543. // code path for Chrome (see #14393)
  25544. const endTime = this.context.currentTime + this.timeDelta;
  25545. listener.positionX.linearRampToValueAtTime( _position$2.x, endTime );
  25546. listener.positionY.linearRampToValueAtTime( _position$2.y, endTime );
  25547. listener.positionZ.linearRampToValueAtTime( _position$2.z, endTime );
  25548. listener.forwardX.linearRampToValueAtTime( _orientation.x, endTime );
  25549. listener.forwardY.linearRampToValueAtTime( _orientation.y, endTime );
  25550. listener.forwardZ.linearRampToValueAtTime( _orientation.z, endTime );
  25551. listener.upX.linearRampToValueAtTime( up.x, endTime );
  25552. listener.upY.linearRampToValueAtTime( up.y, endTime );
  25553. listener.upZ.linearRampToValueAtTime( up.z, endTime );
  25554. } else {
  25555. listener.setPosition( _position$2.x, _position$2.y, _position$2.z );
  25556. listener.setOrientation( _orientation.x, _orientation.y, _orientation.z, up.x, up.y, up.z );
  25557. }
  25558. }
  25559. }
  25560. class Audio extends Object3D {
  25561. constructor( listener ) {
  25562. super();
  25563. this.type = 'Audio';
  25564. this.listener = listener;
  25565. this.context = listener.context;
  25566. this.gain = this.context.createGain();
  25567. this.gain.connect( listener.getInput() );
  25568. this.autoplay = false;
  25569. this.buffer = null;
  25570. this.detune = 0;
  25571. this.loop = false;
  25572. this.loopStart = 0;
  25573. this.loopEnd = 0;
  25574. this.offset = 0;
  25575. this.duration = undefined;
  25576. this.playbackRate = 1;
  25577. this.isPlaying = false;
  25578. this.hasPlaybackControl = true;
  25579. this.source = null;
  25580. this.sourceType = 'empty';
  25581. this._startedAt = 0;
  25582. this._progress = 0;
  25583. this._connected = false;
  25584. this.filters = [];
  25585. }
  25586. getOutput() {
  25587. return this.gain;
  25588. }
  25589. setNodeSource( audioNode ) {
  25590. this.hasPlaybackControl = false;
  25591. this.sourceType = 'audioNode';
  25592. this.source = audioNode;
  25593. this.connect();
  25594. return this;
  25595. }
  25596. setMediaElementSource( mediaElement ) {
  25597. this.hasPlaybackControl = false;
  25598. this.sourceType = 'mediaNode';
  25599. this.source = this.context.createMediaElementSource( mediaElement );
  25600. this.connect();
  25601. return this;
  25602. }
  25603. setMediaStreamSource( mediaStream ) {
  25604. this.hasPlaybackControl = false;
  25605. this.sourceType = 'mediaStreamNode';
  25606. this.source = this.context.createMediaStreamSource( mediaStream );
  25607. this.connect();
  25608. return this;
  25609. }
  25610. setBuffer( audioBuffer ) {
  25611. this.buffer = audioBuffer;
  25612. this.sourceType = 'buffer';
  25613. if ( this.autoplay ) this.play();
  25614. return this;
  25615. }
  25616. play( delay = 0 ) {
  25617. if ( this.isPlaying === true ) {
  25618. console.warn( 'THREE.Audio: Audio is already playing.' );
  25619. return;
  25620. }
  25621. if ( this.hasPlaybackControl === false ) {
  25622. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  25623. return;
  25624. }
  25625. this._startedAt = this.context.currentTime + delay;
  25626. const source = this.context.createBufferSource();
  25627. source.buffer = this.buffer;
  25628. source.loop = this.loop;
  25629. source.loopStart = this.loopStart;
  25630. source.loopEnd = this.loopEnd;
  25631. source.onended = this.onEnded.bind( this );
  25632. source.start( this._startedAt, this._progress + this.offset, this.duration );
  25633. this.isPlaying = true;
  25634. this.source = source;
  25635. this.setDetune( this.detune );
  25636. this.setPlaybackRate( this.playbackRate );
  25637. return this.connect();
  25638. }
  25639. pause() {
  25640. if ( this.hasPlaybackControl === false ) {
  25641. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  25642. return;
  25643. }
  25644. if ( this.isPlaying === true ) {
  25645. // update current progress
  25646. this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
  25647. if ( this.loop === true ) {
  25648. // ensure _progress does not exceed duration with looped audios
  25649. this._progress = this._progress % ( this.duration || this.buffer.duration );
  25650. }
  25651. this.source.stop();
  25652. this.source.onended = null;
  25653. this.isPlaying = false;
  25654. }
  25655. return this;
  25656. }
  25657. stop() {
  25658. if ( this.hasPlaybackControl === false ) {
  25659. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  25660. return;
  25661. }
  25662. this._progress = 0;
  25663. this.source.stop();
  25664. this.source.onended = null;
  25665. this.isPlaying = false;
  25666. return this;
  25667. }
  25668. connect() {
  25669. if ( this.filters.length > 0 ) {
  25670. this.source.connect( this.filters[ 0 ] );
  25671. for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
  25672. this.filters[ i - 1 ].connect( this.filters[ i ] );
  25673. }
  25674. this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
  25675. } else {
  25676. this.source.connect( this.getOutput() );
  25677. }
  25678. this._connected = true;
  25679. return this;
  25680. }
  25681. disconnect() {
  25682. if ( this.filters.length > 0 ) {
  25683. this.source.disconnect( this.filters[ 0 ] );
  25684. for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
  25685. this.filters[ i - 1 ].disconnect( this.filters[ i ] );
  25686. }
  25687. this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
  25688. } else {
  25689. this.source.disconnect( this.getOutput() );
  25690. }
  25691. this._connected = false;
  25692. return this;
  25693. }
  25694. getFilters() {
  25695. return this.filters;
  25696. }
  25697. setFilters( value ) {
  25698. if ( ! value ) value = [];
  25699. if ( this._connected === true ) {
  25700. this.disconnect();
  25701. this.filters = value.slice();
  25702. this.connect();
  25703. } else {
  25704. this.filters = value.slice();
  25705. }
  25706. return this;
  25707. }
  25708. setDetune( value ) {
  25709. this.detune = value;
  25710. if ( this.source.detune === undefined ) return; // only set detune when available
  25711. if ( this.isPlaying === true ) {
  25712. this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
  25713. }
  25714. return this;
  25715. }
  25716. getDetune() {
  25717. return this.detune;
  25718. }
  25719. getFilter() {
  25720. return this.getFilters()[ 0 ];
  25721. }
  25722. setFilter( filter ) {
  25723. return this.setFilters( filter ? [ filter ] : [] );
  25724. }
  25725. setPlaybackRate( value ) {
  25726. if ( this.hasPlaybackControl === false ) {
  25727. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  25728. return;
  25729. }
  25730. this.playbackRate = value;
  25731. if ( this.isPlaying === true ) {
  25732. this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
  25733. }
  25734. return this;
  25735. }
  25736. getPlaybackRate() {
  25737. return this.playbackRate;
  25738. }
  25739. onEnded() {
  25740. this.isPlaying = false;
  25741. }
  25742. getLoop() {
  25743. if ( this.hasPlaybackControl === false ) {
  25744. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  25745. return false;
  25746. }
  25747. return this.loop;
  25748. }
  25749. setLoop( value ) {
  25750. if ( this.hasPlaybackControl === false ) {
  25751. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  25752. return;
  25753. }
  25754. this.loop = value;
  25755. if ( this.isPlaying === true ) {
  25756. this.source.loop = this.loop;
  25757. }
  25758. return this;
  25759. }
  25760. setLoopStart( value ) {
  25761. this.loopStart = value;
  25762. return this;
  25763. }
  25764. setLoopEnd( value ) {
  25765. this.loopEnd = value;
  25766. return this;
  25767. }
  25768. getVolume() {
  25769. return this.gain.gain.value;
  25770. }
  25771. setVolume( value ) {
  25772. this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
  25773. return this;
  25774. }
  25775. }
  25776. const _position$3 = /*@__PURE__*/ new Vector3();
  25777. const _quaternion$4 = /*@__PURE__*/ new Quaternion();
  25778. const _scale$2 = /*@__PURE__*/ new Vector3();
  25779. const _orientation$1 = /*@__PURE__*/ new Vector3();
  25780. class PositionalAudio extends Audio {
  25781. constructor( listener ) {
  25782. super( listener );
  25783. this.panner = this.context.createPanner();
  25784. this.panner.panningModel = 'HRTF';
  25785. this.panner.connect( this.gain );
  25786. }
  25787. getOutput() {
  25788. return this.panner;
  25789. }
  25790. getRefDistance() {
  25791. return this.panner.refDistance;
  25792. }
  25793. setRefDistance( value ) {
  25794. this.panner.refDistance = value;
  25795. return this;
  25796. }
  25797. getRolloffFactor() {
  25798. return this.panner.rolloffFactor;
  25799. }
  25800. setRolloffFactor( value ) {
  25801. this.panner.rolloffFactor = value;
  25802. return this;
  25803. }
  25804. getDistanceModel() {
  25805. return this.panner.distanceModel;
  25806. }
  25807. setDistanceModel( value ) {
  25808. this.panner.distanceModel = value;
  25809. return this;
  25810. }
  25811. getMaxDistance() {
  25812. return this.panner.maxDistance;
  25813. }
  25814. setMaxDistance( value ) {
  25815. this.panner.maxDistance = value;
  25816. return this;
  25817. }
  25818. setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
  25819. this.panner.coneInnerAngle = coneInnerAngle;
  25820. this.panner.coneOuterAngle = coneOuterAngle;
  25821. this.panner.coneOuterGain = coneOuterGain;
  25822. return this;
  25823. }
  25824. updateMatrixWorld( force ) {
  25825. super.updateMatrixWorld( force );
  25826. if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
  25827. this.matrixWorld.decompose( _position$3, _quaternion$4, _scale$2 );
  25828. _orientation$1.set( 0, 0, 1 ).applyQuaternion( _quaternion$4 );
  25829. const panner = this.panner;
  25830. if ( panner.positionX ) {
  25831. // code path for Chrome and Firefox (see #14393)
  25832. const endTime = this.context.currentTime + this.listener.timeDelta;
  25833. panner.positionX.linearRampToValueAtTime( _position$3.x, endTime );
  25834. panner.positionY.linearRampToValueAtTime( _position$3.y, endTime );
  25835. panner.positionZ.linearRampToValueAtTime( _position$3.z, endTime );
  25836. panner.orientationX.linearRampToValueAtTime( _orientation$1.x, endTime );
  25837. panner.orientationY.linearRampToValueAtTime( _orientation$1.y, endTime );
  25838. panner.orientationZ.linearRampToValueAtTime( _orientation$1.z, endTime );
  25839. } else {
  25840. panner.setPosition( _position$3.x, _position$3.y, _position$3.z );
  25841. panner.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z );
  25842. }
  25843. }
  25844. }
  25845. class AudioAnalyser {
  25846. constructor( audio, fftSize = 2048 ) {
  25847. this.analyser = audio.context.createAnalyser();
  25848. this.analyser.fftSize = fftSize;
  25849. this.data = new Uint8Array( this.analyser.frequencyBinCount );
  25850. audio.getOutput().connect( this.analyser );
  25851. }
  25852. getFrequencyData() {
  25853. this.analyser.getByteFrequencyData( this.data );
  25854. return this.data;
  25855. }
  25856. getAverageFrequency() {
  25857. let value = 0;
  25858. const data = this.getFrequencyData();
  25859. for ( let i = 0; i < data.length; i ++ ) {
  25860. value += data[ i ];
  25861. }
  25862. return value / data.length;
  25863. }
  25864. }
  25865. function PropertyMixer( binding, typeName, valueSize ) {
  25866. this.binding = binding;
  25867. this.valueSize = valueSize;
  25868. let mixFunction,
  25869. mixFunctionAdditive,
  25870. setIdentity;
  25871. // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
  25872. //
  25873. // interpolators can use .buffer as their .result
  25874. // the data then goes to 'incoming'
  25875. //
  25876. // 'accu0' and 'accu1' are used frame-interleaved for
  25877. // the cumulative result and are compared to detect
  25878. // changes
  25879. //
  25880. // 'orig' stores the original state of the property
  25881. //
  25882. // 'add' is used for additive cumulative results
  25883. //
  25884. // 'work' is optional and is only present for quaternion types. It is used
  25885. // to store intermediate quaternion multiplication results
  25886. switch ( typeName ) {
  25887. case 'quaternion':
  25888. mixFunction = this._slerp;
  25889. mixFunctionAdditive = this._slerpAdditive;
  25890. setIdentity = this._setAdditiveIdentityQuaternion;
  25891. this.buffer = new Float64Array( valueSize * 6 );
  25892. this._workIndex = 5;
  25893. break;
  25894. case 'string':
  25895. case 'bool':
  25896. mixFunction = this._select;
  25897. // Use the regular mix function and for additive on these types,
  25898. // additive is not relevant for non-numeric types
  25899. mixFunctionAdditive = this._select;
  25900. setIdentity = this._setAdditiveIdentityOther;
  25901. this.buffer = new Array( valueSize * 5 );
  25902. break;
  25903. default:
  25904. mixFunction = this._lerp;
  25905. mixFunctionAdditive = this._lerpAdditive;
  25906. setIdentity = this._setAdditiveIdentityNumeric;
  25907. this.buffer = new Float64Array( valueSize * 5 );
  25908. }
  25909. this._mixBufferRegion = mixFunction;
  25910. this._mixBufferRegionAdditive = mixFunctionAdditive;
  25911. this._setIdentity = setIdentity;
  25912. this._origIndex = 3;
  25913. this._addIndex = 4;
  25914. this.cumulativeWeight = 0;
  25915. this.cumulativeWeightAdditive = 0;
  25916. this.useCount = 0;
  25917. this.referenceCount = 0;
  25918. }
  25919. Object.assign( PropertyMixer.prototype, {
  25920. // accumulate data in the 'incoming' region into 'accu<i>'
  25921. accumulate: function ( accuIndex, weight ) {
  25922. // note: happily accumulating nothing when weight = 0, the caller knows
  25923. // the weight and shouldn't have made the call in the first place
  25924. const buffer = this.buffer,
  25925. stride = this.valueSize,
  25926. offset = accuIndex * stride + stride;
  25927. let currentWeight = this.cumulativeWeight;
  25928. if ( currentWeight === 0 ) {
  25929. // accuN := incoming * weight
  25930. for ( let i = 0; i !== stride; ++ i ) {
  25931. buffer[ offset + i ] = buffer[ i ];
  25932. }
  25933. currentWeight = weight;
  25934. } else {
  25935. // accuN := accuN + incoming * weight
  25936. currentWeight += weight;
  25937. const mix = weight / currentWeight;
  25938. this._mixBufferRegion( buffer, offset, 0, mix, stride );
  25939. }
  25940. this.cumulativeWeight = currentWeight;
  25941. },
  25942. // accumulate data in the 'incoming' region into 'add'
  25943. accumulateAdditive: function ( weight ) {
  25944. const buffer = this.buffer,
  25945. stride = this.valueSize,
  25946. offset = stride * this._addIndex;
  25947. if ( this.cumulativeWeightAdditive === 0 ) {
  25948. // add = identity
  25949. this._setIdentity();
  25950. }
  25951. // add := add + incoming * weight
  25952. this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
  25953. this.cumulativeWeightAdditive += weight;
  25954. },
  25955. // apply the state of 'accu<i>' to the binding when accus differ
  25956. apply: function ( accuIndex ) {
  25957. const stride = this.valueSize,
  25958. buffer = this.buffer,
  25959. offset = accuIndex * stride + stride,
  25960. weight = this.cumulativeWeight,
  25961. weightAdditive = this.cumulativeWeightAdditive,
  25962. binding = this.binding;
  25963. this.cumulativeWeight = 0;
  25964. this.cumulativeWeightAdditive = 0;
  25965. if ( weight < 1 ) {
  25966. // accuN := accuN + original * ( 1 - cumulativeWeight )
  25967. const originalValueOffset = stride * this._origIndex;
  25968. this._mixBufferRegion(
  25969. buffer, offset, originalValueOffset, 1 - weight, stride );
  25970. }
  25971. if ( weightAdditive > 0 ) {
  25972. // accuN := accuN + additive accuN
  25973. this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
  25974. }
  25975. for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
  25976. if ( buffer[ i ] !== buffer[ i + stride ] ) {
  25977. // value has changed -> update scene graph
  25978. binding.setValue( buffer, offset );
  25979. break;
  25980. }
  25981. }
  25982. },
  25983. // remember the state of the bound property and copy it to both accus
  25984. saveOriginalState: function () {
  25985. const binding = this.binding;
  25986. const buffer = this.buffer,
  25987. stride = this.valueSize,
  25988. originalValueOffset = stride * this._origIndex;
  25989. binding.getValue( buffer, originalValueOffset );
  25990. // accu[0..1] := orig -- initially detect changes against the original
  25991. for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
  25992. buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
  25993. }
  25994. // Add to identity for additive
  25995. this._setIdentity();
  25996. this.cumulativeWeight = 0;
  25997. this.cumulativeWeightAdditive = 0;
  25998. },
  25999. // apply the state previously taken via 'saveOriginalState' to the binding
  26000. restoreOriginalState: function () {
  26001. const originalValueOffset = this.valueSize * 3;
  26002. this.binding.setValue( this.buffer, originalValueOffset );
  26003. },
  26004. _setAdditiveIdentityNumeric: function () {
  26005. const startIndex = this._addIndex * this.valueSize;
  26006. const endIndex = startIndex + this.valueSize;
  26007. for ( let i = startIndex; i < endIndex; i ++ ) {
  26008. this.buffer[ i ] = 0;
  26009. }
  26010. },
  26011. _setAdditiveIdentityQuaternion: function () {
  26012. this._setAdditiveIdentityNumeric();
  26013. this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
  26014. },
  26015. _setAdditiveIdentityOther: function () {
  26016. const startIndex = this._origIndex * this.valueSize;
  26017. const targetIndex = this._addIndex * this.valueSize;
  26018. for ( let i = 0; i < this.valueSize; i ++ ) {
  26019. this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
  26020. }
  26021. },
  26022. // mix functions
  26023. _select: function ( buffer, dstOffset, srcOffset, t, stride ) {
  26024. if ( t >= 0.5 ) {
  26025. for ( let i = 0; i !== stride; ++ i ) {
  26026. buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
  26027. }
  26028. }
  26029. },
  26030. _slerp: function ( buffer, dstOffset, srcOffset, t ) {
  26031. Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
  26032. },
  26033. _slerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
  26034. const workOffset = this._workIndex * stride;
  26035. // Store result in intermediate buffer offset
  26036. Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
  26037. // Slerp to the intermediate result
  26038. Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
  26039. },
  26040. _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
  26041. const s = 1 - t;
  26042. for ( let i = 0; i !== stride; ++ i ) {
  26043. const j = dstOffset + i;
  26044. buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
  26045. }
  26046. },
  26047. _lerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
  26048. for ( let i = 0; i !== stride; ++ i ) {
  26049. const j = dstOffset + i;
  26050. buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
  26051. }
  26052. }
  26053. } );
  26054. // Characters [].:/ are reserved for track binding syntax.
  26055. const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
  26056. const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
  26057. // Attempts to allow node names from any language. ES5's `\w` regexp matches
  26058. // only latin characters, and the unicode \p{L} is not yet supported. So
  26059. // instead, we exclude reserved characters and match everything else.
  26060. const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
  26061. const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
  26062. // Parent directories, delimited by '/' or ':'. Currently unused, but must
  26063. // be matched to parse the rest of the track name.
  26064. const _directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
  26065. // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
  26066. const _nodeRe = /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
  26067. // Object on target node, and accessor. May not contain reserved
  26068. // characters. Accessor may contain any character except closing bracket.
  26069. const _objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
  26070. // Property and accessor. May not contain reserved characters. Accessor may
  26071. // contain any non-bracket characters.
  26072. const _propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
  26073. const _trackRe = new RegExp( ''
  26074. + '^'
  26075. + _directoryRe
  26076. + _nodeRe
  26077. + _objectRe
  26078. + _propertyRe
  26079. + '$'
  26080. );
  26081. const _supportedObjectNames = [ 'material', 'materials', 'bones' ];
  26082. function Composite( targetGroup, path, optionalParsedPath ) {
  26083. const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
  26084. this._targetGroup = targetGroup;
  26085. this._bindings = targetGroup.subscribe_( path, parsedPath );
  26086. }
  26087. Object.assign( Composite.prototype, {
  26088. getValue: function ( array, offset ) {
  26089. this.bind(); // bind all binding
  26090. const firstValidIndex = this._targetGroup.nCachedObjects_,
  26091. binding = this._bindings[ firstValidIndex ];
  26092. // and only call .getValue on the first
  26093. if ( binding !== undefined ) binding.getValue( array, offset );
  26094. },
  26095. setValue: function ( array, offset ) {
  26096. const bindings = this._bindings;
  26097. for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
  26098. bindings[ i ].setValue( array, offset );
  26099. }
  26100. },
  26101. bind: function () {
  26102. const bindings = this._bindings;
  26103. for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
  26104. bindings[ i ].bind();
  26105. }
  26106. },
  26107. unbind: function () {
  26108. const bindings = this._bindings;
  26109. for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
  26110. bindings[ i ].unbind();
  26111. }
  26112. }
  26113. } );
  26114. function PropertyBinding( rootNode, path, parsedPath ) {
  26115. this.path = path;
  26116. this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
  26117. this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
  26118. this.rootNode = rootNode;
  26119. }
  26120. Object.assign( PropertyBinding, {
  26121. Composite: Composite,
  26122. create: function ( root, path, parsedPath ) {
  26123. if ( ! ( root && root.isAnimationObjectGroup ) ) {
  26124. return new PropertyBinding( root, path, parsedPath );
  26125. } else {
  26126. return new PropertyBinding.Composite( root, path, parsedPath );
  26127. }
  26128. },
  26129. /**
  26130. * Replaces spaces with underscores and removes unsupported characters from
  26131. * node names, to ensure compatibility with parseTrackName().
  26132. *
  26133. * @param {string} name Node name to be sanitized.
  26134. * @return {string}
  26135. */
  26136. sanitizeNodeName: function ( name ) {
  26137. return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
  26138. },
  26139. parseTrackName: function ( trackName ) {
  26140. const matches = _trackRe.exec( trackName );
  26141. if ( ! matches ) {
  26142. throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
  26143. }
  26144. const results = {
  26145. // directoryName: matches[ 1 ], // (tschw) currently unused
  26146. nodeName: matches[ 2 ],
  26147. objectName: matches[ 3 ],
  26148. objectIndex: matches[ 4 ],
  26149. propertyName: matches[ 5 ], // required
  26150. propertyIndex: matches[ 6 ]
  26151. };
  26152. const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
  26153. if ( lastDot !== undefined && lastDot !== - 1 ) {
  26154. const objectName = results.nodeName.substring( lastDot + 1 );
  26155. // Object names must be checked against an allowlist. Otherwise, there
  26156. // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
  26157. // 'bar' could be the objectName, or part of a nodeName (which can
  26158. // include '.' characters).
  26159. if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
  26160. results.nodeName = results.nodeName.substring( 0, lastDot );
  26161. results.objectName = objectName;
  26162. }
  26163. }
  26164. if ( results.propertyName === null || results.propertyName.length === 0 ) {
  26165. throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
  26166. }
  26167. return results;
  26168. },
  26169. findNode: function ( root, nodeName ) {
  26170. if ( ! nodeName || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
  26171. return root;
  26172. }
  26173. // search into skeleton bones.
  26174. if ( root.skeleton ) {
  26175. const bone = root.skeleton.getBoneByName( nodeName );
  26176. if ( bone !== undefined ) {
  26177. return bone;
  26178. }
  26179. }
  26180. // search into node subtree.
  26181. if ( root.children ) {
  26182. const searchNodeSubtree = function ( children ) {
  26183. for ( let i = 0; i < children.length; i ++ ) {
  26184. const childNode = children[ i ];
  26185. if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
  26186. return childNode;
  26187. }
  26188. const result = searchNodeSubtree( childNode.children );
  26189. if ( result ) return result;
  26190. }
  26191. return null;
  26192. };
  26193. const subTreeNode = searchNodeSubtree( root.children );
  26194. if ( subTreeNode ) {
  26195. return subTreeNode;
  26196. }
  26197. }
  26198. return null;
  26199. }
  26200. } );
  26201. Object.assign( PropertyBinding.prototype, { // prototype, continued
  26202. // these are used to "bind" a nonexistent property
  26203. _getValue_unavailable: function () {},
  26204. _setValue_unavailable: function () {},
  26205. BindingType: {
  26206. Direct: 0,
  26207. EntireArray: 1,
  26208. ArrayElement: 2,
  26209. HasFromToArray: 3
  26210. },
  26211. Versioning: {
  26212. None: 0,
  26213. NeedsUpdate: 1,
  26214. MatrixWorldNeedsUpdate: 2
  26215. },
  26216. GetterByBindingType: [
  26217. function getValue_direct( buffer, offset ) {
  26218. buffer[ offset ] = this.node[ this.propertyName ];
  26219. },
  26220. function getValue_array( buffer, offset ) {
  26221. const source = this.resolvedProperty;
  26222. for ( let i = 0, n = source.length; i !== n; ++ i ) {
  26223. buffer[ offset ++ ] = source[ i ];
  26224. }
  26225. },
  26226. function getValue_arrayElement( buffer, offset ) {
  26227. buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
  26228. },
  26229. function getValue_toArray( buffer, offset ) {
  26230. this.resolvedProperty.toArray( buffer, offset );
  26231. }
  26232. ],
  26233. SetterByBindingTypeAndVersioning: [
  26234. [
  26235. // Direct
  26236. function setValue_direct( buffer, offset ) {
  26237. this.targetObject[ this.propertyName ] = buffer[ offset ];
  26238. },
  26239. function setValue_direct_setNeedsUpdate( buffer, offset ) {
  26240. this.targetObject[ this.propertyName ] = buffer[ offset ];
  26241. this.targetObject.needsUpdate = true;
  26242. },
  26243. function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
  26244. this.targetObject[ this.propertyName ] = buffer[ offset ];
  26245. this.targetObject.matrixWorldNeedsUpdate = true;
  26246. }
  26247. ], [
  26248. // EntireArray
  26249. function setValue_array( buffer, offset ) {
  26250. const dest = this.resolvedProperty;
  26251. for ( let i = 0, n = dest.length; i !== n; ++ i ) {
  26252. dest[ i ] = buffer[ offset ++ ];
  26253. }
  26254. },
  26255. function setValue_array_setNeedsUpdate( buffer, offset ) {
  26256. const dest = this.resolvedProperty;
  26257. for ( let i = 0, n = dest.length; i !== n; ++ i ) {
  26258. dest[ i ] = buffer[ offset ++ ];
  26259. }
  26260. this.targetObject.needsUpdate = true;
  26261. },
  26262. function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
  26263. const dest = this.resolvedProperty;
  26264. for ( let i = 0, n = dest.length; i !== n; ++ i ) {
  26265. dest[ i ] = buffer[ offset ++ ];
  26266. }
  26267. this.targetObject.matrixWorldNeedsUpdate = true;
  26268. }
  26269. ], [
  26270. // ArrayElement
  26271. function setValue_arrayElement( buffer, offset ) {
  26272. this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
  26273. },
  26274. function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
  26275. this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
  26276. this.targetObject.needsUpdate = true;
  26277. },
  26278. function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
  26279. this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
  26280. this.targetObject.matrixWorldNeedsUpdate = true;
  26281. }
  26282. ], [
  26283. // HasToFromArray
  26284. function setValue_fromArray( buffer, offset ) {
  26285. this.resolvedProperty.fromArray( buffer, offset );
  26286. },
  26287. function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
  26288. this.resolvedProperty.fromArray( buffer, offset );
  26289. this.targetObject.needsUpdate = true;
  26290. },
  26291. function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
  26292. this.resolvedProperty.fromArray( buffer, offset );
  26293. this.targetObject.matrixWorldNeedsUpdate = true;
  26294. }
  26295. ]
  26296. ],
  26297. getValue: function getValue_unbound( targetArray, offset ) {
  26298. this.bind();
  26299. this.getValue( targetArray, offset );
  26300. // Note: This class uses a State pattern on a per-method basis:
  26301. // 'bind' sets 'this.getValue' / 'setValue' and shadows the
  26302. // prototype version of these methods with one that represents
  26303. // the bound state. When the property is not found, the methods
  26304. // become no-ops.
  26305. },
  26306. setValue: function getValue_unbound( sourceArray, offset ) {
  26307. this.bind();
  26308. this.setValue( sourceArray, offset );
  26309. },
  26310. // create getter / setter pair for a property in the scene graph
  26311. bind: function () {
  26312. let targetObject = this.node;
  26313. const parsedPath = this.parsedPath;
  26314. const objectName = parsedPath.objectName;
  26315. const propertyName = parsedPath.propertyName;
  26316. let propertyIndex = parsedPath.propertyIndex;
  26317. if ( ! targetObject ) {
  26318. targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
  26319. this.node = targetObject;
  26320. }
  26321. // set fail state so we can just 'return' on error
  26322. this.getValue = this._getValue_unavailable;
  26323. this.setValue = this._setValue_unavailable;
  26324. // ensure there is a value node
  26325. if ( ! targetObject ) {
  26326. console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
  26327. return;
  26328. }
  26329. if ( objectName ) {
  26330. let objectIndex = parsedPath.objectIndex;
  26331. // special cases were we need to reach deeper into the hierarchy to get the face materials....
  26332. switch ( objectName ) {
  26333. case 'materials':
  26334. if ( ! targetObject.material ) {
  26335. console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
  26336. return;
  26337. }
  26338. if ( ! targetObject.material.materials ) {
  26339. console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
  26340. return;
  26341. }
  26342. targetObject = targetObject.material.materials;
  26343. break;
  26344. case 'bones':
  26345. if ( ! targetObject.skeleton ) {
  26346. console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
  26347. return;
  26348. }
  26349. // potential future optimization: skip this if propertyIndex is already an integer
  26350. // and convert the integer string to a true integer.
  26351. targetObject = targetObject.skeleton.bones;
  26352. // support resolving morphTarget names into indices.
  26353. for ( let i = 0; i < targetObject.length; i ++ ) {
  26354. if ( targetObject[ i ].name === objectIndex ) {
  26355. objectIndex = i;
  26356. break;
  26357. }
  26358. }
  26359. break;
  26360. default:
  26361. if ( targetObject[ objectName ] === undefined ) {
  26362. console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
  26363. return;
  26364. }
  26365. targetObject = targetObject[ objectName ];
  26366. }
  26367. if ( objectIndex !== undefined ) {
  26368. if ( targetObject[ objectIndex ] === undefined ) {
  26369. console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
  26370. return;
  26371. }
  26372. targetObject = targetObject[ objectIndex ];
  26373. }
  26374. }
  26375. // resolve property
  26376. const nodeProperty = targetObject[ propertyName ];
  26377. if ( nodeProperty === undefined ) {
  26378. const nodeName = parsedPath.nodeName;
  26379. console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
  26380. '.' + propertyName + ' but it wasn\'t found.', targetObject );
  26381. return;
  26382. }
  26383. // determine versioning scheme
  26384. let versioning = this.Versioning.None;
  26385. this.targetObject = targetObject;
  26386. if ( targetObject.needsUpdate !== undefined ) { // material
  26387. versioning = this.Versioning.NeedsUpdate;
  26388. } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
  26389. versioning = this.Versioning.MatrixWorldNeedsUpdate;
  26390. }
  26391. // determine how the property gets bound
  26392. let bindingType = this.BindingType.Direct;
  26393. if ( propertyIndex !== undefined ) {
  26394. // access a sub element of the property array (only primitives are supported right now)
  26395. if ( propertyName === 'morphTargetInfluences' ) {
  26396. // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
  26397. // support resolving morphTarget names into indices.
  26398. if ( ! targetObject.geometry ) {
  26399. console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
  26400. return;
  26401. }
  26402. if ( targetObject.geometry.isBufferGeometry ) {
  26403. if ( ! targetObject.geometry.morphAttributes ) {
  26404. console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
  26405. return;
  26406. }
  26407. if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
  26408. propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
  26409. }
  26410. } else {
  26411. console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences on THREE.Geometry. Use THREE.BufferGeometry instead.', this );
  26412. return;
  26413. }
  26414. }
  26415. bindingType = this.BindingType.ArrayElement;
  26416. this.resolvedProperty = nodeProperty;
  26417. this.propertyIndex = propertyIndex;
  26418. } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
  26419. // must use copy for Object3D.Euler/Quaternion
  26420. bindingType = this.BindingType.HasFromToArray;
  26421. this.resolvedProperty = nodeProperty;
  26422. } else if ( Array.isArray( nodeProperty ) ) {
  26423. bindingType = this.BindingType.EntireArray;
  26424. this.resolvedProperty = nodeProperty;
  26425. } else {
  26426. this.propertyName = propertyName;
  26427. }
  26428. // select getter / setter
  26429. this.getValue = this.GetterByBindingType[ bindingType ];
  26430. this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
  26431. },
  26432. unbind: function () {
  26433. this.node = null;
  26434. // back to the prototype version of getValue / setValue
  26435. // note: avoiding to mutate the shape of 'this' via 'delete'
  26436. this.getValue = this._getValue_unbound;
  26437. this.setValue = this._setValue_unbound;
  26438. }
  26439. } );
  26440. // DECLARE ALIAS AFTER assign prototype
  26441. Object.assign( PropertyBinding.prototype, {
  26442. // initial state of these methods that calls 'bind'
  26443. _getValue_unbound: PropertyBinding.prototype.getValue,
  26444. _setValue_unbound: PropertyBinding.prototype.setValue,
  26445. } );
  26446. /**
  26447. *
  26448. * A group of objects that receives a shared animation state.
  26449. *
  26450. * Usage:
  26451. *
  26452. * - Add objects you would otherwise pass as 'root' to the
  26453. * constructor or the .clipAction method of AnimationMixer.
  26454. *
  26455. * - Instead pass this object as 'root'.
  26456. *
  26457. * - You can also add and remove objects later when the mixer
  26458. * is running.
  26459. *
  26460. * Note:
  26461. *
  26462. * Objects of this class appear as one object to the mixer,
  26463. * so cache control of the individual objects must be done
  26464. * on the group.
  26465. *
  26466. * Limitation:
  26467. *
  26468. * - The animated properties must be compatible among the
  26469. * all objects in the group.
  26470. *
  26471. * - A single property can either be controlled through a
  26472. * target group or directly, but not both.
  26473. */
  26474. function AnimationObjectGroup() {
  26475. this.uuid = MathUtils$1.generateUUID();
  26476. // cached objects followed by the active ones
  26477. this._objects = Array.prototype.slice.call( arguments );
  26478. this.nCachedObjects_ = 0; // threshold
  26479. // note: read by PropertyBinding.Composite
  26480. const indices = {};
  26481. this._indicesByUUID = indices; // for bookkeeping
  26482. for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
  26483. indices[ arguments[ i ].uuid ] = i;
  26484. }
  26485. this._paths = []; // inside: string
  26486. this._parsedPaths = []; // inside: { we don't care, here }
  26487. this._bindings = []; // inside: Array< PropertyBinding >
  26488. this._bindingsIndicesByPath = {}; // inside: indices in these arrays
  26489. const scope = this;
  26490. this.stats = {
  26491. objects: {
  26492. get total() {
  26493. return scope._objects.length;
  26494. },
  26495. get inUse() {
  26496. return this.total - scope.nCachedObjects_;
  26497. }
  26498. },
  26499. get bindingsPerObject() {
  26500. return scope._bindings.length;
  26501. }
  26502. };
  26503. }
  26504. Object.assign( AnimationObjectGroup.prototype, {
  26505. isAnimationObjectGroup: true,
  26506. add: function () {
  26507. const objects = this._objects,
  26508. indicesByUUID = this._indicesByUUID,
  26509. paths = this._paths,
  26510. parsedPaths = this._parsedPaths,
  26511. bindings = this._bindings,
  26512. nBindings = bindings.length;
  26513. let knownObject = undefined,
  26514. nObjects = objects.length,
  26515. nCachedObjects = this.nCachedObjects_;
  26516. for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
  26517. const object = arguments[ i ],
  26518. uuid = object.uuid;
  26519. let index = indicesByUUID[ uuid ];
  26520. if ( index === undefined ) {
  26521. // unknown object -> add it to the ACTIVE region
  26522. index = nObjects ++;
  26523. indicesByUUID[ uuid ] = index;
  26524. objects.push( object );
  26525. // accounting is done, now do the same for all bindings
  26526. for ( let j = 0, m = nBindings; j !== m; ++ j ) {
  26527. bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
  26528. }
  26529. } else if ( index < nCachedObjects ) {
  26530. knownObject = objects[ index ];
  26531. // move existing object to the ACTIVE region
  26532. const firstActiveIndex = -- nCachedObjects,
  26533. lastCachedObject = objects[ firstActiveIndex ];
  26534. indicesByUUID[ lastCachedObject.uuid ] = index;
  26535. objects[ index ] = lastCachedObject;
  26536. indicesByUUID[ uuid ] = firstActiveIndex;
  26537. objects[ firstActiveIndex ] = object;
  26538. // accounting is done, now do the same for all bindings
  26539. for ( let j = 0, m = nBindings; j !== m; ++ j ) {
  26540. const bindingsForPath = bindings[ j ],
  26541. lastCached = bindingsForPath[ firstActiveIndex ];
  26542. let binding = bindingsForPath[ index ];
  26543. bindingsForPath[ index ] = lastCached;
  26544. if ( binding === undefined ) {
  26545. // since we do not bother to create new bindings
  26546. // for objects that are cached, the binding may
  26547. // or may not exist
  26548. binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
  26549. }
  26550. bindingsForPath[ firstActiveIndex ] = binding;
  26551. }
  26552. } else if ( objects[ index ] !== knownObject ) {
  26553. console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
  26554. 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
  26555. } // else the object is already where we want it to be
  26556. } // for arguments
  26557. this.nCachedObjects_ = nCachedObjects;
  26558. },
  26559. remove: function () {
  26560. const objects = this._objects,
  26561. indicesByUUID = this._indicesByUUID,
  26562. bindings = this._bindings,
  26563. nBindings = bindings.length;
  26564. let nCachedObjects = this.nCachedObjects_;
  26565. for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
  26566. const object = arguments[ i ],
  26567. uuid = object.uuid,
  26568. index = indicesByUUID[ uuid ];
  26569. if ( index !== undefined && index >= nCachedObjects ) {
  26570. // move existing object into the CACHED region
  26571. const lastCachedIndex = nCachedObjects ++,
  26572. firstActiveObject = objects[ lastCachedIndex ];
  26573. indicesByUUID[ firstActiveObject.uuid ] = index;
  26574. objects[ index ] = firstActiveObject;
  26575. indicesByUUID[ uuid ] = lastCachedIndex;
  26576. objects[ lastCachedIndex ] = object;
  26577. // accounting is done, now do the same for all bindings
  26578. for ( let j = 0, m = nBindings; j !== m; ++ j ) {
  26579. const bindingsForPath = bindings[ j ],
  26580. firstActive = bindingsForPath[ lastCachedIndex ],
  26581. binding = bindingsForPath[ index ];
  26582. bindingsForPath[ index ] = firstActive;
  26583. bindingsForPath[ lastCachedIndex ] = binding;
  26584. }
  26585. }
  26586. } // for arguments
  26587. this.nCachedObjects_ = nCachedObjects;
  26588. },
  26589. // remove & forget
  26590. uncache: function () {
  26591. const objects = this._objects,
  26592. indicesByUUID = this._indicesByUUID,
  26593. bindings = this._bindings,
  26594. nBindings = bindings.length;
  26595. let nCachedObjects = this.nCachedObjects_,
  26596. nObjects = objects.length;
  26597. for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
  26598. const object = arguments[ i ],
  26599. uuid = object.uuid,
  26600. index = indicesByUUID[ uuid ];
  26601. if ( index !== undefined ) {
  26602. delete indicesByUUID[ uuid ];
  26603. if ( index < nCachedObjects ) {
  26604. // object is cached, shrink the CACHED region
  26605. const firstActiveIndex = -- nCachedObjects,
  26606. lastCachedObject = objects[ firstActiveIndex ],
  26607. lastIndex = -- nObjects,
  26608. lastObject = objects[ lastIndex ];
  26609. // last cached object takes this object's place
  26610. indicesByUUID[ lastCachedObject.uuid ] = index;
  26611. objects[ index ] = lastCachedObject;
  26612. // last object goes to the activated slot and pop
  26613. indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
  26614. objects[ firstActiveIndex ] = lastObject;
  26615. objects.pop();
  26616. // accounting is done, now do the same for all bindings
  26617. for ( let j = 0, m = nBindings; j !== m; ++ j ) {
  26618. const bindingsForPath = bindings[ j ],
  26619. lastCached = bindingsForPath[ firstActiveIndex ],
  26620. last = bindingsForPath[ lastIndex ];
  26621. bindingsForPath[ index ] = lastCached;
  26622. bindingsForPath[ firstActiveIndex ] = last;
  26623. bindingsForPath.pop();
  26624. }
  26625. } else {
  26626. // object is active, just swap with the last and pop
  26627. const lastIndex = -- nObjects,
  26628. lastObject = objects[ lastIndex ];
  26629. if ( lastIndex > 0 ) {
  26630. indicesByUUID[ lastObject.uuid ] = index;
  26631. }
  26632. objects[ index ] = lastObject;
  26633. objects.pop();
  26634. // accounting is done, now do the same for all bindings
  26635. for ( let j = 0, m = nBindings; j !== m; ++ j ) {
  26636. const bindingsForPath = bindings[ j ];
  26637. bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
  26638. bindingsForPath.pop();
  26639. }
  26640. } // cached or active
  26641. } // if object is known
  26642. } // for arguments
  26643. this.nCachedObjects_ = nCachedObjects;
  26644. },
  26645. // Internal interface used by befriended PropertyBinding.Composite:
  26646. subscribe_: function ( path, parsedPath ) {
  26647. // returns an array of bindings for the given path that is changed
  26648. // according to the contained objects in the group
  26649. const indicesByPath = this._bindingsIndicesByPath;
  26650. let index = indicesByPath[ path ];
  26651. const bindings = this._bindings;
  26652. if ( index !== undefined ) return bindings[ index ];
  26653. const paths = this._paths,
  26654. parsedPaths = this._parsedPaths,
  26655. objects = this._objects,
  26656. nObjects = objects.length,
  26657. nCachedObjects = this.nCachedObjects_,
  26658. bindingsForPath = new Array( nObjects );
  26659. index = bindings.length;
  26660. indicesByPath[ path ] = index;
  26661. paths.push( path );
  26662. parsedPaths.push( parsedPath );
  26663. bindings.push( bindingsForPath );
  26664. for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
  26665. const object = objects[ i ];
  26666. bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
  26667. }
  26668. return bindingsForPath;
  26669. },
  26670. unsubscribe_: function ( path ) {
  26671. // tells the group to forget about a property path and no longer
  26672. // update the array previously obtained with 'subscribe_'
  26673. const indicesByPath = this._bindingsIndicesByPath,
  26674. index = indicesByPath[ path ];
  26675. if ( index !== undefined ) {
  26676. const paths = this._paths,
  26677. parsedPaths = this._parsedPaths,
  26678. bindings = this._bindings,
  26679. lastBindingsIndex = bindings.length - 1,
  26680. lastBindings = bindings[ lastBindingsIndex ],
  26681. lastBindingsPath = path[ lastBindingsIndex ];
  26682. indicesByPath[ lastBindingsPath ] = index;
  26683. bindings[ index ] = lastBindings;
  26684. bindings.pop();
  26685. parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
  26686. parsedPaths.pop();
  26687. paths[ index ] = paths[ lastBindingsIndex ];
  26688. paths.pop();
  26689. }
  26690. }
  26691. } );
  26692. class AnimationAction {
  26693. constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
  26694. this._mixer = mixer;
  26695. this._clip = clip;
  26696. this._localRoot = localRoot;
  26697. this.blendMode = blendMode;
  26698. const tracks = clip.tracks,
  26699. nTracks = tracks.length,
  26700. interpolants = new Array( nTracks );
  26701. const interpolantSettings = {
  26702. endingStart: ZeroCurvatureEnding,
  26703. endingEnd: ZeroCurvatureEnding
  26704. };
  26705. for ( let i = 0; i !== nTracks; ++ i ) {
  26706. const interpolant = tracks[ i ].createInterpolant( null );
  26707. interpolants[ i ] = interpolant;
  26708. interpolant.settings = interpolantSettings;
  26709. }
  26710. this._interpolantSettings = interpolantSettings;
  26711. this._interpolants = interpolants; // bound by the mixer
  26712. // inside: PropertyMixer (managed by the mixer)
  26713. this._propertyBindings = new Array( nTracks );
  26714. this._cacheIndex = null; // for the memory manager
  26715. this._byClipCacheIndex = null; // for the memory manager
  26716. this._timeScaleInterpolant = null;
  26717. this._weightInterpolant = null;
  26718. this.loop = LoopRepeat;
  26719. this._loopCount = - 1;
  26720. // global mixer time when the action is to be started
  26721. // it's set back to 'null' upon start of the action
  26722. this._startTime = null;
  26723. // scaled local time of the action
  26724. // gets clamped or wrapped to 0..clip.duration according to loop
  26725. this.time = 0;
  26726. this.timeScale = 1;
  26727. this._effectiveTimeScale = 1;
  26728. this.weight = 1;
  26729. this._effectiveWeight = 1;
  26730. this.repetitions = Infinity; // no. of repetitions when looping
  26731. this.paused = false; // true -> zero effective time scale
  26732. this.enabled = true; // false -> zero effective weight
  26733. this.clampWhenFinished = false;// keep feeding the last frame?
  26734. this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
  26735. this.zeroSlopeAtEnd = true;// clips for start, loop and end
  26736. }
  26737. // State & Scheduling
  26738. play() {
  26739. this._mixer._activateAction( this );
  26740. return this;
  26741. }
  26742. stop() {
  26743. this._mixer._deactivateAction( this );
  26744. return this.reset();
  26745. }
  26746. reset() {
  26747. this.paused = false;
  26748. this.enabled = true;
  26749. this.time = 0; // restart clip
  26750. this._loopCount = - 1;// forget previous loops
  26751. this._startTime = null;// forget scheduling
  26752. return this.stopFading().stopWarping();
  26753. }
  26754. isRunning() {
  26755. return this.enabled && ! this.paused && this.timeScale !== 0 &&
  26756. this._startTime === null && this._mixer._isActiveAction( this );
  26757. }
  26758. // return true when play has been called
  26759. isScheduled() {
  26760. return this._mixer._isActiveAction( this );
  26761. }
  26762. startAt( time ) {
  26763. this._startTime = time;
  26764. return this;
  26765. }
  26766. setLoop( mode, repetitions ) {
  26767. this.loop = mode;
  26768. this.repetitions = repetitions;
  26769. return this;
  26770. }
  26771. // Weight
  26772. // set the weight stopping any scheduled fading
  26773. // although .enabled = false yields an effective weight of zero, this
  26774. // method does *not* change .enabled, because it would be confusing
  26775. setEffectiveWeight( weight ) {
  26776. this.weight = weight;
  26777. // note: same logic as when updated at runtime
  26778. this._effectiveWeight = this.enabled ? weight : 0;
  26779. return this.stopFading();
  26780. }
  26781. // return the weight considering fading and .enabled
  26782. getEffectiveWeight() {
  26783. return this._effectiveWeight;
  26784. }
  26785. fadeIn( duration ) {
  26786. return this._scheduleFading( duration, 0, 1 );
  26787. }
  26788. fadeOut( duration ) {
  26789. return this._scheduleFading( duration, 1, 0 );
  26790. }
  26791. crossFadeFrom( fadeOutAction, duration, warp ) {
  26792. fadeOutAction.fadeOut( duration );
  26793. this.fadeIn( duration );
  26794. if ( warp ) {
  26795. const fadeInDuration = this._clip.duration,
  26796. fadeOutDuration = fadeOutAction._clip.duration,
  26797. startEndRatio = fadeOutDuration / fadeInDuration,
  26798. endStartRatio = fadeInDuration / fadeOutDuration;
  26799. fadeOutAction.warp( 1.0, startEndRatio, duration );
  26800. this.warp( endStartRatio, 1.0, duration );
  26801. }
  26802. return this;
  26803. }
  26804. crossFadeTo( fadeInAction, duration, warp ) {
  26805. return fadeInAction.crossFadeFrom( this, duration, warp );
  26806. }
  26807. stopFading() {
  26808. const weightInterpolant = this._weightInterpolant;
  26809. if ( weightInterpolant !== null ) {
  26810. this._weightInterpolant = null;
  26811. this._mixer._takeBackControlInterpolant( weightInterpolant );
  26812. }
  26813. return this;
  26814. }
  26815. // Time Scale Control
  26816. // set the time scale stopping any scheduled warping
  26817. // although .paused = true yields an effective time scale of zero, this
  26818. // method does *not* change .paused, because it would be confusing
  26819. setEffectiveTimeScale( timeScale ) {
  26820. this.timeScale = timeScale;
  26821. this._effectiveTimeScale = this.paused ? 0 : timeScale;
  26822. return this.stopWarping();
  26823. }
  26824. // return the time scale considering warping and .paused
  26825. getEffectiveTimeScale() {
  26826. return this._effectiveTimeScale;
  26827. }
  26828. setDuration( duration ) {
  26829. this.timeScale = this._clip.duration / duration;
  26830. return this.stopWarping();
  26831. }
  26832. syncWith( action ) {
  26833. this.time = action.time;
  26834. this.timeScale = action.timeScale;
  26835. return this.stopWarping();
  26836. }
  26837. halt( duration ) {
  26838. return this.warp( this._effectiveTimeScale, 0, duration );
  26839. }
  26840. warp( startTimeScale, endTimeScale, duration ) {
  26841. const mixer = this._mixer,
  26842. now = mixer.time,
  26843. timeScale = this.timeScale;
  26844. let interpolant = this._timeScaleInterpolant;
  26845. if ( interpolant === null ) {
  26846. interpolant = mixer._lendControlInterpolant();
  26847. this._timeScaleInterpolant = interpolant;
  26848. }
  26849. const times = interpolant.parameterPositions,
  26850. values = interpolant.sampleValues;
  26851. times[ 0 ] = now;
  26852. times[ 1 ] = now + duration;
  26853. values[ 0 ] = startTimeScale / timeScale;
  26854. values[ 1 ] = endTimeScale / timeScale;
  26855. return this;
  26856. }
  26857. stopWarping() {
  26858. const timeScaleInterpolant = this._timeScaleInterpolant;
  26859. if ( timeScaleInterpolant !== null ) {
  26860. this._timeScaleInterpolant = null;
  26861. this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
  26862. }
  26863. return this;
  26864. }
  26865. // Object Accessors
  26866. getMixer() {
  26867. return this._mixer;
  26868. }
  26869. getClip() {
  26870. return this._clip;
  26871. }
  26872. getRoot() {
  26873. return this._localRoot || this._mixer._root;
  26874. }
  26875. // Interna
  26876. _update( time, deltaTime, timeDirection, accuIndex ) {
  26877. // called by the mixer
  26878. if ( ! this.enabled ) {
  26879. // call ._updateWeight() to update ._effectiveWeight
  26880. this._updateWeight( time );
  26881. return;
  26882. }
  26883. const startTime = this._startTime;
  26884. if ( startTime !== null ) {
  26885. // check for scheduled start of action
  26886. const timeRunning = ( time - startTime ) * timeDirection;
  26887. if ( timeRunning < 0 || timeDirection === 0 ) {
  26888. return; // yet to come / don't decide when delta = 0
  26889. }
  26890. // start
  26891. this._startTime = null; // unschedule
  26892. deltaTime = timeDirection * timeRunning;
  26893. }
  26894. // apply time scale and advance time
  26895. deltaTime *= this._updateTimeScale( time );
  26896. const clipTime = this._updateTime( deltaTime );
  26897. // note: _updateTime may disable the action resulting in
  26898. // an effective weight of 0
  26899. const weight = this._updateWeight( time );
  26900. if ( weight > 0 ) {
  26901. const interpolants = this._interpolants;
  26902. const propertyMixers = this._propertyBindings;
  26903. switch ( this.blendMode ) {
  26904. case AdditiveAnimationBlendMode:
  26905. for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
  26906. interpolants[ j ].evaluate( clipTime );
  26907. propertyMixers[ j ].accumulateAdditive( weight );
  26908. }
  26909. break;
  26910. case NormalAnimationBlendMode:
  26911. default:
  26912. for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
  26913. interpolants[ j ].evaluate( clipTime );
  26914. propertyMixers[ j ].accumulate( accuIndex, weight );
  26915. }
  26916. }
  26917. }
  26918. }
  26919. _updateWeight( time ) {
  26920. let weight = 0;
  26921. if ( this.enabled ) {
  26922. weight = this.weight;
  26923. const interpolant = this._weightInterpolant;
  26924. if ( interpolant !== null ) {
  26925. const interpolantValue = interpolant.evaluate( time )[ 0 ];
  26926. weight *= interpolantValue;
  26927. if ( time > interpolant.parameterPositions[ 1 ] ) {
  26928. this.stopFading();
  26929. if ( interpolantValue === 0 ) {
  26930. // faded out, disable
  26931. this.enabled = false;
  26932. }
  26933. }
  26934. }
  26935. }
  26936. this._effectiveWeight = weight;
  26937. return weight;
  26938. }
  26939. _updateTimeScale( time ) {
  26940. let timeScale = 0;
  26941. if ( ! this.paused ) {
  26942. timeScale = this.timeScale;
  26943. const interpolant = this._timeScaleInterpolant;
  26944. if ( interpolant !== null ) {
  26945. const interpolantValue = interpolant.evaluate( time )[ 0 ];
  26946. timeScale *= interpolantValue;
  26947. if ( time > interpolant.parameterPositions[ 1 ] ) {
  26948. this.stopWarping();
  26949. if ( timeScale === 0 ) {
  26950. // motion has halted, pause
  26951. this.paused = true;
  26952. } else {
  26953. // warp done - apply final time scale
  26954. this.timeScale = timeScale;
  26955. }
  26956. }
  26957. }
  26958. }
  26959. this._effectiveTimeScale = timeScale;
  26960. return timeScale;
  26961. }
  26962. _updateTime( deltaTime ) {
  26963. const duration = this._clip.duration;
  26964. const loop = this.loop;
  26965. let time = this.time + deltaTime;
  26966. let loopCount = this._loopCount;
  26967. const pingPong = ( loop === LoopPingPong );
  26968. if ( deltaTime === 0 ) {
  26969. if ( loopCount === - 1 ) return time;
  26970. return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
  26971. }
  26972. if ( loop === LoopOnce ) {
  26973. if ( loopCount === - 1 ) {
  26974. // just started
  26975. this._loopCount = 0;
  26976. this._setEndings( true, true, false );
  26977. }
  26978. handle_stop: {
  26979. if ( time >= duration ) {
  26980. time = duration;
  26981. } else if ( time < 0 ) {
  26982. time = 0;
  26983. } else {
  26984. this.time = time;
  26985. break handle_stop;
  26986. }
  26987. if ( this.clampWhenFinished ) this.paused = true;
  26988. else this.enabled = false;
  26989. this.time = time;
  26990. this._mixer.dispatchEvent( {
  26991. type: 'finished', action: this,
  26992. direction: deltaTime < 0 ? - 1 : 1
  26993. } );
  26994. }
  26995. } else { // repetitive Repeat or PingPong
  26996. if ( loopCount === - 1 ) {
  26997. // just started
  26998. if ( deltaTime >= 0 ) {
  26999. loopCount = 0;
  27000. this._setEndings( true, this.repetitions === 0, pingPong );
  27001. } else {
  27002. // when looping in reverse direction, the initial
  27003. // transition through zero counts as a repetition,
  27004. // so leave loopCount at -1
  27005. this._setEndings( this.repetitions === 0, true, pingPong );
  27006. }
  27007. }
  27008. if ( time >= duration || time < 0 ) {
  27009. // wrap around
  27010. const loopDelta = Math.floor( time / duration ); // signed
  27011. time -= duration * loopDelta;
  27012. loopCount += Math.abs( loopDelta );
  27013. const pending = this.repetitions - loopCount;
  27014. if ( pending <= 0 ) {
  27015. // have to stop (switch state, clamp time, fire event)
  27016. if ( this.clampWhenFinished ) this.paused = true;
  27017. else this.enabled = false;
  27018. time = deltaTime > 0 ? duration : 0;
  27019. this.time = time;
  27020. this._mixer.dispatchEvent( {
  27021. type: 'finished', action: this,
  27022. direction: deltaTime > 0 ? 1 : - 1
  27023. } );
  27024. } else {
  27025. // keep running
  27026. if ( pending === 1 ) {
  27027. // entering the last round
  27028. const atStart = deltaTime < 0;
  27029. this._setEndings( atStart, ! atStart, pingPong );
  27030. } else {
  27031. this._setEndings( false, false, pingPong );
  27032. }
  27033. this._loopCount = loopCount;
  27034. this.time = time;
  27035. this._mixer.dispatchEvent( {
  27036. type: 'loop', action: this, loopDelta: loopDelta
  27037. } );
  27038. }
  27039. } else {
  27040. this.time = time;
  27041. }
  27042. if ( pingPong && ( loopCount & 1 ) === 1 ) {
  27043. // invert time for the "pong round"
  27044. return duration - time;
  27045. }
  27046. }
  27047. return time;
  27048. }
  27049. _setEndings( atStart, atEnd, pingPong ) {
  27050. const settings = this._interpolantSettings;
  27051. if ( pingPong ) {
  27052. settings.endingStart = ZeroSlopeEnding;
  27053. settings.endingEnd = ZeroSlopeEnding;
  27054. } else {
  27055. // assuming for LoopOnce atStart == atEnd == true
  27056. if ( atStart ) {
  27057. settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
  27058. } else {
  27059. settings.endingStart = WrapAroundEnding;
  27060. }
  27061. if ( atEnd ) {
  27062. settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
  27063. } else {
  27064. settings.endingEnd = WrapAroundEnding;
  27065. }
  27066. }
  27067. }
  27068. _scheduleFading( duration, weightNow, weightThen ) {
  27069. const mixer = this._mixer, now = mixer.time;
  27070. let interpolant = this._weightInterpolant;
  27071. if ( interpolant === null ) {
  27072. interpolant = mixer._lendControlInterpolant();
  27073. this._weightInterpolant = interpolant;
  27074. }
  27075. const times = interpolant.parameterPositions,
  27076. values = interpolant.sampleValues;
  27077. times[ 0 ] = now;
  27078. values[ 0 ] = weightNow;
  27079. times[ 1 ] = now + duration;
  27080. values[ 1 ] = weightThen;
  27081. return this;
  27082. }
  27083. }
  27084. function AnimationMixer( root ) {
  27085. this._root = root;
  27086. this._initMemoryManager();
  27087. this._accuIndex = 0;
  27088. this.time = 0;
  27089. this.timeScale = 1.0;
  27090. }
  27091. AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
  27092. constructor: AnimationMixer,
  27093. _bindAction: function ( action, prototypeAction ) {
  27094. const root = action._localRoot || this._root,
  27095. tracks = action._clip.tracks,
  27096. nTracks = tracks.length,
  27097. bindings = action._propertyBindings,
  27098. interpolants = action._interpolants,
  27099. rootUuid = root.uuid,
  27100. bindingsByRoot = this._bindingsByRootAndName;
  27101. let bindingsByName = bindingsByRoot[ rootUuid ];
  27102. if ( bindingsByName === undefined ) {
  27103. bindingsByName = {};
  27104. bindingsByRoot[ rootUuid ] = bindingsByName;
  27105. }
  27106. for ( let i = 0; i !== nTracks; ++ i ) {
  27107. const track = tracks[ i ],
  27108. trackName = track.name;
  27109. let binding = bindingsByName[ trackName ];
  27110. if ( binding !== undefined ) {
  27111. bindings[ i ] = binding;
  27112. } else {
  27113. binding = bindings[ i ];
  27114. if ( binding !== undefined ) {
  27115. // existing binding, make sure the cache knows
  27116. if ( binding._cacheIndex === null ) {
  27117. ++ binding.referenceCount;
  27118. this._addInactiveBinding( binding, rootUuid, trackName );
  27119. }
  27120. continue;
  27121. }
  27122. const path = prototypeAction && prototypeAction.
  27123. _propertyBindings[ i ].binding.parsedPath;
  27124. binding = new PropertyMixer(
  27125. PropertyBinding.create( root, trackName, path ),
  27126. track.ValueTypeName, track.getValueSize() );
  27127. ++ binding.referenceCount;
  27128. this._addInactiveBinding( binding, rootUuid, trackName );
  27129. bindings[ i ] = binding;
  27130. }
  27131. interpolants[ i ].resultBuffer = binding.buffer;
  27132. }
  27133. },
  27134. _activateAction: function ( action ) {
  27135. if ( ! this._isActiveAction( action ) ) {
  27136. if ( action._cacheIndex === null ) {
  27137. // this action has been forgotten by the cache, but the user
  27138. // appears to be still using it -> rebind
  27139. const rootUuid = ( action._localRoot || this._root ).uuid,
  27140. clipUuid = action._clip.uuid,
  27141. actionsForClip = this._actionsByClip[ clipUuid ];
  27142. this._bindAction( action,
  27143. actionsForClip && actionsForClip.knownActions[ 0 ] );
  27144. this._addInactiveAction( action, clipUuid, rootUuid );
  27145. }
  27146. const bindings = action._propertyBindings;
  27147. // increment reference counts / sort out state
  27148. for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
  27149. const binding = bindings[ i ];
  27150. if ( binding.useCount ++ === 0 ) {
  27151. this._lendBinding( binding );
  27152. binding.saveOriginalState();
  27153. }
  27154. }
  27155. this._lendAction( action );
  27156. }
  27157. },
  27158. _deactivateAction: function ( action ) {
  27159. if ( this._isActiveAction( action ) ) {
  27160. const bindings = action._propertyBindings;
  27161. // decrement reference counts / sort out state
  27162. for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
  27163. const binding = bindings[ i ];
  27164. if ( -- binding.useCount === 0 ) {
  27165. binding.restoreOriginalState();
  27166. this._takeBackBinding( binding );
  27167. }
  27168. }
  27169. this._takeBackAction( action );
  27170. }
  27171. },
  27172. // Memory manager
  27173. _initMemoryManager: function () {
  27174. this._actions = []; // 'nActiveActions' followed by inactive ones
  27175. this._nActiveActions = 0;
  27176. this._actionsByClip = {};
  27177. // inside:
  27178. // {
  27179. // knownActions: Array< AnimationAction > - used as prototypes
  27180. // actionByRoot: AnimationAction - lookup
  27181. // }
  27182. this._bindings = []; // 'nActiveBindings' followed by inactive ones
  27183. this._nActiveBindings = 0;
  27184. this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
  27185. this._controlInterpolants = []; // same game as above
  27186. this._nActiveControlInterpolants = 0;
  27187. const scope = this;
  27188. this.stats = {
  27189. actions: {
  27190. get total() {
  27191. return scope._actions.length;
  27192. },
  27193. get inUse() {
  27194. return scope._nActiveActions;
  27195. }
  27196. },
  27197. bindings: {
  27198. get total() {
  27199. return scope._bindings.length;
  27200. },
  27201. get inUse() {
  27202. return scope._nActiveBindings;
  27203. }
  27204. },
  27205. controlInterpolants: {
  27206. get total() {
  27207. return scope._controlInterpolants.length;
  27208. },
  27209. get inUse() {
  27210. return scope._nActiveControlInterpolants;
  27211. }
  27212. }
  27213. };
  27214. },
  27215. // Memory management for AnimationAction objects
  27216. _isActiveAction: function ( action ) {
  27217. const index = action._cacheIndex;
  27218. return index !== null && index < this._nActiveActions;
  27219. },
  27220. _addInactiveAction: function ( action, clipUuid, rootUuid ) {
  27221. const actions = this._actions,
  27222. actionsByClip = this._actionsByClip;
  27223. let actionsForClip = actionsByClip[ clipUuid ];
  27224. if ( actionsForClip === undefined ) {
  27225. actionsForClip = {
  27226. knownActions: [ action ],
  27227. actionByRoot: {}
  27228. };
  27229. action._byClipCacheIndex = 0;
  27230. actionsByClip[ clipUuid ] = actionsForClip;
  27231. } else {
  27232. const knownActions = actionsForClip.knownActions;
  27233. action._byClipCacheIndex = knownActions.length;
  27234. knownActions.push( action );
  27235. }
  27236. action._cacheIndex = actions.length;
  27237. actions.push( action );
  27238. actionsForClip.actionByRoot[ rootUuid ] = action;
  27239. },
  27240. _removeInactiveAction: function ( action ) {
  27241. const actions = this._actions,
  27242. lastInactiveAction = actions[ actions.length - 1 ],
  27243. cacheIndex = action._cacheIndex;
  27244. lastInactiveAction._cacheIndex = cacheIndex;
  27245. actions[ cacheIndex ] = lastInactiveAction;
  27246. actions.pop();
  27247. action._cacheIndex = null;
  27248. const clipUuid = action._clip.uuid,
  27249. actionsByClip = this._actionsByClip,
  27250. actionsForClip = actionsByClip[ clipUuid ],
  27251. knownActionsForClip = actionsForClip.knownActions,
  27252. lastKnownAction =
  27253. knownActionsForClip[ knownActionsForClip.length - 1 ],
  27254. byClipCacheIndex = action._byClipCacheIndex;
  27255. lastKnownAction._byClipCacheIndex = byClipCacheIndex;
  27256. knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
  27257. knownActionsForClip.pop();
  27258. action._byClipCacheIndex = null;
  27259. const actionByRoot = actionsForClip.actionByRoot,
  27260. rootUuid = ( action._localRoot || this._root ).uuid;
  27261. delete actionByRoot[ rootUuid ];
  27262. if ( knownActionsForClip.length === 0 ) {
  27263. delete actionsByClip[ clipUuid ];
  27264. }
  27265. this._removeInactiveBindingsForAction( action );
  27266. },
  27267. _removeInactiveBindingsForAction: function ( action ) {
  27268. const bindings = action._propertyBindings;
  27269. for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
  27270. const binding = bindings[ i ];
  27271. if ( -- binding.referenceCount === 0 ) {
  27272. this._removeInactiveBinding( binding );
  27273. }
  27274. }
  27275. },
  27276. _lendAction: function ( action ) {
  27277. // [ active actions | inactive actions ]
  27278. // [ active actions >| inactive actions ]
  27279. // s a
  27280. // <-swap->
  27281. // a s
  27282. const actions = this._actions,
  27283. prevIndex = action._cacheIndex,
  27284. lastActiveIndex = this._nActiveActions ++,
  27285. firstInactiveAction = actions[ lastActiveIndex ];
  27286. action._cacheIndex = lastActiveIndex;
  27287. actions[ lastActiveIndex ] = action;
  27288. firstInactiveAction._cacheIndex = prevIndex;
  27289. actions[ prevIndex ] = firstInactiveAction;
  27290. },
  27291. _takeBackAction: function ( action ) {
  27292. // [ active actions | inactive actions ]
  27293. // [ active actions |< inactive actions ]
  27294. // a s
  27295. // <-swap->
  27296. // s a
  27297. const actions = this._actions,
  27298. prevIndex = action._cacheIndex,
  27299. firstInactiveIndex = -- this._nActiveActions,
  27300. lastActiveAction = actions[ firstInactiveIndex ];
  27301. action._cacheIndex = firstInactiveIndex;
  27302. actions[ firstInactiveIndex ] = action;
  27303. lastActiveAction._cacheIndex = prevIndex;
  27304. actions[ prevIndex ] = lastActiveAction;
  27305. },
  27306. // Memory management for PropertyMixer objects
  27307. _addInactiveBinding: function ( binding, rootUuid, trackName ) {
  27308. const bindingsByRoot = this._bindingsByRootAndName,
  27309. bindings = this._bindings;
  27310. let bindingByName = bindingsByRoot[ rootUuid ];
  27311. if ( bindingByName === undefined ) {
  27312. bindingByName = {};
  27313. bindingsByRoot[ rootUuid ] = bindingByName;
  27314. }
  27315. bindingByName[ trackName ] = binding;
  27316. binding._cacheIndex = bindings.length;
  27317. bindings.push( binding );
  27318. },
  27319. _removeInactiveBinding: function ( binding ) {
  27320. const bindings = this._bindings,
  27321. propBinding = binding.binding,
  27322. rootUuid = propBinding.rootNode.uuid,
  27323. trackName = propBinding.path,
  27324. bindingsByRoot = this._bindingsByRootAndName,
  27325. bindingByName = bindingsByRoot[ rootUuid ],
  27326. lastInactiveBinding = bindings[ bindings.length - 1 ],
  27327. cacheIndex = binding._cacheIndex;
  27328. lastInactiveBinding._cacheIndex = cacheIndex;
  27329. bindings[ cacheIndex ] = lastInactiveBinding;
  27330. bindings.pop();
  27331. delete bindingByName[ trackName ];
  27332. if ( Object.keys( bindingByName ).length === 0 ) {
  27333. delete bindingsByRoot[ rootUuid ];
  27334. }
  27335. },
  27336. _lendBinding: function ( binding ) {
  27337. const bindings = this._bindings,
  27338. prevIndex = binding._cacheIndex,
  27339. lastActiveIndex = this._nActiveBindings ++,
  27340. firstInactiveBinding = bindings[ lastActiveIndex ];
  27341. binding._cacheIndex = lastActiveIndex;
  27342. bindings[ lastActiveIndex ] = binding;
  27343. firstInactiveBinding._cacheIndex = prevIndex;
  27344. bindings[ prevIndex ] = firstInactiveBinding;
  27345. },
  27346. _takeBackBinding: function ( binding ) {
  27347. const bindings = this._bindings,
  27348. prevIndex = binding._cacheIndex,
  27349. firstInactiveIndex = -- this._nActiveBindings,
  27350. lastActiveBinding = bindings[ firstInactiveIndex ];
  27351. binding._cacheIndex = firstInactiveIndex;
  27352. bindings[ firstInactiveIndex ] = binding;
  27353. lastActiveBinding._cacheIndex = prevIndex;
  27354. bindings[ prevIndex ] = lastActiveBinding;
  27355. },
  27356. // Memory management of Interpolants for weight and time scale
  27357. _lendControlInterpolant: function () {
  27358. const interpolants = this._controlInterpolants,
  27359. lastActiveIndex = this._nActiveControlInterpolants ++;
  27360. let interpolant = interpolants[ lastActiveIndex ];
  27361. if ( interpolant === undefined ) {
  27362. interpolant = new LinearInterpolant(
  27363. new Float32Array( 2 ), new Float32Array( 2 ),
  27364. 1, this._controlInterpolantsResultBuffer );
  27365. interpolant.__cacheIndex = lastActiveIndex;
  27366. interpolants[ lastActiveIndex ] = interpolant;
  27367. }
  27368. return interpolant;
  27369. },
  27370. _takeBackControlInterpolant: function ( interpolant ) {
  27371. const interpolants = this._controlInterpolants,
  27372. prevIndex = interpolant.__cacheIndex,
  27373. firstInactiveIndex = -- this._nActiveControlInterpolants,
  27374. lastActiveInterpolant = interpolants[ firstInactiveIndex ];
  27375. interpolant.__cacheIndex = firstInactiveIndex;
  27376. interpolants[ firstInactiveIndex ] = interpolant;
  27377. lastActiveInterpolant.__cacheIndex = prevIndex;
  27378. interpolants[ prevIndex ] = lastActiveInterpolant;
  27379. },
  27380. _controlInterpolantsResultBuffer: new Float32Array( 1 ),
  27381. // return an action for a clip optionally using a custom root target
  27382. // object (this method allocates a lot of dynamic memory in case a
  27383. // previously unknown clip/root combination is specified)
  27384. clipAction: function ( clip, optionalRoot, blendMode ) {
  27385. const root = optionalRoot || this._root,
  27386. rootUuid = root.uuid;
  27387. let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
  27388. const clipUuid = clipObject !== null ? clipObject.uuid : clip;
  27389. const actionsForClip = this._actionsByClip[ clipUuid ];
  27390. let prototypeAction = null;
  27391. if ( blendMode === undefined ) {
  27392. if ( clipObject !== null ) {
  27393. blendMode = clipObject.blendMode;
  27394. } else {
  27395. blendMode = NormalAnimationBlendMode;
  27396. }
  27397. }
  27398. if ( actionsForClip !== undefined ) {
  27399. const existingAction = actionsForClip.actionByRoot[ rootUuid ];
  27400. if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
  27401. return existingAction;
  27402. }
  27403. // we know the clip, so we don't have to parse all
  27404. // the bindings again but can just copy
  27405. prototypeAction = actionsForClip.knownActions[ 0 ];
  27406. // also, take the clip from the prototype action
  27407. if ( clipObject === null )
  27408. clipObject = prototypeAction._clip;
  27409. }
  27410. // clip must be known when specified via string
  27411. if ( clipObject === null ) return null;
  27412. // allocate all resources required to run it
  27413. const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
  27414. this._bindAction( newAction, prototypeAction );
  27415. // and make the action known to the memory manager
  27416. this._addInactiveAction( newAction, clipUuid, rootUuid );
  27417. return newAction;
  27418. },
  27419. // get an existing action
  27420. existingAction: function ( clip, optionalRoot ) {
  27421. const root = optionalRoot || this._root,
  27422. rootUuid = root.uuid,
  27423. clipObject = typeof clip === 'string' ?
  27424. AnimationClip.findByName( root, clip ) : clip,
  27425. clipUuid = clipObject ? clipObject.uuid : clip,
  27426. actionsForClip = this._actionsByClip[ clipUuid ];
  27427. if ( actionsForClip !== undefined ) {
  27428. return actionsForClip.actionByRoot[ rootUuid ] || null;
  27429. }
  27430. return null;
  27431. },
  27432. // deactivates all previously scheduled actions
  27433. stopAllAction: function () {
  27434. const actions = this._actions,
  27435. nActions = this._nActiveActions;
  27436. for ( let i = nActions - 1; i >= 0; -- i ) {
  27437. actions[ i ].stop();
  27438. }
  27439. return this;
  27440. },
  27441. // advance the time and update apply the animation
  27442. update: function ( deltaTime ) {
  27443. deltaTime *= this.timeScale;
  27444. const actions = this._actions,
  27445. nActions = this._nActiveActions,
  27446. time = this.time += deltaTime,
  27447. timeDirection = Math.sign( deltaTime ),
  27448. accuIndex = this._accuIndex ^= 1;
  27449. // run active actions
  27450. for ( let i = 0; i !== nActions; ++ i ) {
  27451. const action = actions[ i ];
  27452. action._update( time, deltaTime, timeDirection, accuIndex );
  27453. }
  27454. // update scene graph
  27455. const bindings = this._bindings,
  27456. nBindings = this._nActiveBindings;
  27457. for ( let i = 0; i !== nBindings; ++ i ) {
  27458. bindings[ i ].apply( accuIndex );
  27459. }
  27460. return this;
  27461. },
  27462. // Allows you to seek to a specific time in an animation.
  27463. setTime: function ( timeInSeconds ) {
  27464. this.time = 0; // Zero out time attribute for AnimationMixer object;
  27465. for ( let i = 0; i < this._actions.length; i ++ ) {
  27466. this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
  27467. }
  27468. return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
  27469. },
  27470. // return this mixer's root target object
  27471. getRoot: function () {
  27472. return this._root;
  27473. },
  27474. // free all resources specific to a particular clip
  27475. uncacheClip: function ( clip ) {
  27476. const actions = this._actions,
  27477. clipUuid = clip.uuid,
  27478. actionsByClip = this._actionsByClip,
  27479. actionsForClip = actionsByClip[ clipUuid ];
  27480. if ( actionsForClip !== undefined ) {
  27481. // note: just calling _removeInactiveAction would mess up the
  27482. // iteration state and also require updating the state we can
  27483. // just throw away
  27484. const actionsToRemove = actionsForClip.knownActions;
  27485. for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
  27486. const action = actionsToRemove[ i ];
  27487. this._deactivateAction( action );
  27488. const cacheIndex = action._cacheIndex,
  27489. lastInactiveAction = actions[ actions.length - 1 ];
  27490. action._cacheIndex = null;
  27491. action._byClipCacheIndex = null;
  27492. lastInactiveAction._cacheIndex = cacheIndex;
  27493. actions[ cacheIndex ] = lastInactiveAction;
  27494. actions.pop();
  27495. this._removeInactiveBindingsForAction( action );
  27496. }
  27497. delete actionsByClip[ clipUuid ];
  27498. }
  27499. },
  27500. // free all resources specific to a particular root target object
  27501. uncacheRoot: function ( root ) {
  27502. const rootUuid = root.uuid,
  27503. actionsByClip = this._actionsByClip;
  27504. for ( const clipUuid in actionsByClip ) {
  27505. const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
  27506. action = actionByRoot[ rootUuid ];
  27507. if ( action !== undefined ) {
  27508. this._deactivateAction( action );
  27509. this._removeInactiveAction( action );
  27510. }
  27511. }
  27512. const bindingsByRoot = this._bindingsByRootAndName,
  27513. bindingByName = bindingsByRoot[ rootUuid ];
  27514. if ( bindingByName !== undefined ) {
  27515. for ( const trackName in bindingByName ) {
  27516. const binding = bindingByName[ trackName ];
  27517. binding.restoreOriginalState();
  27518. this._removeInactiveBinding( binding );
  27519. }
  27520. }
  27521. },
  27522. // remove a targeted clip from the cache
  27523. uncacheAction: function ( clip, optionalRoot ) {
  27524. const action = this.existingAction( clip, optionalRoot );
  27525. if ( action !== null ) {
  27526. this._deactivateAction( action );
  27527. this._removeInactiveAction( action );
  27528. }
  27529. }
  27530. } );
  27531. class Uniform {
  27532. constructor( value ) {
  27533. if ( typeof value === 'string' ) {
  27534. console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
  27535. value = arguments[ 1 ];
  27536. }
  27537. this.value = value;
  27538. }
  27539. clone() {
  27540. return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
  27541. }
  27542. }
  27543. function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
  27544. InterleavedBuffer.call( this, array, stride );
  27545. this.meshPerAttribute = meshPerAttribute || 1;
  27546. }
  27547. InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
  27548. constructor: InstancedInterleavedBuffer,
  27549. isInstancedInterleavedBuffer: true,
  27550. copy: function ( source ) {
  27551. InterleavedBuffer.prototype.copy.call( this, source );
  27552. this.meshPerAttribute = source.meshPerAttribute;
  27553. return this;
  27554. },
  27555. clone: function ( data ) {
  27556. const ib = InterleavedBuffer.prototype.clone.call( this, data );
  27557. ib.meshPerAttribute = this.meshPerAttribute;
  27558. return ib;
  27559. },
  27560. toJSON: function ( data ) {
  27561. const json = InterleavedBuffer.prototype.toJSON.call( this, data );
  27562. json.isInstancedInterleavedBuffer = true;
  27563. json.meshPerAttribute = this.meshPerAttribute;
  27564. return json;
  27565. }
  27566. } );
  27567. function GLBufferAttribute( buffer, type, itemSize, elementSize, count ) {
  27568. this.buffer = buffer;
  27569. this.type = type;
  27570. this.itemSize = itemSize;
  27571. this.elementSize = elementSize;
  27572. this.count = count;
  27573. this.version = 0;
  27574. }
  27575. Object.defineProperty( GLBufferAttribute.prototype, 'needsUpdate', {
  27576. set: function ( value ) {
  27577. if ( value === true ) this.version ++;
  27578. }
  27579. } );
  27580. Object.assign( GLBufferAttribute.prototype, {
  27581. isGLBufferAttribute: true,
  27582. setBuffer: function ( buffer ) {
  27583. this.buffer = buffer;
  27584. return this;
  27585. },
  27586. setType: function ( type, elementSize ) {
  27587. this.type = type;
  27588. this.elementSize = elementSize;
  27589. return this;
  27590. },
  27591. setItemSize: function ( itemSize ) {
  27592. this.itemSize = itemSize;
  27593. return this;
  27594. },
  27595. setCount: function ( count ) {
  27596. this.count = count;
  27597. return this;
  27598. },
  27599. } );
  27600. function Raycaster( origin, direction, near, far ) {
  27601. this.ray = new Ray( origin, direction );
  27602. // direction is assumed to be normalized (for accurate distance calculations)
  27603. this.near = near || 0;
  27604. this.far = far || Infinity;
  27605. this.camera = null;
  27606. this.layers = new Layers();
  27607. this.params = {
  27608. Mesh: {},
  27609. Line: { threshold: 1 },
  27610. LOD: {},
  27611. Points: { threshold: 1 },
  27612. Sprite: {}
  27613. };
  27614. Object.defineProperties( this.params, {
  27615. PointCloud: {
  27616. get: function () {
  27617. console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
  27618. return this.Points;
  27619. }
  27620. }
  27621. } );
  27622. }
  27623. function ascSort( a, b ) {
  27624. return a.distance - b.distance;
  27625. }
  27626. function intersectObject( object, raycaster, intersects, recursive ) {
  27627. if ( object.layers.test( raycaster.layers ) ) {
  27628. object.raycast( raycaster, intersects );
  27629. }
  27630. if ( recursive === true ) {
  27631. const children = object.children;
  27632. for ( let i = 0, l = children.length; i < l; i ++ ) {
  27633. intersectObject( children[ i ], raycaster, intersects, true );
  27634. }
  27635. }
  27636. }
  27637. Object.assign( Raycaster.prototype, {
  27638. set: function ( origin, direction ) {
  27639. // direction is assumed to be normalized (for accurate distance calculations)
  27640. this.ray.set( origin, direction );
  27641. },
  27642. setFromCamera: function ( coords, camera ) {
  27643. if ( camera && camera.isPerspectiveCamera ) {
  27644. this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
  27645. this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
  27646. this.camera = camera;
  27647. } else if ( camera && camera.isOrthographicCamera ) {
  27648. this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
  27649. this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
  27650. this.camera = camera;
  27651. } else {
  27652. console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
  27653. }
  27654. },
  27655. intersectObject: function ( object, recursive, optionalTarget ) {
  27656. const intersects = optionalTarget || [];
  27657. intersectObject( object, this, intersects, recursive );
  27658. intersects.sort( ascSort );
  27659. return intersects;
  27660. },
  27661. intersectObjects: function ( objects, recursive, optionalTarget ) {
  27662. const intersects = optionalTarget || [];
  27663. if ( Array.isArray( objects ) === false ) {
  27664. console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
  27665. return intersects;
  27666. }
  27667. for ( let i = 0, l = objects.length; i < l; i ++ ) {
  27668. intersectObject( objects[ i ], this, intersects, recursive );
  27669. }
  27670. intersects.sort( ascSort );
  27671. return intersects;
  27672. }
  27673. } );
  27674. /**
  27675. * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
  27676. *
  27677. * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.
  27678. * The azimuthal angle (theta) is measured from the positive z-axis.
  27679. */
  27680. class Spherical {
  27681. constructor( radius = 1, phi = 0, theta = 0 ) {
  27682. this.radius = radius;
  27683. this.phi = phi; // polar angle
  27684. this.theta = theta; // azimuthal angle
  27685. return this;
  27686. }
  27687. set( radius, phi, theta ) {
  27688. this.radius = radius;
  27689. this.phi = phi;
  27690. this.theta = theta;
  27691. return this;
  27692. }
  27693. clone() {
  27694. return new this.constructor().copy( this );
  27695. }
  27696. copy( other ) {
  27697. this.radius = other.radius;
  27698. this.phi = other.phi;
  27699. this.theta = other.theta;
  27700. return this;
  27701. }
  27702. // restrict phi to be betwee EPS and PI-EPS
  27703. makeSafe() {
  27704. const EPS = 0.000001;
  27705. this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
  27706. return this;
  27707. }
  27708. setFromVector3( v ) {
  27709. return this.setFromCartesianCoords( v.x, v.y, v.z );
  27710. }
  27711. setFromCartesianCoords( x, y, z ) {
  27712. this.radius = Math.sqrt( x * x + y * y + z * z );
  27713. if ( this.radius === 0 ) {
  27714. this.theta = 0;
  27715. this.phi = 0;
  27716. } else {
  27717. this.theta = Math.atan2( x, z );
  27718. this.phi = Math.acos( MathUtils$1.clamp( y / this.radius, - 1, 1 ) );
  27719. }
  27720. return this;
  27721. }
  27722. }
  27723. /**
  27724. * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
  27725. */
  27726. class Cylindrical {
  27727. constructor( radius, theta, y ) {
  27728. this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
  27729. this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
  27730. this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
  27731. return this;
  27732. }
  27733. set( radius, theta, y ) {
  27734. this.radius = radius;
  27735. this.theta = theta;
  27736. this.y = y;
  27737. return this;
  27738. }
  27739. clone() {
  27740. return new this.constructor().copy( this );
  27741. }
  27742. copy( other ) {
  27743. this.radius = other.radius;
  27744. this.theta = other.theta;
  27745. this.y = other.y;
  27746. return this;
  27747. }
  27748. setFromVector3( v ) {
  27749. return this.setFromCartesianCoords( v.x, v.y, v.z );
  27750. }
  27751. setFromCartesianCoords( x, y, z ) {
  27752. this.radius = Math.sqrt( x * x + z * z );
  27753. this.theta = Math.atan2( x, z );
  27754. this.y = y;
  27755. return this;
  27756. }
  27757. }
  27758. const _vector$8 = /*@__PURE__*/ new Vector2();
  27759. class Box2 {
  27760. constructor( min, max ) {
  27761. Object.defineProperty( this, 'isBox2', { value: true } );
  27762. this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
  27763. this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
  27764. }
  27765. set( min, max ) {
  27766. this.min.copy( min );
  27767. this.max.copy( max );
  27768. return this;
  27769. }
  27770. setFromPoints( points ) {
  27771. this.makeEmpty();
  27772. for ( let i = 0, il = points.length; i < il; i ++ ) {
  27773. this.expandByPoint( points[ i ] );
  27774. }
  27775. return this;
  27776. }
  27777. setFromCenterAndSize( center, size ) {
  27778. const halfSize = _vector$8.copy( size ).multiplyScalar( 0.5 );
  27779. this.min.copy( center ).sub( halfSize );
  27780. this.max.copy( center ).add( halfSize );
  27781. return this;
  27782. }
  27783. clone() {
  27784. return new this.constructor().copy( this );
  27785. }
  27786. copy( box ) {
  27787. this.min.copy( box.min );
  27788. this.max.copy( box.max );
  27789. return this;
  27790. }
  27791. makeEmpty() {
  27792. this.min.x = this.min.y = + Infinity;
  27793. this.max.x = this.max.y = - Infinity;
  27794. return this;
  27795. }
  27796. isEmpty() {
  27797. // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
  27798. return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
  27799. }
  27800. getCenter( target ) {
  27801. if ( target === undefined ) {
  27802. console.warn( 'THREE.Box2: .getCenter() target is now required' );
  27803. target = new Vector2();
  27804. }
  27805. return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
  27806. }
  27807. getSize( target ) {
  27808. if ( target === undefined ) {
  27809. console.warn( 'THREE.Box2: .getSize() target is now required' );
  27810. target = new Vector2();
  27811. }
  27812. return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
  27813. }
  27814. expandByPoint( point ) {
  27815. this.min.min( point );
  27816. this.max.max( point );
  27817. return this;
  27818. }
  27819. expandByVector( vector ) {
  27820. this.min.sub( vector );
  27821. this.max.add( vector );
  27822. return this;
  27823. }
  27824. expandByScalar( scalar ) {
  27825. this.min.addScalar( - scalar );
  27826. this.max.addScalar( scalar );
  27827. return this;
  27828. }
  27829. containsPoint( point ) {
  27830. return point.x < this.min.x || point.x > this.max.x ||
  27831. point.y < this.min.y || point.y > this.max.y ? false : true;
  27832. }
  27833. containsBox( box ) {
  27834. return this.min.x <= box.min.x && box.max.x <= this.max.x &&
  27835. this.min.y <= box.min.y && box.max.y <= this.max.y;
  27836. }
  27837. getParameter( point, target ) {
  27838. // This can potentially have a divide by zero if the box
  27839. // has a size dimension of 0.
  27840. if ( target === undefined ) {
  27841. console.warn( 'THREE.Box2: .getParameter() target is now required' );
  27842. target = new Vector2();
  27843. }
  27844. return target.set(
  27845. ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
  27846. ( point.y - this.min.y ) / ( this.max.y - this.min.y )
  27847. );
  27848. }
  27849. intersectsBox( box ) {
  27850. // using 4 splitting planes to rule out intersections
  27851. return box.max.x < this.min.x || box.min.x > this.max.x ||
  27852. box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
  27853. }
  27854. clampPoint( point, target ) {
  27855. if ( target === undefined ) {
  27856. console.warn( 'THREE.Box2: .clampPoint() target is now required' );
  27857. target = new Vector2();
  27858. }
  27859. return target.copy( point ).clamp( this.min, this.max );
  27860. }
  27861. distanceToPoint( point ) {
  27862. const clampedPoint = _vector$8.copy( point ).clamp( this.min, this.max );
  27863. return clampedPoint.sub( point ).length();
  27864. }
  27865. intersect( box ) {
  27866. this.min.max( box.min );
  27867. this.max.min( box.max );
  27868. return this;
  27869. }
  27870. union( box ) {
  27871. this.min.min( box.min );
  27872. this.max.max( box.max );
  27873. return this;
  27874. }
  27875. translate( offset ) {
  27876. this.min.add( offset );
  27877. this.max.add( offset );
  27878. return this;
  27879. }
  27880. equals( box ) {
  27881. return box.min.equals( this.min ) && box.max.equals( this.max );
  27882. }
  27883. }
  27884. const _startP = /*@__PURE__*/ new Vector3();
  27885. const _startEnd = /*@__PURE__*/ new Vector3();
  27886. class Line3 {
  27887. constructor( start, end ) {
  27888. this.start = ( start !== undefined ) ? start : new Vector3();
  27889. this.end = ( end !== undefined ) ? end : new Vector3();
  27890. }
  27891. set( start, end ) {
  27892. this.start.copy( start );
  27893. this.end.copy( end );
  27894. return this;
  27895. }
  27896. clone() {
  27897. return new this.constructor().copy( this );
  27898. }
  27899. copy( line ) {
  27900. this.start.copy( line.start );
  27901. this.end.copy( line.end );
  27902. return this;
  27903. }
  27904. getCenter( target ) {
  27905. if ( target === undefined ) {
  27906. console.warn( 'THREE.Line3: .getCenter() target is now required' );
  27907. target = new Vector3();
  27908. }
  27909. return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
  27910. }
  27911. delta( target ) {
  27912. if ( target === undefined ) {
  27913. console.warn( 'THREE.Line3: .delta() target is now required' );
  27914. target = new Vector3();
  27915. }
  27916. return target.subVectors( this.end, this.start );
  27917. }
  27918. distanceSq() {
  27919. return this.start.distanceToSquared( this.end );
  27920. }
  27921. distance() {
  27922. return this.start.distanceTo( this.end );
  27923. }
  27924. at( t, target ) {
  27925. if ( target === undefined ) {
  27926. console.warn( 'THREE.Line3: .at() target is now required' );
  27927. target = new Vector3();
  27928. }
  27929. return this.delta( target ).multiplyScalar( t ).add( this.start );
  27930. }
  27931. closestPointToPointParameter( point, clampToLine ) {
  27932. _startP.subVectors( point, this.start );
  27933. _startEnd.subVectors( this.end, this.start );
  27934. const startEnd2 = _startEnd.dot( _startEnd );
  27935. const startEnd_startP = _startEnd.dot( _startP );
  27936. let t = startEnd_startP / startEnd2;
  27937. if ( clampToLine ) {
  27938. t = MathUtils$1.clamp( t, 0, 1 );
  27939. }
  27940. return t;
  27941. }
  27942. closestPointToPoint( point, clampToLine, target ) {
  27943. const t = this.closestPointToPointParameter( point, clampToLine );
  27944. if ( target === undefined ) {
  27945. console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );
  27946. target = new Vector3();
  27947. }
  27948. return this.delta( target ).multiplyScalar( t ).add( this.start );
  27949. }
  27950. applyMatrix4( matrix ) {
  27951. this.start.applyMatrix4( matrix );
  27952. this.end.applyMatrix4( matrix );
  27953. return this;
  27954. }
  27955. equals( line ) {
  27956. return line.start.equals( this.start ) && line.end.equals( this.end );
  27957. }
  27958. }
  27959. function ImmediateRenderObject( material ) {
  27960. Object3D.call( this );
  27961. this.material = material;
  27962. this.render = function ( /* renderCallback */ ) {};
  27963. this.hasPositions = false;
  27964. this.hasNormals = false;
  27965. this.hasColors = false;
  27966. this.hasUvs = false;
  27967. this.positionArray = null;
  27968. this.normalArray = null;
  27969. this.colorArray = null;
  27970. this.uvArray = null;
  27971. this.count = 0;
  27972. }
  27973. ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
  27974. ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
  27975. ImmediateRenderObject.prototype.isImmediateRenderObject = true;
  27976. const _vector$9 = /*@__PURE__*/ new Vector3();
  27977. class SpotLightHelper extends Object3D {
  27978. constructor( light, color ) {
  27979. super();
  27980. this.light = light;
  27981. this.light.updateMatrixWorld();
  27982. this.matrix = light.matrixWorld;
  27983. this.matrixAutoUpdate = false;
  27984. this.color = color;
  27985. const geometry = new BufferGeometry();
  27986. const positions = [
  27987. 0, 0, 0, 0, 0, 1,
  27988. 0, 0, 0, 1, 0, 1,
  27989. 0, 0, 0, - 1, 0, 1,
  27990. 0, 0, 0, 0, 1, 1,
  27991. 0, 0, 0, 0, - 1, 1
  27992. ];
  27993. for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
  27994. const p1 = ( i / l ) * Math.PI * 2;
  27995. const p2 = ( j / l ) * Math.PI * 2;
  27996. positions.push(
  27997. Math.cos( p1 ), Math.sin( p1 ), 1,
  27998. Math.cos( p2 ), Math.sin( p2 ), 1
  27999. );
  28000. }
  28001. geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
  28002. const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
  28003. this.cone = new LineSegments( geometry, material );
  28004. this.add( this.cone );
  28005. this.update();
  28006. }
  28007. dispose() {
  28008. this.cone.geometry.dispose();
  28009. this.cone.material.dispose();
  28010. }
  28011. update() {
  28012. this.light.updateMatrixWorld();
  28013. const coneLength = this.light.distance ? this.light.distance : 1000;
  28014. const coneWidth = coneLength * Math.tan( this.light.angle );
  28015. this.cone.scale.set( coneWidth, coneWidth, coneLength );
  28016. _vector$9.setFromMatrixPosition( this.light.target.matrixWorld );
  28017. this.cone.lookAt( _vector$9 );
  28018. if ( this.color !== undefined ) {
  28019. this.cone.material.color.set( this.color );
  28020. } else {
  28021. this.cone.material.color.copy( this.light.color );
  28022. }
  28023. }
  28024. }
  28025. const _vector$a = /*@__PURE__*/ new Vector3();
  28026. const _boneMatrix = /*@__PURE__*/ new Matrix4();
  28027. const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
  28028. class SkeletonHelper extends LineSegments {
  28029. constructor( object ) {
  28030. const bones = getBoneList( object );
  28031. const geometry = new BufferGeometry();
  28032. const vertices = [];
  28033. const colors = [];
  28034. const color1 = new Color( 0, 0, 1 );
  28035. const color2 = new Color( 0, 1, 0 );
  28036. for ( let i = 0; i < bones.length; i ++ ) {
  28037. const bone = bones[ i ];
  28038. if ( bone.parent && bone.parent.isBone ) {
  28039. vertices.push( 0, 0, 0 );
  28040. vertices.push( 0, 0, 0 );
  28041. colors.push( color1.r, color1.g, color1.b );
  28042. colors.push( color2.r, color2.g, color2.b );
  28043. }
  28044. }
  28045. geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  28046. geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
  28047. const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
  28048. super( geometry, material );
  28049. this.type = 'SkeletonHelper';
  28050. this.isSkeletonHelper = true;
  28051. this.root = object;
  28052. this.bones = bones;
  28053. this.matrix = object.matrixWorld;
  28054. this.matrixAutoUpdate = false;
  28055. }
  28056. updateMatrixWorld( force ) {
  28057. const bones = this.bones;
  28058. const geometry = this.geometry;
  28059. const position = geometry.getAttribute( 'position' );
  28060. _matrixWorldInv.copy( this.root.matrixWorld ).invert();
  28061. for ( let i = 0, j = 0; i < bones.length; i ++ ) {
  28062. const bone = bones[ i ];
  28063. if ( bone.parent && bone.parent.isBone ) {
  28064. _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
  28065. _vector$a.setFromMatrixPosition( _boneMatrix );
  28066. position.setXYZ( j, _vector$a.x, _vector$a.y, _vector$a.z );
  28067. _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
  28068. _vector$a.setFromMatrixPosition( _boneMatrix );
  28069. position.setXYZ( j + 1, _vector$a.x, _vector$a.y, _vector$a.z );
  28070. j += 2;
  28071. }
  28072. }
  28073. geometry.getAttribute( 'position' ).needsUpdate = true;
  28074. super.updateMatrixWorld( force );
  28075. }
  28076. }
  28077. function getBoneList( object ) {
  28078. const boneList = [];
  28079. if ( object && object.isBone ) {
  28080. boneList.push( object );
  28081. }
  28082. for ( let i = 0; i < object.children.length; i ++ ) {
  28083. boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
  28084. }
  28085. return boneList;
  28086. }
  28087. class PointLightHelper extends Mesh {
  28088. constructor( light, sphereSize, color ) {
  28089. const geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
  28090. const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
  28091. super( geometry, material );
  28092. this.light = light;
  28093. this.light.updateMatrixWorld();
  28094. this.color = color;
  28095. this.type = 'PointLightHelper';
  28096. this.matrix = this.light.matrixWorld;
  28097. this.matrixAutoUpdate = false;
  28098. this.update();
  28099. /*
  28100. // TODO: delete this comment?
  28101. const distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );
  28102. const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
  28103. this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
  28104. this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
  28105. const d = light.distance;
  28106. if ( d === 0.0 ) {
  28107. this.lightDistance.visible = false;
  28108. } else {
  28109. this.lightDistance.scale.set( d, d, d );
  28110. }
  28111. this.add( this.lightDistance );
  28112. */
  28113. }
  28114. dispose() {
  28115. this.geometry.dispose();
  28116. this.material.dispose();
  28117. }
  28118. update() {
  28119. if ( this.color !== undefined ) {
  28120. this.material.color.set( this.color );
  28121. } else {
  28122. this.material.color.copy( this.light.color );
  28123. }
  28124. /*
  28125. const d = this.light.distance;
  28126. if ( d === 0.0 ) {
  28127. this.lightDistance.visible = false;
  28128. } else {
  28129. this.lightDistance.visible = true;
  28130. this.lightDistance.scale.set( d, d, d );
  28131. }
  28132. */
  28133. }
  28134. }
  28135. const _vector$b = /*@__PURE__*/ new Vector3();
  28136. const _color1 = /*@__PURE__*/ new Color();
  28137. const _color2 = /*@__PURE__*/ new Color();
  28138. class HemisphereLightHelper extends Object3D {
  28139. constructor( light, size, color ) {
  28140. super();
  28141. this.light = light;
  28142. this.light.updateMatrixWorld();
  28143. this.matrix = light.matrixWorld;
  28144. this.matrixAutoUpdate = false;
  28145. this.color = color;
  28146. const geometry = new OctahedronBufferGeometry( size );
  28147. geometry.rotateY( Math.PI * 0.5 );
  28148. this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
  28149. if ( this.color === undefined ) this.material.vertexColors = true;
  28150. const position = geometry.getAttribute( 'position' );
  28151. const colors = new Float32Array( position.count * 3 );
  28152. geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
  28153. this.add( new Mesh( geometry, this.material ) );
  28154. this.update();
  28155. }
  28156. dispose() {
  28157. this.children[ 0 ].geometry.dispose();
  28158. this.children[ 0 ].material.dispose();
  28159. }
  28160. update() {
  28161. const mesh = this.children[ 0 ];
  28162. if ( this.color !== undefined ) {
  28163. this.material.color.set( this.color );
  28164. } else {
  28165. const colors = mesh.geometry.getAttribute( 'color' );
  28166. _color1.copy( this.light.color );
  28167. _color2.copy( this.light.groundColor );
  28168. for ( let i = 0, l = colors.count; i < l; i ++ ) {
  28169. const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
  28170. colors.setXYZ( i, color.r, color.g, color.b );
  28171. }
  28172. colors.needsUpdate = true;
  28173. }
  28174. mesh.lookAt( _vector$b.setFromMatrixPosition( this.light.matrixWorld ).negate() );
  28175. }
  28176. }
  28177. class GridHelper extends LineSegments {
  28178. constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
  28179. color1 = new Color( color1 );
  28180. color2 = new Color( color2 );
  28181. const center = divisions / 2;
  28182. const step = size / divisions;
  28183. const halfSize = size / 2;
  28184. const vertices = [], colors = [];
  28185. for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
  28186. vertices.push( - halfSize, 0, k, halfSize, 0, k );
  28187. vertices.push( k, 0, - halfSize, k, 0, halfSize );
  28188. const color = i === center ? color1 : color2;
  28189. color.toArray( colors, j ); j += 3;
  28190. color.toArray( colors, j ); j += 3;
  28191. color.toArray( colors, j ); j += 3;
  28192. color.toArray( colors, j ); j += 3;
  28193. }
  28194. const geometry = new BufferGeometry();
  28195. geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  28196. geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
  28197. const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
  28198. super( geometry, material );
  28199. this.type = 'GridHelper';
  28200. }
  28201. }
  28202. class PolarGridHelper extends LineSegments {
  28203. constructor( radius = 10, radials = 16, circles = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
  28204. color1 = new Color( color1 );
  28205. color2 = new Color( color2 );
  28206. const vertices = [];
  28207. const colors = [];
  28208. // create the radials
  28209. for ( let i = 0; i <= radials; i ++ ) {
  28210. const v = ( i / radials ) * ( Math.PI * 2 );
  28211. const x = Math.sin( v ) * radius;
  28212. const z = Math.cos( v ) * radius;
  28213. vertices.push( 0, 0, 0 );
  28214. vertices.push( x, 0, z );
  28215. const color = ( i & 1 ) ? color1 : color2;
  28216. colors.push( color.r, color.g, color.b );
  28217. colors.push( color.r, color.g, color.b );
  28218. }
  28219. // create the circles
  28220. for ( let i = 0; i <= circles; i ++ ) {
  28221. const color = ( i & 1 ) ? color1 : color2;
  28222. const r = radius - ( radius / circles * i );
  28223. for ( let j = 0; j < divisions; j ++ ) {
  28224. // first vertex
  28225. let v = ( j / divisions ) * ( Math.PI * 2 );
  28226. let x = Math.sin( v ) * r;
  28227. let z = Math.cos( v ) * r;
  28228. vertices.push( x, 0, z );
  28229. colors.push( color.r, color.g, color.b );
  28230. // second vertex
  28231. v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
  28232. x = Math.sin( v ) * r;
  28233. z = Math.cos( v ) * r;
  28234. vertices.push( x, 0, z );
  28235. colors.push( color.r, color.g, color.b );
  28236. }
  28237. }
  28238. const geometry = new BufferGeometry();
  28239. geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  28240. geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
  28241. const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
  28242. super( geometry, material );
  28243. this.type = 'PolarGridHelper';
  28244. }
  28245. }
  28246. const _v1$6 = /*@__PURE__*/ new Vector3();
  28247. const _v2$3 = /*@__PURE__*/ new Vector3();
  28248. const _v3$1 = /*@__PURE__*/ new Vector3();
  28249. class DirectionalLightHelper extends Object3D {
  28250. constructor( light, size, color ) {
  28251. super();
  28252. this.light = light;
  28253. this.light.updateMatrixWorld();
  28254. this.matrix = light.matrixWorld;
  28255. this.matrixAutoUpdate = false;
  28256. this.color = color;
  28257. if ( size === undefined ) size = 1;
  28258. let geometry = new BufferGeometry();
  28259. geometry.setAttribute( 'position', new Float32BufferAttribute( [
  28260. - size, size, 0,
  28261. size, size, 0,
  28262. size, - size, 0,
  28263. - size, - size, 0,
  28264. - size, size, 0
  28265. ], 3 ) );
  28266. const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
  28267. this.lightPlane = new Line( geometry, material );
  28268. this.add( this.lightPlane );
  28269. geometry = new BufferGeometry();
  28270. geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
  28271. this.targetLine = new Line( geometry, material );
  28272. this.add( this.targetLine );
  28273. this.update();
  28274. }
  28275. dispose() {
  28276. this.lightPlane.geometry.dispose();
  28277. this.lightPlane.material.dispose();
  28278. this.targetLine.geometry.dispose();
  28279. this.targetLine.material.dispose();
  28280. }
  28281. update() {
  28282. _v1$6.setFromMatrixPosition( this.light.matrixWorld );
  28283. _v2$3.setFromMatrixPosition( this.light.target.matrixWorld );
  28284. _v3$1.subVectors( _v2$3, _v1$6 );
  28285. this.lightPlane.lookAt( _v2$3 );
  28286. if ( this.color !== undefined ) {
  28287. this.lightPlane.material.color.set( this.color );
  28288. this.targetLine.material.color.set( this.color );
  28289. } else {
  28290. this.lightPlane.material.color.copy( this.light.color );
  28291. this.targetLine.material.color.copy( this.light.color );
  28292. }
  28293. this.targetLine.lookAt( _v2$3 );
  28294. this.targetLine.scale.z = _v3$1.length();
  28295. }
  28296. }
  28297. const _vector$c = /*@__PURE__*/ new Vector3();
  28298. const _camera = /*@__PURE__*/ new Camera();
  28299. /**
  28300. * - shows frustum, line of sight and up of the camera
  28301. * - suitable for fast updates
  28302. * - based on frustum visualization in lightgl.js shadowmap example
  28303. * http://evanw.github.com/lightgl.js/tests/shadowmap.html
  28304. */
  28305. class CameraHelper extends LineSegments {
  28306. constructor( camera ) {
  28307. const geometry = new BufferGeometry();
  28308. const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
  28309. const vertices = [];
  28310. const colors = [];
  28311. const pointMap = {};
  28312. // colors
  28313. const colorFrustum = new Color( 0xffaa00 );
  28314. const colorCone = new Color( 0xff0000 );
  28315. const colorUp = new Color( 0x00aaff );
  28316. const colorTarget = new Color( 0xffffff );
  28317. const colorCross = new Color( 0x333333 );
  28318. // near
  28319. addLine( 'n1', 'n2', colorFrustum );
  28320. addLine( 'n2', 'n4', colorFrustum );
  28321. addLine( 'n4', 'n3', colorFrustum );
  28322. addLine( 'n3', 'n1', colorFrustum );
  28323. // far
  28324. addLine( 'f1', 'f2', colorFrustum );
  28325. addLine( 'f2', 'f4', colorFrustum );
  28326. addLine( 'f4', 'f3', colorFrustum );
  28327. addLine( 'f3', 'f1', colorFrustum );
  28328. // sides
  28329. addLine( 'n1', 'f1', colorFrustum );
  28330. addLine( 'n2', 'f2', colorFrustum );
  28331. addLine( 'n3', 'f3', colorFrustum );
  28332. addLine( 'n4', 'f4', colorFrustum );
  28333. // cone
  28334. addLine( 'p', 'n1', colorCone );
  28335. addLine( 'p', 'n2', colorCone );
  28336. addLine( 'p', 'n3', colorCone );
  28337. addLine( 'p', 'n4', colorCone );
  28338. // up
  28339. addLine( 'u1', 'u2', colorUp );
  28340. addLine( 'u2', 'u3', colorUp );
  28341. addLine( 'u3', 'u1', colorUp );
  28342. // target
  28343. addLine( 'c', 't', colorTarget );
  28344. addLine( 'p', 'c', colorCross );
  28345. // cross
  28346. addLine( 'cn1', 'cn2', colorCross );
  28347. addLine( 'cn3', 'cn4', colorCross );
  28348. addLine( 'cf1', 'cf2', colorCross );
  28349. addLine( 'cf3', 'cf4', colorCross );
  28350. function addLine( a, b, color ) {
  28351. addPoint( a, color );
  28352. addPoint( b, color );
  28353. }
  28354. function addPoint( id, color ) {
  28355. vertices.push( 0, 0, 0 );
  28356. colors.push( color.r, color.g, color.b );
  28357. if ( pointMap[ id ] === undefined ) {
  28358. pointMap[ id ] = [];
  28359. }
  28360. pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
  28361. }
  28362. geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  28363. geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
  28364. super( geometry, material );
  28365. this.type = 'CameraHelper';
  28366. this.camera = camera;
  28367. if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
  28368. this.matrix = camera.matrixWorld;
  28369. this.matrixAutoUpdate = false;
  28370. this.pointMap = pointMap;
  28371. this.update();
  28372. }
  28373. update() {
  28374. const geometry = this.geometry;
  28375. const pointMap = this.pointMap;
  28376. const w = 1, h = 1;
  28377. // we need just camera projection matrix inverse
  28378. // world matrix must be identity
  28379. _camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
  28380. // center / target
  28381. setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
  28382. setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
  28383. // near
  28384. setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
  28385. setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
  28386. setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
  28387. setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
  28388. // far
  28389. setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );
  28390. setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );
  28391. setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );
  28392. setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );
  28393. // up
  28394. setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
  28395. setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
  28396. setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
  28397. // cross
  28398. setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );
  28399. setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );
  28400. setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
  28401. setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
  28402. setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
  28403. setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
  28404. setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
  28405. setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
  28406. geometry.getAttribute( 'position' ).needsUpdate = true;
  28407. }
  28408. }
  28409. function setPoint( point, pointMap, geometry, camera, x, y, z ) {
  28410. _vector$c.set( x, y, z ).unproject( camera );
  28411. const points = pointMap[ point ];
  28412. if ( points !== undefined ) {
  28413. const position = geometry.getAttribute( 'position' );
  28414. for ( let i = 0, l = points.length; i < l; i ++ ) {
  28415. position.setXYZ( points[ i ], _vector$c.x, _vector$c.y, _vector$c.z );
  28416. }
  28417. }
  28418. }
  28419. const _box$3 = /*@__PURE__*/ new Box3();
  28420. class BoxHelper extends LineSegments {
  28421. constructor( object, color = 0xffff00 ) {
  28422. 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 ] );
  28423. const positions = new Float32Array( 8 * 3 );
  28424. const geometry = new BufferGeometry();
  28425. geometry.setIndex( new BufferAttribute( indices, 1 ) );
  28426. geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
  28427. super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
  28428. this.object = object;
  28429. this.type = 'BoxHelper';
  28430. this.matrixAutoUpdate = false;
  28431. this.update();
  28432. }
  28433. update( object ) {
  28434. if ( object !== undefined ) {
  28435. console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
  28436. }
  28437. if ( this.object !== undefined ) {
  28438. _box$3.setFromObject( this.object );
  28439. }
  28440. if ( _box$3.isEmpty() ) return;
  28441. const min = _box$3.min;
  28442. const max = _box$3.max;
  28443. /*
  28444. 5____4
  28445. 1/___0/|
  28446. | 6__|_7
  28447. 2/___3/
  28448. 0: max.x, max.y, max.z
  28449. 1: min.x, max.y, max.z
  28450. 2: min.x, min.y, max.z
  28451. 3: max.x, min.y, max.z
  28452. 4: max.x, max.y, min.z
  28453. 5: min.x, max.y, min.z
  28454. 6: min.x, min.y, min.z
  28455. 7: max.x, min.y, min.z
  28456. */
  28457. const position = this.geometry.attributes.position;
  28458. const array = position.array;
  28459. array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
  28460. array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
  28461. array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
  28462. array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
  28463. array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
  28464. array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
  28465. array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
  28466. array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
  28467. position.needsUpdate = true;
  28468. this.geometry.computeBoundingSphere();
  28469. }
  28470. setFromObject( object ) {
  28471. this.object = object;
  28472. this.update();
  28473. return this;
  28474. }
  28475. copy( source ) {
  28476. LineSegments.prototype.copy.call( this, source );
  28477. this.object = source.object;
  28478. return this;
  28479. }
  28480. }
  28481. class Box3Helper extends LineSegments {
  28482. constructor( box, color = 0xffff00 ) {
  28483. 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 ] );
  28484. 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 ];
  28485. const geometry = new BufferGeometry();
  28486. geometry.setIndex( new BufferAttribute( indices, 1 ) );
  28487. geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
  28488. super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
  28489. this.box = box;
  28490. this.type = 'Box3Helper';
  28491. this.geometry.computeBoundingSphere();
  28492. }
  28493. updateMatrixWorld( force ) {
  28494. const box = this.box;
  28495. if ( box.isEmpty() ) return;
  28496. box.getCenter( this.position );
  28497. box.getSize( this.scale );
  28498. this.scale.multiplyScalar( 0.5 );
  28499. super.updateMatrixWorld( force );
  28500. }
  28501. }
  28502. class PlaneHelper extends Line {
  28503. constructor( plane, size = 1, hex = 0xffff00 ) {
  28504. const color = hex;
  28505. 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 ];
  28506. const geometry = new BufferGeometry();
  28507. geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
  28508. geometry.computeBoundingSphere();
  28509. super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
  28510. this.type = 'PlaneHelper';
  28511. this.plane = plane;
  28512. this.size = size;
  28513. const positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
  28514. const geometry2 = new BufferGeometry();
  28515. geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
  28516. geometry2.computeBoundingSphere();
  28517. this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
  28518. }
  28519. updateMatrixWorld( force ) {
  28520. let scale = - this.plane.constant;
  28521. if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
  28522. this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
  28523. this.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here
  28524. this.lookAt( this.plane.normal );
  28525. super.updateMatrixWorld( force );
  28526. }
  28527. }
  28528. const _axis = /*@__PURE__*/ new Vector3();
  28529. let _lineGeometry, _coneGeometry;
  28530. class ArrowHelper extends Object3D {
  28531. constructor( dir, origin, length, color, headLength, headWidth ) {
  28532. super();
  28533. // dir is assumed to be normalized
  28534. this.type = 'ArrowHelper';
  28535. if ( dir === undefined ) dir = new Vector3( 0, 0, 1 );
  28536. if ( origin === undefined ) origin = new Vector3( 0, 0, 0 );
  28537. if ( length === undefined ) length = 1;
  28538. if ( color === undefined ) color = 0xffff00;
  28539. if ( headLength === undefined ) headLength = 0.2 * length;
  28540. if ( headWidth === undefined ) headWidth = 0.2 * headLength;
  28541. if ( _lineGeometry === undefined ) {
  28542. _lineGeometry = new BufferGeometry();
  28543. _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
  28544. _coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
  28545. _coneGeometry.translate( 0, - 0.5, 0 );
  28546. }
  28547. this.position.copy( origin );
  28548. this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
  28549. this.line.matrixAutoUpdate = false;
  28550. this.add( this.line );
  28551. this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
  28552. this.cone.matrixAutoUpdate = false;
  28553. this.add( this.cone );
  28554. this.setDirection( dir );
  28555. this.setLength( length, headLength, headWidth );
  28556. }
  28557. setDirection( dir ) {
  28558. // dir is assumed to be normalized
  28559. if ( dir.y > 0.99999 ) {
  28560. this.quaternion.set( 0, 0, 0, 1 );
  28561. } else if ( dir.y < - 0.99999 ) {
  28562. this.quaternion.set( 1, 0, 0, 0 );
  28563. } else {
  28564. _axis.set( dir.z, 0, - dir.x ).normalize();
  28565. const radians = Math.acos( dir.y );
  28566. this.quaternion.setFromAxisAngle( _axis, radians );
  28567. }
  28568. }
  28569. setLength( length, headLength, headWidth ) {
  28570. if ( headLength === undefined ) headLength = 0.2 * length;
  28571. if ( headWidth === undefined ) headWidth = 0.2 * headLength;
  28572. this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
  28573. this.line.updateMatrix();
  28574. this.cone.scale.set( headWidth, headLength, headWidth );
  28575. this.cone.position.y = length;
  28576. this.cone.updateMatrix();
  28577. }
  28578. setColor( color ) {
  28579. this.line.material.color.set( color );
  28580. this.cone.material.color.set( color );
  28581. }
  28582. copy( source ) {
  28583. super.copy( source, false );
  28584. this.line.copy( source.line );
  28585. this.cone.copy( source.cone );
  28586. return this;
  28587. }
  28588. }
  28589. class AxesHelper extends LineSegments {
  28590. constructor( size = 1 ) {
  28591. const vertices = [
  28592. 0, 0, 0, size, 0, 0,
  28593. 0, 0, 0, 0, size, 0,
  28594. 0, 0, 0, 0, 0, size
  28595. ];
  28596. const colors = [
  28597. 1, 0, 0, 1, 0.6, 0,
  28598. 0, 1, 0, 0.6, 1, 0,
  28599. 0, 0, 1, 0, 0.6, 1
  28600. ];
  28601. const geometry = new BufferGeometry();
  28602. geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  28603. geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
  28604. const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
  28605. super( geometry, material );
  28606. this.type = 'AxesHelper';
  28607. }
  28608. }
  28609. const _floatView = new Float32Array( 1 );
  28610. const _int32View = new Int32Array( _floatView.buffer );
  28611. const DataUtils = {
  28612. // Converts float32 to float16 (stored as uint16 value).
  28613. toHalfFloat: function ( val ) {
  28614. // Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
  28615. /* This method is faster than the OpenEXR implementation (very often
  28616. * used, eg. in Ogre), with the additional benefit of rounding, inspired
  28617. * by James Tursa?s half-precision code. */
  28618. _floatView[ 0 ] = val;
  28619. const x = _int32View[ 0 ];
  28620. let bits = ( x >> 16 ) & 0x8000; /* Get the sign */
  28621. let m = ( x >> 12 ) & 0x07ff; /* Keep one extra bit for rounding */
  28622. const e = ( x >> 23 ) & 0xff; /* Using int is faster here */
  28623. /* If zero, or denormal, or exponent underflows too much for a denormal
  28624. * half, return signed zero. */
  28625. if ( e < 103 ) return bits;
  28626. /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
  28627. if ( e > 142 ) {
  28628. bits |= 0x7c00;
  28629. /* If exponent was 0xff and one mantissa bit was set, it means NaN,
  28630. * not Inf, so make sure we set one mantissa bit too. */
  28631. bits |= ( ( e == 255 ) ? 0 : 1 ) && ( x & 0x007fffff );
  28632. return bits;
  28633. }
  28634. /* If exponent underflows but not too much, return a denormal */
  28635. if ( e < 113 ) {
  28636. m |= 0x0800;
  28637. /* Extra rounding may overflow and set mantissa to 0 and exponent
  28638. * to 1, which is OK. */
  28639. bits |= ( m >> ( 114 - e ) ) + ( ( m >> ( 113 - e ) ) & 1 );
  28640. return bits;
  28641. }
  28642. bits |= ( ( e - 112 ) << 10 ) | ( m >> 1 );
  28643. /* Extra rounding. An overflow will set mantissa to 0 and increment
  28644. * the exponent, which is OK. */
  28645. bits += m & 1;
  28646. return bits;
  28647. }
  28648. };
  28649. const LOD_MIN = 4;
  28650. const LOD_MAX = 8;
  28651. const SIZE_MAX = Math.pow( 2, LOD_MAX );
  28652. // The standard deviations (radians) associated with the extra mips. These are
  28653. // chosen to approximate a Trowbridge-Reitz distribution function times the
  28654. // geometric shadowing function. These sigma values squared must match the
  28655. // variance #defines in cube_uv_reflection_fragment.glsl.js.
  28656. const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
  28657. const TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
  28658. // The maximum length of the blur for loop. Smaller sigmas will use fewer
  28659. // samples and exit early, but not recompile the shader.
  28660. const MAX_SAMPLES = 20;
  28661. const ENCODINGS = {
  28662. [ LinearEncoding ]: 0,
  28663. [ sRGBEncoding ]: 1,
  28664. [ RGBEEncoding ]: 2,
  28665. [ RGBM7Encoding ]: 3,
  28666. [ RGBM16Encoding ]: 4,
  28667. [ RGBDEncoding ]: 5,
  28668. [ GammaEncoding ]: 6
  28669. };
  28670. const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
  28671. const { _lodPlanes, _sizeLods, _sigmas } = /*@__PURE__*/ _createPlanes();
  28672. const _clearColor = /*@__PURE__*/ new Color();
  28673. let _oldTarget = null;
  28674. // Golden Ratio
  28675. const PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
  28676. const INV_PHI = 1 / PHI;
  28677. // Vertices of a dodecahedron (except the opposites, which represent the
  28678. // same axis), used as axis directions evenly spread on a sphere.
  28679. const _axisDirections = [
  28680. /*@__PURE__*/ new Vector3( 1, 1, 1 ),
  28681. /*@__PURE__*/ new Vector3( - 1, 1, 1 ),
  28682. /*@__PURE__*/ new Vector3( 1, 1, - 1 ),
  28683. /*@__PURE__*/ new Vector3( - 1, 1, - 1 ),
  28684. /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ),
  28685. /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ),
  28686. /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ),
  28687. /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ),
  28688. /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ),
  28689. /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ];
  28690. /**
  28691. * This class generates a Prefiltered, Mipmapped Radiance Environment Map
  28692. * (PMREM) from a cubeMap environment texture. This allows different levels of
  28693. * blur to be quickly accessed based on material roughness. It is packed into a
  28694. * special CubeUV format that allows us to perform custom interpolation so that
  28695. * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
  28696. * chain, it only goes down to the LOD_MIN level (above), and then creates extra
  28697. * even more filtered 'mips' at the same LOD_MIN resolution, associated with
  28698. * higher roughness levels. In this way we maintain resolution to smoothly
  28699. * interpolate diffuse lighting while limiting sampling computation.
  28700. */
  28701. class PMREMGenerator {
  28702. constructor( renderer ) {
  28703. this._renderer = renderer;
  28704. this._pingPongRenderTarget = null;
  28705. this._blurMaterial = _getBlurShader( MAX_SAMPLES );
  28706. this._equirectShader = null;
  28707. this._cubemapShader = null;
  28708. this._compileMaterial( this._blurMaterial );
  28709. }
  28710. /**
  28711. * Generates a PMREM from a supplied Scene, which can be faster than using an
  28712. * image if networking bandwidth is low. Optional sigma specifies a blur radius
  28713. * in radians to be applied to the scene before PMREM generation. Optional near
  28714. * and far planes ensure the scene is rendered in its entirety (the cubeCamera
  28715. * is placed at the origin).
  28716. */
  28717. fromScene( scene, sigma = 0, near = 0.1, far = 100 ) {
  28718. _oldTarget = this._renderer.getRenderTarget();
  28719. const cubeUVRenderTarget = this._allocateTargets();
  28720. this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
  28721. if ( sigma > 0 ) {
  28722. this._blur( cubeUVRenderTarget, 0, 0, sigma );
  28723. }
  28724. this._applyPMREM( cubeUVRenderTarget );
  28725. this._cleanup( cubeUVRenderTarget );
  28726. return cubeUVRenderTarget;
  28727. }
  28728. /**
  28729. * Generates a PMREM from an equirectangular texture, which can be either LDR
  28730. * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512),
  28731. * as this matches best with the 256 x 256 cubemap output.
  28732. */
  28733. fromEquirectangular( equirectangular ) {
  28734. return this._fromTexture( equirectangular );
  28735. }
  28736. /**
  28737. * Generates a PMREM from an cubemap texture, which can be either LDR
  28738. * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
  28739. * as this matches best with the 256 x 256 cubemap output.
  28740. */
  28741. fromCubemap( cubemap ) {
  28742. return this._fromTexture( cubemap );
  28743. }
  28744. /**
  28745. * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
  28746. * your texture's network fetch for increased concurrency.
  28747. */
  28748. compileCubemapShader() {
  28749. if ( this._cubemapShader === null ) {
  28750. this._cubemapShader = _getCubemapShader();
  28751. this._compileMaterial( this._cubemapShader );
  28752. }
  28753. }
  28754. /**
  28755. * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
  28756. * your texture's network fetch for increased concurrency.
  28757. */
  28758. compileEquirectangularShader() {
  28759. if ( this._equirectShader === null ) {
  28760. this._equirectShader = _getEquirectShader();
  28761. this._compileMaterial( this._equirectShader );
  28762. }
  28763. }
  28764. /**
  28765. * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
  28766. * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
  28767. * one of them will cause any others to also become unusable.
  28768. */
  28769. dispose() {
  28770. this._blurMaterial.dispose();
  28771. if ( this._cubemapShader !== null ) this._cubemapShader.dispose();
  28772. if ( this._equirectShader !== null ) this._equirectShader.dispose();
  28773. for ( let i = 0; i < _lodPlanes.length; i ++ ) {
  28774. _lodPlanes[ i ].dispose();
  28775. }
  28776. }
  28777. // private interface
  28778. _cleanup( outputTarget ) {
  28779. this._pingPongRenderTarget.dispose();
  28780. this._renderer.setRenderTarget( _oldTarget );
  28781. outputTarget.scissorTest = false;
  28782. _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
  28783. }
  28784. _fromTexture( texture ) {
  28785. _oldTarget = this._renderer.getRenderTarget();
  28786. const cubeUVRenderTarget = this._allocateTargets( texture );
  28787. this._textureToCubeUV( texture, cubeUVRenderTarget );
  28788. this._applyPMREM( cubeUVRenderTarget );
  28789. this._cleanup( cubeUVRenderTarget );
  28790. return cubeUVRenderTarget;
  28791. }
  28792. _allocateTargets( texture ) { // warning: null texture is valid
  28793. const params = {
  28794. magFilter: NearestFilter,
  28795. minFilter: NearestFilter,
  28796. generateMipmaps: false,
  28797. type: UnsignedByteType,
  28798. format: RGBEFormat,
  28799. encoding: _isLDR( texture ) ? texture.encoding : RGBEEncoding,
  28800. depthBuffer: false
  28801. };
  28802. const cubeUVRenderTarget = _createRenderTarget( params );
  28803. cubeUVRenderTarget.depthBuffer = texture ? false : true;
  28804. this._pingPongRenderTarget = _createRenderTarget( params );
  28805. return cubeUVRenderTarget;
  28806. }
  28807. _compileMaterial( material ) {
  28808. const tmpMesh = new Mesh( _lodPlanes[ 0 ], material );
  28809. this._renderer.compile( tmpMesh, _flatCamera );
  28810. }
  28811. _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
  28812. const fov = 90;
  28813. const aspect = 1;
  28814. const cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
  28815. const upSign = [ 1, - 1, 1, 1, 1, 1 ];
  28816. const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
  28817. const renderer = this._renderer;
  28818. const outputEncoding = renderer.outputEncoding;
  28819. const toneMapping = renderer.toneMapping;
  28820. renderer.getClearColor( _clearColor );
  28821. const clearAlpha = renderer.getClearAlpha();
  28822. renderer.toneMapping = NoToneMapping;
  28823. renderer.outputEncoding = LinearEncoding;
  28824. let background = scene.background;
  28825. if ( background && background.isColor ) {
  28826. background.convertSRGBToLinear();
  28827. // Convert linear to RGBE
  28828. const maxComponent = Math.max( background.r, background.g, background.b );
  28829. const fExp = Math.min( Math.max( Math.ceil( Math.log2( maxComponent ) ), - 128.0 ), 127.0 );
  28830. background = background.multiplyScalar( Math.pow( 2.0, - fExp ) );
  28831. const alpha = ( fExp + 128.0 ) / 255.0;
  28832. renderer.setClearColor( background, alpha );
  28833. scene.background = null;
  28834. }
  28835. for ( let i = 0; i < 6; i ++ ) {
  28836. const col = i % 3;
  28837. if ( col == 0 ) {
  28838. cubeCamera.up.set( 0, upSign[ i ], 0 );
  28839. cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
  28840. } else if ( col == 1 ) {
  28841. cubeCamera.up.set( 0, 0, upSign[ i ] );
  28842. cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
  28843. } else {
  28844. cubeCamera.up.set( 0, upSign[ i ], 0 );
  28845. cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
  28846. }
  28847. _setViewport( cubeUVRenderTarget,
  28848. col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX );
  28849. renderer.setRenderTarget( cubeUVRenderTarget );
  28850. renderer.render( scene, cubeCamera );
  28851. }
  28852. renderer.toneMapping = toneMapping;
  28853. renderer.outputEncoding = outputEncoding;
  28854. renderer.setClearColor( _clearColor, clearAlpha );
  28855. }
  28856. _textureToCubeUV( texture, cubeUVRenderTarget ) {
  28857. const renderer = this._renderer;
  28858. if ( texture.isCubeTexture ) {
  28859. if ( this._cubemapShader == null ) {
  28860. this._cubemapShader = _getCubemapShader();
  28861. }
  28862. } else {
  28863. if ( this._equirectShader == null ) {
  28864. this._equirectShader = _getEquirectShader();
  28865. }
  28866. }
  28867. const material = texture.isCubeTexture ? this._cubemapShader : this._equirectShader;
  28868. const mesh = new Mesh( _lodPlanes[ 0 ], material );
  28869. const uniforms = material.uniforms;
  28870. uniforms[ 'envMap' ].value = texture;
  28871. if ( ! texture.isCubeTexture ) {
  28872. uniforms[ 'texelSize' ].value.set( 1.0 / texture.image.width, 1.0 / texture.image.height );
  28873. }
  28874. uniforms[ 'inputEncoding' ].value = ENCODINGS[ texture.encoding ];
  28875. uniforms[ 'outputEncoding' ].value = ENCODINGS[ cubeUVRenderTarget.texture.encoding ];
  28876. _setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
  28877. renderer.setRenderTarget( cubeUVRenderTarget );
  28878. renderer.render( mesh, _flatCamera );
  28879. }
  28880. _applyPMREM( cubeUVRenderTarget ) {
  28881. const renderer = this._renderer;
  28882. const autoClear = renderer.autoClear;
  28883. renderer.autoClear = false;
  28884. for ( let i = 1; i < TOTAL_LODS; i ++ ) {
  28885. const sigma = Math.sqrt( _sigmas[ i ] * _sigmas[ i ] - _sigmas[ i - 1 ] * _sigmas[ i - 1 ] );
  28886. const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ];
  28887. this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
  28888. }
  28889. renderer.autoClear = autoClear;
  28890. }
  28891. /**
  28892. * This is a two-pass Gaussian blur for a cubemap. Normally this is done
  28893. * vertically and horizontally, but this breaks down on a cube. Here we apply
  28894. * the blur latitudinally (around the poles), and then longitudinally (towards
  28895. * the poles) to approximate the orthogonally-separable blur. It is least
  28896. * accurate at the poles, but still does a decent job.
  28897. */
  28898. _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
  28899. const pingPongRenderTarget = this._pingPongRenderTarget;
  28900. this._halfBlur(
  28901. cubeUVRenderTarget,
  28902. pingPongRenderTarget,
  28903. lodIn,
  28904. lodOut,
  28905. sigma,
  28906. 'latitudinal',
  28907. poleAxis );
  28908. this._halfBlur(
  28909. pingPongRenderTarget,
  28910. cubeUVRenderTarget,
  28911. lodOut,
  28912. lodOut,
  28913. sigma,
  28914. 'longitudinal',
  28915. poleAxis );
  28916. }
  28917. _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
  28918. const renderer = this._renderer;
  28919. const blurMaterial = this._blurMaterial;
  28920. if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
  28921. console.error(
  28922. 'blur direction must be either latitudinal or longitudinal!' );
  28923. }
  28924. // Number of standard deviations at which to cut off the discrete approximation.
  28925. const STANDARD_DEVIATIONS = 3;
  28926. const blurMesh = new Mesh( _lodPlanes[ lodOut ], blurMaterial );
  28927. const blurUniforms = blurMaterial.uniforms;
  28928. const pixels = _sizeLods[ lodIn ] - 1;
  28929. const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
  28930. const sigmaPixels = sigmaRadians / radiansPerPixel;
  28931. const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
  28932. if ( samples > MAX_SAMPLES ) {
  28933. console.warn( `sigmaRadians, ${
  28934. sigmaRadians}, is too large and will clip, as it requested ${
  28935. samples} samples when the maximum is set to ${MAX_SAMPLES}` );
  28936. }
  28937. const weights = [];
  28938. let sum = 0;
  28939. for ( let i = 0; i < MAX_SAMPLES; ++ i ) {
  28940. const x = i / sigmaPixels;
  28941. const weight = Math.exp( - x * x / 2 );
  28942. weights.push( weight );
  28943. if ( i == 0 ) {
  28944. sum += weight;
  28945. } else if ( i < samples ) {
  28946. sum += 2 * weight;
  28947. }
  28948. }
  28949. for ( let i = 0; i < weights.length; i ++ ) {
  28950. weights[ i ] = weights[ i ] / sum;
  28951. }
  28952. blurUniforms[ 'envMap' ].value = targetIn.texture;
  28953. blurUniforms[ 'samples' ].value = samples;
  28954. blurUniforms[ 'weights' ].value = weights;
  28955. blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
  28956. if ( poleAxis ) {
  28957. blurUniforms[ 'poleAxis' ].value = poleAxis;
  28958. }
  28959. blurUniforms[ 'dTheta' ].value = radiansPerPixel;
  28960. blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn;
  28961. blurUniforms[ 'inputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
  28962. blurUniforms[ 'outputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
  28963. const outputSize = _sizeLods[ lodOut ];
  28964. const x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize );
  28965. const y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) + 2 * outputSize * ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 );
  28966. _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
  28967. renderer.setRenderTarget( targetOut );
  28968. renderer.render( blurMesh, _flatCamera );
  28969. }
  28970. }
  28971. function _isLDR( texture ) {
  28972. if ( texture === undefined || texture.type !== UnsignedByteType ) return false;
  28973. return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding;
  28974. }
  28975. function _createPlanes() {
  28976. const _lodPlanes = [];
  28977. const _sizeLods = [];
  28978. const _sigmas = [];
  28979. let lod = LOD_MAX;
  28980. for ( let i = 0; i < TOTAL_LODS; i ++ ) {
  28981. const sizeLod = Math.pow( 2, lod );
  28982. _sizeLods.push( sizeLod );
  28983. let sigma = 1.0 / sizeLod;
  28984. if ( i > LOD_MAX - LOD_MIN ) {
  28985. sigma = EXTRA_LOD_SIGMA[ i - LOD_MAX + LOD_MIN - 1 ];
  28986. } else if ( i == 0 ) {
  28987. sigma = 0;
  28988. }
  28989. _sigmas.push( sigma );
  28990. const texelSize = 1.0 / ( sizeLod - 1 );
  28991. const min = - texelSize / 2;
  28992. const max = 1 + texelSize / 2;
  28993. const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
  28994. const cubeFaces = 6;
  28995. const vertices = 6;
  28996. const positionSize = 3;
  28997. const uvSize = 2;
  28998. const faceIndexSize = 1;
  28999. const position = new Float32Array( positionSize * vertices * cubeFaces );
  29000. const uv = new Float32Array( uvSize * vertices * cubeFaces );
  29001. const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
  29002. for ( let face = 0; face < cubeFaces; face ++ ) {
  29003. const x = ( face % 3 ) * 2 / 3 - 1;
  29004. const y = face > 2 ? 0 : - 1;
  29005. const coordinates = [
  29006. x, y, 0,
  29007. x + 2 / 3, y, 0,
  29008. x + 2 / 3, y + 1, 0,
  29009. x, y, 0,
  29010. x + 2 / 3, y + 1, 0,
  29011. x, y + 1, 0
  29012. ];
  29013. position.set( coordinates, positionSize * vertices * face );
  29014. uv.set( uv1, uvSize * vertices * face );
  29015. const fill = [ face, face, face, face, face, face ];
  29016. faceIndex.set( fill, faceIndexSize * vertices * face );
  29017. }
  29018. const planes = new BufferGeometry();
  29019. planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
  29020. planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
  29021. planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
  29022. _lodPlanes.push( planes );
  29023. if ( lod > LOD_MIN ) {
  29024. lod --;
  29025. }
  29026. }
  29027. return { _lodPlanes, _sizeLods, _sigmas };
  29028. }
  29029. function _createRenderTarget( params ) {
  29030. const cubeUVRenderTarget = new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
  29031. cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
  29032. cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
  29033. cubeUVRenderTarget.scissorTest = true;
  29034. return cubeUVRenderTarget;
  29035. }
  29036. function _setViewport( target, x, y, width, height ) {
  29037. target.viewport.set( x, y, width, height );
  29038. target.scissor.set( x, y, width, height );
  29039. }
  29040. function _getBlurShader( maxSamples ) {
  29041. const weights = new Float32Array( maxSamples );
  29042. const poleAxis = new Vector3( 0, 1, 0 );
  29043. const shaderMaterial = new RawShaderMaterial( {
  29044. name: 'SphericalGaussianBlur',
  29045. defines: { 'n': maxSamples },
  29046. uniforms: {
  29047. 'envMap': { value: null },
  29048. 'samples': { value: 1 },
  29049. 'weights': { value: weights },
  29050. 'latitudinal': { value: false },
  29051. 'dTheta': { value: 0 },
  29052. 'mipInt': { value: 0 },
  29053. 'poleAxis': { value: poleAxis },
  29054. 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
  29055. 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
  29056. },
  29057. vertexShader: _getCommonVertexShader(),
  29058. fragmentShader: /* glsl */`
  29059. precision mediump float;
  29060. precision mediump int;
  29061. varying vec3 vOutputDirection;
  29062. uniform sampler2D envMap;
  29063. uniform int samples;
  29064. uniform float weights[ n ];
  29065. uniform bool latitudinal;
  29066. uniform float dTheta;
  29067. uniform float mipInt;
  29068. uniform vec3 poleAxis;
  29069. ${ _getEncodings() }
  29070. #define ENVMAP_TYPE_CUBE_UV
  29071. #include <cube_uv_reflection_fragment>
  29072. vec3 getSample( float theta, vec3 axis ) {
  29073. float cosTheta = cos( theta );
  29074. // Rodrigues' axis-angle rotation
  29075. vec3 sampleDirection = vOutputDirection * cosTheta
  29076. + cross( axis, vOutputDirection ) * sin( theta )
  29077. + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
  29078. return bilinearCubeUV( envMap, sampleDirection, mipInt );
  29079. }
  29080. void main() {
  29081. vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
  29082. if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
  29083. axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
  29084. }
  29085. axis = normalize( axis );
  29086. gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
  29087. gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
  29088. for ( int i = 1; i < n; i++ ) {
  29089. if ( i >= samples ) {
  29090. break;
  29091. }
  29092. float theta = dTheta * float( i );
  29093. gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
  29094. gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
  29095. }
  29096. gl_FragColor = linearToOutputTexel( gl_FragColor );
  29097. }
  29098. `,
  29099. blending: NoBlending,
  29100. depthTest: false,
  29101. depthWrite: false
  29102. } );
  29103. return shaderMaterial;
  29104. }
  29105. function _getEquirectShader() {
  29106. const texelSize = new Vector2( 1, 1 );
  29107. const shaderMaterial = new RawShaderMaterial( {
  29108. name: 'EquirectangularToCubeUV',
  29109. uniforms: {
  29110. 'envMap': { value: null },
  29111. 'texelSize': { value: texelSize },
  29112. 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
  29113. 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
  29114. },
  29115. vertexShader: _getCommonVertexShader(),
  29116. fragmentShader: /* glsl */`
  29117. precision mediump float;
  29118. precision mediump int;
  29119. varying vec3 vOutputDirection;
  29120. uniform sampler2D envMap;
  29121. uniform vec2 texelSize;
  29122. ${ _getEncodings() }
  29123. #include <common>
  29124. void main() {
  29125. gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
  29126. vec3 outputDirection = normalize( vOutputDirection );
  29127. vec2 uv = equirectUv( outputDirection );
  29128. vec2 f = fract( uv / texelSize - 0.5 );
  29129. uv -= f * texelSize;
  29130. vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
  29131. uv.x += texelSize.x;
  29132. vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
  29133. uv.y += texelSize.y;
  29134. vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
  29135. uv.x -= texelSize.x;
  29136. vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
  29137. vec3 tm = mix( tl, tr, f.x );
  29138. vec3 bm = mix( bl, br, f.x );
  29139. gl_FragColor.rgb = mix( tm, bm, f.y );
  29140. gl_FragColor = linearToOutputTexel( gl_FragColor );
  29141. }
  29142. `,
  29143. blending: NoBlending,
  29144. depthTest: false,
  29145. depthWrite: false
  29146. } );
  29147. return shaderMaterial;
  29148. }
  29149. function _getCubemapShader() {
  29150. const shaderMaterial = new RawShaderMaterial( {
  29151. name: 'CubemapToCubeUV',
  29152. uniforms: {
  29153. 'envMap': { value: null },
  29154. 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
  29155. 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
  29156. },
  29157. vertexShader: _getCommonVertexShader(),
  29158. fragmentShader: /* glsl */`
  29159. precision mediump float;
  29160. precision mediump int;
  29161. varying vec3 vOutputDirection;
  29162. uniform samplerCube envMap;
  29163. ${ _getEncodings() }
  29164. void main() {
  29165. gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
  29166. gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb;
  29167. gl_FragColor = linearToOutputTexel( gl_FragColor );
  29168. }
  29169. `,
  29170. blending: NoBlending,
  29171. depthTest: false,
  29172. depthWrite: false
  29173. } );
  29174. return shaderMaterial;
  29175. }
  29176. function _getCommonVertexShader() {
  29177. return /* glsl */`
  29178. precision mediump float;
  29179. precision mediump int;
  29180. attribute vec3 position;
  29181. attribute vec2 uv;
  29182. attribute float faceIndex;
  29183. varying vec3 vOutputDirection;
  29184. // RH coordinate system; PMREM face-indexing convention
  29185. vec3 getDirection( vec2 uv, float face ) {
  29186. uv = 2.0 * uv - 1.0;
  29187. vec3 direction = vec3( uv, 1.0 );
  29188. if ( face == 0.0 ) {
  29189. direction = direction.zyx; // ( 1, v, u ) pos x
  29190. } else if ( face == 1.0 ) {
  29191. direction = direction.xzy;
  29192. direction.xz *= -1.0; // ( -u, 1, -v ) pos y
  29193. } else if ( face == 2.0 ) {
  29194. direction.x *= -1.0; // ( -u, v, 1 ) pos z
  29195. } else if ( face == 3.0 ) {
  29196. direction = direction.zyx;
  29197. direction.xz *= -1.0; // ( -1, v, -u ) neg x
  29198. } else if ( face == 4.0 ) {
  29199. direction = direction.xzy;
  29200. direction.xy *= -1.0; // ( -u, -1, v ) neg y
  29201. } else if ( face == 5.0 ) {
  29202. direction.z *= -1.0; // ( u, v, -1 ) neg z
  29203. }
  29204. return direction;
  29205. }
  29206. void main() {
  29207. vOutputDirection = getDirection( uv, faceIndex );
  29208. gl_Position = vec4( position, 1.0 );
  29209. }
  29210. `;
  29211. }
  29212. function _getEncodings() {
  29213. return /* glsl */`
  29214. uniform int inputEncoding;
  29215. uniform int outputEncoding;
  29216. #include <encodings_pars_fragment>
  29217. vec4 inputTexelToLinear( vec4 value ) {
  29218. if ( inputEncoding == 0 ) {
  29219. return value;
  29220. } else if ( inputEncoding == 1 ) {
  29221. return sRGBToLinear( value );
  29222. } else if ( inputEncoding == 2 ) {
  29223. return RGBEToLinear( value );
  29224. } else if ( inputEncoding == 3 ) {
  29225. return RGBMToLinear( value, 7.0 );
  29226. } else if ( inputEncoding == 4 ) {
  29227. return RGBMToLinear( value, 16.0 );
  29228. } else if ( inputEncoding == 5 ) {
  29229. return RGBDToLinear( value, 256.0 );
  29230. } else {
  29231. return GammaToLinear( value, 2.2 );
  29232. }
  29233. }
  29234. vec4 linearToOutputTexel( vec4 value ) {
  29235. if ( outputEncoding == 0 ) {
  29236. return value;
  29237. } else if ( outputEncoding == 1 ) {
  29238. return LinearTosRGB( value );
  29239. } else if ( outputEncoding == 2 ) {
  29240. return LinearToRGBE( value );
  29241. } else if ( outputEncoding == 3 ) {
  29242. return LinearToRGBM( value, 7.0 );
  29243. } else if ( outputEncoding == 4 ) {
  29244. return LinearToRGBM( value, 16.0 );
  29245. } else if ( outputEncoding == 5 ) {
  29246. return LinearToRGBD( value, 256.0 );
  29247. } else {
  29248. return LinearToGamma( value, 2.2 );
  29249. }
  29250. }
  29251. vec4 envMapTexelToLinear( vec4 color ) {
  29252. return inputTexelToLinear( color );
  29253. }
  29254. `;
  29255. }
  29256. function Face4( a, b, c, d, normal, color, materialIndex ) {
  29257. console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
  29258. return new Face3( a, b, c, normal, color, materialIndex );
  29259. }
  29260. const LineStrip = 0;
  29261. const LinePieces = 1;
  29262. const NoColors = 0;
  29263. const FaceColors = 1;
  29264. const VertexColors = 2;
  29265. function MeshFaceMaterial( materials ) {
  29266. console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );
  29267. return materials;
  29268. }
  29269. function MultiMaterial( materials = [] ) {
  29270. console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );
  29271. materials.isMultiMaterial = true;
  29272. materials.materials = materials;
  29273. materials.clone = function () {
  29274. return materials.slice();
  29275. };
  29276. return materials;
  29277. }
  29278. function PointCloud( geometry, material ) {
  29279. console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
  29280. return new Points( geometry, material );
  29281. }
  29282. function Particle( material ) {
  29283. console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );
  29284. return new Sprite$1( material );
  29285. }
  29286. function ParticleSystem( geometry, material ) {
  29287. console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
  29288. return new Points( geometry, material );
  29289. }
  29290. function PointCloudMaterial( parameters ) {
  29291. console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
  29292. return new PointsMaterial( parameters );
  29293. }
  29294. function ParticleBasicMaterial( parameters ) {
  29295. console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
  29296. return new PointsMaterial( parameters );
  29297. }
  29298. function ParticleSystemMaterial( parameters ) {
  29299. console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
  29300. return new PointsMaterial( parameters );
  29301. }
  29302. function Vertex( x, y, z ) {
  29303. console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
  29304. return new Vector3( x, y, z );
  29305. }
  29306. //
  29307. function DynamicBufferAttribute( array, itemSize ) {
  29308. console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setUsage( THREE.DynamicDrawUsage ) instead.' );
  29309. return new BufferAttribute( array, itemSize ).setUsage( DynamicDrawUsage );
  29310. }
  29311. function Int8Attribute( array, itemSize ) {
  29312. console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );
  29313. return new Int8BufferAttribute( array, itemSize );
  29314. }
  29315. function Uint8Attribute( array, itemSize ) {
  29316. console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );
  29317. return new Uint8BufferAttribute( array, itemSize );
  29318. }
  29319. function Uint8ClampedAttribute( array, itemSize ) {
  29320. console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );
  29321. return new Uint8ClampedBufferAttribute( array, itemSize );
  29322. }
  29323. function Int16Attribute( array, itemSize ) {
  29324. console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );
  29325. return new Int16BufferAttribute( array, itemSize );
  29326. }
  29327. function Uint16Attribute( array, itemSize ) {
  29328. console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );
  29329. return new Uint16BufferAttribute( array, itemSize );
  29330. }
  29331. function Int32Attribute( array, itemSize ) {
  29332. console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );
  29333. return new Int32BufferAttribute( array, itemSize );
  29334. }
  29335. function Uint32Attribute( array, itemSize ) {
  29336. console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );
  29337. return new Uint32BufferAttribute( array, itemSize );
  29338. }
  29339. function Float32Attribute( array, itemSize ) {
  29340. console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );
  29341. return new Float32BufferAttribute( array, itemSize );
  29342. }
  29343. function Float64Attribute( array, itemSize ) {
  29344. console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );
  29345. return new Float64BufferAttribute( array, itemSize );
  29346. }
  29347. //
  29348. Curve.create = function ( construct, getPoint ) {
  29349. console.log( 'THREE.Curve.create() has been deprecated' );
  29350. construct.prototype = Object.create( Curve.prototype );
  29351. construct.prototype.constructor = construct;
  29352. construct.prototype.getPoint = getPoint;
  29353. return construct;
  29354. };
  29355. //
  29356. Object.assign( CurvePath.prototype, {
  29357. createPointsGeometry: function ( divisions ) {
  29358. console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
  29359. // generate geometry from path points (for Line or Points objects)
  29360. const pts = this.getPoints( divisions );
  29361. return this.createGeometry( pts );
  29362. },
  29363. createSpacedPointsGeometry: function ( divisions ) {
  29364. console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
  29365. // generate geometry from equidistant sampling along the path
  29366. const pts = this.getSpacedPoints( divisions );
  29367. return this.createGeometry( pts );
  29368. },
  29369. createGeometry: function ( points ) {
  29370. console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
  29371. const geometry = new Geometry();
  29372. for ( let i = 0, l = points.length; i < l; i ++ ) {
  29373. const point = points[ i ];
  29374. geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
  29375. }
  29376. return geometry;
  29377. }
  29378. } );
  29379. //
  29380. Object.assign( Path.prototype, {
  29381. fromPoints: function ( points ) {
  29382. console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
  29383. return this.setFromPoints( points );
  29384. }
  29385. } );
  29386. //
  29387. function ClosedSplineCurve3( points ) {
  29388. console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
  29389. CatmullRomCurve3.call( this, points );
  29390. this.type = 'catmullrom';
  29391. this.closed = true;
  29392. }
  29393. ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
  29394. //
  29395. function SplineCurve3( points ) {
  29396. console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
  29397. CatmullRomCurve3.call( this, points );
  29398. this.type = 'catmullrom';
  29399. }
  29400. SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
  29401. //
  29402. function Spline( points ) {
  29403. console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
  29404. CatmullRomCurve3.call( this, points );
  29405. this.type = 'catmullrom';
  29406. }
  29407. Spline.prototype = Object.create( CatmullRomCurve3.prototype );
  29408. Object.assign( Spline.prototype, {
  29409. initFromArray: function ( /* a */ ) {
  29410. console.error( 'THREE.Spline: .initFromArray() has been removed.' );
  29411. },
  29412. getControlPointsArray: function ( /* optionalTarget */ ) {
  29413. console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
  29414. },
  29415. reparametrizeByArcLength: function ( /* samplingCoef */ ) {
  29416. console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
  29417. }
  29418. } );
  29419. //
  29420. function AxisHelper( size ) {
  29421. console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );
  29422. return new AxesHelper( size );
  29423. }
  29424. function BoundingBoxHelper( object, color ) {
  29425. console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );
  29426. return new BoxHelper( object, color );
  29427. }
  29428. function EdgesHelper( object, hex ) {
  29429. console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );
  29430. return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
  29431. }
  29432. GridHelper.prototype.setColors = function () {
  29433. console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
  29434. };
  29435. SkeletonHelper.prototype.update = function () {
  29436. console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
  29437. };
  29438. function WireframeHelper( object, hex ) {
  29439. console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );
  29440. return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
  29441. }
  29442. //
  29443. Object.assign( Loader.prototype, {
  29444. extractUrlBase: function ( url ) {
  29445. console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
  29446. return LoaderUtils.extractUrlBase( url );
  29447. }
  29448. } );
  29449. Loader.Handlers = {
  29450. add: function ( /* regex, loader */ ) {
  29451. console.error( 'THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.' );
  29452. },
  29453. get: function ( /* file */ ) {
  29454. console.error( 'THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.' );
  29455. }
  29456. };
  29457. function XHRLoader( manager ) {
  29458. console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );
  29459. return new FileLoader( manager );
  29460. }
  29461. function BinaryTextureLoader( manager ) {
  29462. console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );
  29463. return new DataTextureLoader( manager );
  29464. }
  29465. //
  29466. Object.assign( Box2.prototype, {
  29467. center: function ( optionalTarget ) {
  29468. console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
  29469. return this.getCenter( optionalTarget );
  29470. },
  29471. empty: function () {
  29472. console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
  29473. return this.isEmpty();
  29474. },
  29475. isIntersectionBox: function ( box ) {
  29476. console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
  29477. return this.intersectsBox( box );
  29478. },
  29479. size: function ( optionalTarget ) {
  29480. console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
  29481. return this.getSize( optionalTarget );
  29482. }
  29483. } );
  29484. Object.assign( Box3.prototype, {
  29485. center: function ( optionalTarget ) {
  29486. console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
  29487. return this.getCenter( optionalTarget );
  29488. },
  29489. empty: function () {
  29490. console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
  29491. return this.isEmpty();
  29492. },
  29493. isIntersectionBox: function ( box ) {
  29494. console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
  29495. return this.intersectsBox( box );
  29496. },
  29497. isIntersectionSphere: function ( sphere ) {
  29498. console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
  29499. return this.intersectsSphere( sphere );
  29500. },
  29501. size: function ( optionalTarget ) {
  29502. console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
  29503. return this.getSize( optionalTarget );
  29504. }
  29505. } );
  29506. Object.assign( Sphere.prototype, {
  29507. empty: function () {
  29508. console.warn( 'THREE.Sphere: .empty() has been renamed to .isEmpty().' );
  29509. return this.isEmpty();
  29510. },
  29511. } );
  29512. Frustum.prototype.setFromMatrix = function ( m ) {
  29513. console.warn( 'THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().' );
  29514. return this.setFromProjectionMatrix( m );
  29515. };
  29516. Line3.prototype.center = function ( optionalTarget ) {
  29517. console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
  29518. return this.getCenter( optionalTarget );
  29519. };
  29520. Object.assign( MathUtils$1, {
  29521. random16: function () {
  29522. console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
  29523. return Math.random();
  29524. },
  29525. nearestPowerOfTwo: function ( value ) {
  29526. console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
  29527. return MathUtils$1.floorPowerOfTwo( value );
  29528. },
  29529. nextPowerOfTwo: function ( value ) {
  29530. console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
  29531. return MathUtils$1.ceilPowerOfTwo( value );
  29532. }
  29533. } );
  29534. Object.assign( Matrix3.prototype, {
  29535. flattenToArrayOffset: function ( array, offset ) {
  29536. console.warn( 'THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
  29537. return this.toArray( array, offset );
  29538. },
  29539. multiplyVector3: function ( vector ) {
  29540. console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
  29541. return vector.applyMatrix3( this );
  29542. },
  29543. multiplyVector3Array: function ( /* a */ ) {
  29544. console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
  29545. },
  29546. applyToBufferAttribute: function ( attribute ) {
  29547. console.warn( 'THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead.' );
  29548. return attribute.applyMatrix3( this );
  29549. },
  29550. applyToVector3Array: function ( /* array, offset, length */ ) {
  29551. console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
  29552. },
  29553. getInverse: function ( matrix ) {
  29554. console.warn( 'THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
  29555. return this.copy( matrix ).invert();
  29556. }
  29557. } );
  29558. Object.assign( Matrix4.prototype, {
  29559. extractPosition: function ( m ) {
  29560. console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
  29561. return this.copyPosition( m );
  29562. },
  29563. flattenToArrayOffset: function ( array, offset ) {
  29564. console.warn( 'THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
  29565. return this.toArray( array, offset );
  29566. },
  29567. getPosition: function () {
  29568. console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
  29569. return new Vector3().setFromMatrixColumn( this, 3 );
  29570. },
  29571. setRotationFromQuaternion: function ( q ) {
  29572. console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
  29573. return this.makeRotationFromQuaternion( q );
  29574. },
  29575. multiplyToArray: function () {
  29576. console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
  29577. },
  29578. multiplyVector3: function ( vector ) {
  29579. console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
  29580. return vector.applyMatrix4( this );
  29581. },
  29582. multiplyVector4: function ( vector ) {
  29583. console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
  29584. return vector.applyMatrix4( this );
  29585. },
  29586. multiplyVector3Array: function ( /* a */ ) {
  29587. console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
  29588. },
  29589. rotateAxis: function ( v ) {
  29590. console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
  29591. v.transformDirection( this );
  29592. },
  29593. crossVector: function ( vector ) {
  29594. console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
  29595. return vector.applyMatrix4( this );
  29596. },
  29597. translate: function () {
  29598. console.error( 'THREE.Matrix4: .translate() has been removed.' );
  29599. },
  29600. rotateX: function () {
  29601. console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
  29602. },
  29603. rotateY: function () {
  29604. console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
  29605. },
  29606. rotateZ: function () {
  29607. console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
  29608. },
  29609. rotateByAxis: function () {
  29610. console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
  29611. },
  29612. applyToBufferAttribute: function ( attribute ) {
  29613. console.warn( 'THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead.' );
  29614. return attribute.applyMatrix4( this );
  29615. },
  29616. applyToVector3Array: function ( /* array, offset, length */ ) {
  29617. console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
  29618. },
  29619. makeFrustum: function ( left, right, bottom, top, near, far ) {
  29620. console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
  29621. return this.makePerspective( left, right, top, bottom, near, far );
  29622. },
  29623. getInverse: function ( matrix ) {
  29624. console.warn( 'THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
  29625. return this.copy( matrix ).invert();
  29626. }
  29627. } );
  29628. Plane.prototype.isIntersectionLine = function ( line ) {
  29629. console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
  29630. return this.intersectsLine( line );
  29631. };
  29632. Object.assign( Quaternion.prototype, {
  29633. multiplyVector3: function ( vector ) {
  29634. console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
  29635. return vector.applyQuaternion( this );
  29636. },
  29637. inverse: function ( ) {
  29638. console.warn( 'THREE.Quaternion: .inverse() has been renamed to invert().' );
  29639. return this.invert();
  29640. }
  29641. } );
  29642. Object.assign( Ray.prototype, {
  29643. isIntersectionBox: function ( box ) {
  29644. console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
  29645. return this.intersectsBox( box );
  29646. },
  29647. isIntersectionPlane: function ( plane ) {
  29648. console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
  29649. return this.intersectsPlane( plane );
  29650. },
  29651. isIntersectionSphere: function ( sphere ) {
  29652. console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
  29653. return this.intersectsSphere( sphere );
  29654. }
  29655. } );
  29656. Object.assign( Triangle.prototype, {
  29657. area: function () {
  29658. console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
  29659. return this.getArea();
  29660. },
  29661. barycoordFromPoint: function ( point, target ) {
  29662. console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
  29663. return this.getBarycoord( point, target );
  29664. },
  29665. midpoint: function ( target ) {
  29666. console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
  29667. return this.getMidpoint( target );
  29668. },
  29669. normal: function ( target ) {
  29670. console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
  29671. return this.getNormal( target );
  29672. },
  29673. plane: function ( target ) {
  29674. console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
  29675. return this.getPlane( target );
  29676. }
  29677. } );
  29678. Object.assign( Triangle, {
  29679. barycoordFromPoint: function ( point, a, b, c, target ) {
  29680. console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
  29681. return Triangle.getBarycoord( point, a, b, c, target );
  29682. },
  29683. normal: function ( a, b, c, target ) {
  29684. console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
  29685. return Triangle.getNormal( a, b, c, target );
  29686. }
  29687. } );
  29688. Object.assign( Shape.prototype, {
  29689. extractAllPoints: function ( divisions ) {
  29690. console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
  29691. return this.extractPoints( divisions );
  29692. },
  29693. extrude: function ( options ) {
  29694. console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
  29695. return new ExtrudeGeometry( this, options );
  29696. },
  29697. makeGeometry: function ( options ) {
  29698. console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
  29699. return new ShapeGeometry( this, options );
  29700. }
  29701. } );
  29702. Object.assign( Vector2.prototype, {
  29703. fromAttribute: function ( attribute, index, offset ) {
  29704. console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
  29705. return this.fromBufferAttribute( attribute, index, offset );
  29706. },
  29707. distanceToManhattan: function ( v ) {
  29708. console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
  29709. return this.manhattanDistanceTo( v );
  29710. },
  29711. lengthManhattan: function () {
  29712. console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
  29713. return this.manhattanLength();
  29714. }
  29715. } );
  29716. Object.assign( Vector3.prototype, {
  29717. setEulerFromRotationMatrix: function () {
  29718. console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
  29719. },
  29720. setEulerFromQuaternion: function () {
  29721. console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
  29722. },
  29723. getPositionFromMatrix: function ( m ) {
  29724. console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
  29725. return this.setFromMatrixPosition( m );
  29726. },
  29727. getScaleFromMatrix: function ( m ) {
  29728. console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
  29729. return this.setFromMatrixScale( m );
  29730. },
  29731. getColumnFromMatrix: function ( index, matrix ) {
  29732. console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
  29733. return this.setFromMatrixColumn( matrix, index );
  29734. },
  29735. applyProjection: function ( m ) {
  29736. console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
  29737. return this.applyMatrix4( m );
  29738. },
  29739. fromAttribute: function ( attribute, index, offset ) {
  29740. console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
  29741. return this.fromBufferAttribute( attribute, index, offset );
  29742. },
  29743. distanceToManhattan: function ( v ) {
  29744. console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
  29745. return this.manhattanDistanceTo( v );
  29746. },
  29747. lengthManhattan: function () {
  29748. console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
  29749. return this.manhattanLength();
  29750. }
  29751. } );
  29752. Object.assign( Vector4.prototype, {
  29753. fromAttribute: function ( attribute, index, offset ) {
  29754. console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
  29755. return this.fromBufferAttribute( attribute, index, offset );
  29756. },
  29757. lengthManhattan: function () {
  29758. console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
  29759. return this.manhattanLength();
  29760. }
  29761. } );
  29762. //
  29763. Object.assign( Geometry.prototype, {
  29764. computeTangents: function () {
  29765. console.error( 'THREE.Geometry: .computeTangents() has been removed.' );
  29766. },
  29767. computeLineDistances: function () {
  29768. console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );
  29769. },
  29770. applyMatrix: function ( matrix ) {
  29771. console.warn( 'THREE.Geometry: .applyMatrix() has been renamed to .applyMatrix4().' );
  29772. return this.applyMatrix4( matrix );
  29773. }
  29774. } );
  29775. Object.assign( Object3D.prototype, {
  29776. getChildByName: function ( name ) {
  29777. console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
  29778. return this.getObjectByName( name );
  29779. },
  29780. renderDepth: function () {
  29781. console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
  29782. },
  29783. translate: function ( distance, axis ) {
  29784. console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
  29785. return this.translateOnAxis( axis, distance );
  29786. },
  29787. getWorldRotation: function () {
  29788. console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
  29789. },
  29790. applyMatrix: function ( matrix ) {
  29791. console.warn( 'THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4().' );
  29792. return this.applyMatrix4( matrix );
  29793. }
  29794. } );
  29795. Object.defineProperties( Object3D.prototype, {
  29796. eulerOrder: {
  29797. get: function () {
  29798. console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
  29799. return this.rotation.order;
  29800. },
  29801. set: function ( value ) {
  29802. console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
  29803. this.rotation.order = value;
  29804. }
  29805. },
  29806. useQuaternion: {
  29807. get: function () {
  29808. console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
  29809. },
  29810. set: function () {
  29811. console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
  29812. }
  29813. }
  29814. } );
  29815. Object.assign( Mesh.prototype, {
  29816. setDrawMode: function () {
  29817. console.error( 'THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
  29818. },
  29819. } );
  29820. Object.defineProperties( Mesh.prototype, {
  29821. drawMode: {
  29822. get: function () {
  29823. console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.' );
  29824. return TrianglesDrawMode;
  29825. },
  29826. set: function () {
  29827. console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
  29828. }
  29829. }
  29830. } );
  29831. Object.defineProperties( LOD.prototype, {
  29832. objects: {
  29833. get: function () {
  29834. console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
  29835. return this.levels;
  29836. }
  29837. }
  29838. } );
  29839. Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
  29840. get: function () {
  29841. console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
  29842. },
  29843. set: function () {
  29844. console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
  29845. }
  29846. } );
  29847. SkinnedMesh.prototype.initBones = function () {
  29848. console.error( 'THREE.SkinnedMesh: initBones() has been removed.' );
  29849. };
  29850. Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
  29851. get: function () {
  29852. console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
  29853. return this.arcLengthDivisions;
  29854. },
  29855. set: function ( value ) {
  29856. console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
  29857. this.arcLengthDivisions = value;
  29858. }
  29859. } );
  29860. //
  29861. PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
  29862. console.warn( 'THREE.PerspectiveCamera.setLens is deprecated. ' +
  29863. 'Use .setFocalLength and .filmGauge for a photographic setup.' );
  29864. if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
  29865. this.setFocalLength( focalLength );
  29866. };
  29867. //
  29868. Object.defineProperties( Light.prototype, {
  29869. onlyShadow: {
  29870. set: function () {
  29871. console.warn( 'THREE.Light: .onlyShadow has been removed.' );
  29872. }
  29873. },
  29874. shadowCameraFov: {
  29875. set: function ( value ) {
  29876. console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
  29877. this.shadow.camera.fov = value;
  29878. }
  29879. },
  29880. shadowCameraLeft: {
  29881. set: function ( value ) {
  29882. console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
  29883. this.shadow.camera.left = value;
  29884. }
  29885. },
  29886. shadowCameraRight: {
  29887. set: function ( value ) {
  29888. console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
  29889. this.shadow.camera.right = value;
  29890. }
  29891. },
  29892. shadowCameraTop: {
  29893. set: function ( value ) {
  29894. console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
  29895. this.shadow.camera.top = value;
  29896. }
  29897. },
  29898. shadowCameraBottom: {
  29899. set: function ( value ) {
  29900. console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
  29901. this.shadow.camera.bottom = value;
  29902. }
  29903. },
  29904. shadowCameraNear: {
  29905. set: function ( value ) {
  29906. console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
  29907. this.shadow.camera.near = value;
  29908. }
  29909. },
  29910. shadowCameraFar: {
  29911. set: function ( value ) {
  29912. console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
  29913. this.shadow.camera.far = value;
  29914. }
  29915. },
  29916. shadowCameraVisible: {
  29917. set: function () {
  29918. console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
  29919. }
  29920. },
  29921. shadowBias: {
  29922. set: function ( value ) {
  29923. console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
  29924. this.shadow.bias = value;
  29925. }
  29926. },
  29927. shadowDarkness: {
  29928. set: function () {
  29929. console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
  29930. }
  29931. },
  29932. shadowMapWidth: {
  29933. set: function ( value ) {
  29934. console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
  29935. this.shadow.mapSize.width = value;
  29936. }
  29937. },
  29938. shadowMapHeight: {
  29939. set: function ( value ) {
  29940. console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
  29941. this.shadow.mapSize.height = value;
  29942. }
  29943. }
  29944. } );
  29945. //
  29946. Object.defineProperties( BufferAttribute.prototype, {
  29947. length: {
  29948. get: function () {
  29949. console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
  29950. return this.array.length;
  29951. }
  29952. },
  29953. dynamic: {
  29954. get: function () {
  29955. console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
  29956. return this.usage === DynamicDrawUsage;
  29957. },
  29958. set: function ( /* value */ ) {
  29959. console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
  29960. this.setUsage( DynamicDrawUsage );
  29961. }
  29962. }
  29963. } );
  29964. Object.assign( BufferAttribute.prototype, {
  29965. setDynamic: function ( value ) {
  29966. //console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
  29967. this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
  29968. return this;
  29969. },
  29970. copyIndicesArray: function ( /* indices */ ) {
  29971. console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
  29972. },
  29973. setArray: function ( /* array */ ) {
  29974. console.error( 'THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
  29975. }
  29976. } );
  29977. Object.assign( BufferGeometry.prototype, {
  29978. addIndex: function ( index ) {
  29979. console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
  29980. this.setIndex( index );
  29981. },
  29982. addAttribute: function ( name, attribute ) {
  29983. console.warn( 'THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().' );
  29984. if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
  29985. console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
  29986. return this.setAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
  29987. }
  29988. if ( name === 'index' ) {
  29989. console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
  29990. this.setIndex( attribute );
  29991. return this;
  29992. }
  29993. return this.setAttribute( name, attribute );
  29994. },
  29995. addDrawCall: function ( start, count, indexOffset ) {
  29996. if ( indexOffset !== undefined ) {
  29997. console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
  29998. }
  29999. console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
  30000. this.addGroup( start, count );
  30001. },
  30002. clearDrawCalls: function () {
  30003. console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
  30004. this.clearGroups();
  30005. },
  30006. computeTangents: function () {
  30007. console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
  30008. },
  30009. computeOffsets: function () {
  30010. console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
  30011. },
  30012. removeAttribute: function ( name ) {
  30013. console.warn( 'THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().' );
  30014. return this.deleteAttribute( name );
  30015. },
  30016. applyMatrix: function ( matrix ) {
  30017. console.warn( 'THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4().' );
  30018. return this.applyMatrix4( matrix );
  30019. }
  30020. } );
  30021. Object.defineProperties( BufferGeometry.prototype, {
  30022. drawcalls: {
  30023. get: function () {
  30024. console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
  30025. return this.groups;
  30026. }
  30027. },
  30028. offsets: {
  30029. get: function () {
  30030. console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
  30031. return this.groups;
  30032. }
  30033. }
  30034. } );
  30035. Object.defineProperties( InstancedBufferGeometry.prototype, {
  30036. maxInstancedCount: {
  30037. get: function () {
  30038. console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
  30039. return this.instanceCount;
  30040. },
  30041. set: function ( value ) {
  30042. console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
  30043. this.instanceCount = value;
  30044. }
  30045. }
  30046. } );
  30047. Object.defineProperties( Raycaster.prototype, {
  30048. linePrecision: {
  30049. get: function () {
  30050. console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
  30051. return this.params.Line.threshold;
  30052. },
  30053. set: function ( value ) {
  30054. console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
  30055. this.params.Line.threshold = value;
  30056. }
  30057. }
  30058. } );
  30059. Object.defineProperties( InterleavedBuffer.prototype, {
  30060. dynamic: {
  30061. get: function () {
  30062. console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
  30063. return this.usage === DynamicDrawUsage;
  30064. },
  30065. set: function ( value ) {
  30066. console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
  30067. this.setUsage( value );
  30068. }
  30069. }
  30070. } );
  30071. Object.assign( InterleavedBuffer.prototype, {
  30072. setDynamic: function ( value ) {
  30073. console.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' );
  30074. this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
  30075. return this;
  30076. },
  30077. setArray: function ( /* array */ ) {
  30078. console.error( 'THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
  30079. }
  30080. } );
  30081. //
  30082. Object.assign( ExtrudeBufferGeometry.prototype, {
  30083. getArrays: function () {
  30084. console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );
  30085. },
  30086. addShapeList: function () {
  30087. console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );
  30088. },
  30089. addShape: function () {
  30090. console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );
  30091. }
  30092. } );
  30093. //
  30094. Object.assign( Scene.prototype, {
  30095. dispose: function () {
  30096. console.error( 'THREE.Scene: .dispose() has been removed.' );
  30097. }
  30098. } );
  30099. //
  30100. Object.defineProperties( Uniform.prototype, {
  30101. dynamic: {
  30102. set: function () {
  30103. console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
  30104. }
  30105. },
  30106. onUpdate: {
  30107. value: function () {
  30108. console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
  30109. return this;
  30110. }
  30111. }
  30112. } );
  30113. //
  30114. Object.defineProperties( Material.prototype, {
  30115. wrapAround: {
  30116. get: function () {
  30117. console.warn( 'THREE.Material: .wrapAround has been removed.' );
  30118. },
  30119. set: function () {
  30120. console.warn( 'THREE.Material: .wrapAround has been removed.' );
  30121. }
  30122. },
  30123. overdraw: {
  30124. get: function () {
  30125. console.warn( 'THREE.Material: .overdraw has been removed.' );
  30126. },
  30127. set: function () {
  30128. console.warn( 'THREE.Material: .overdraw has been removed.' );
  30129. }
  30130. },
  30131. wrapRGB: {
  30132. get: function () {
  30133. console.warn( 'THREE.Material: .wrapRGB has been removed.' );
  30134. return new Color();
  30135. }
  30136. },
  30137. shading: {
  30138. get: function () {
  30139. console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
  30140. },
  30141. set: function ( value ) {
  30142. console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
  30143. this.flatShading = ( value === FlatShading$1 );
  30144. }
  30145. },
  30146. stencilMask: {
  30147. get: function () {
  30148. console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
  30149. return this.stencilFuncMask;
  30150. },
  30151. set: function ( value ) {
  30152. console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
  30153. this.stencilFuncMask = value;
  30154. }
  30155. }
  30156. } );
  30157. Object.defineProperties( MeshPhongMaterial.prototype, {
  30158. metal: {
  30159. get: function () {
  30160. console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
  30161. return false;
  30162. },
  30163. set: function () {
  30164. console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
  30165. }
  30166. }
  30167. } );
  30168. Object.defineProperties( MeshPhysicalMaterial.prototype, {
  30169. transparency: {
  30170. get: function () {
  30171. console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' );
  30172. return this.transmission;
  30173. },
  30174. set: function ( value ) {
  30175. console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' );
  30176. this.transmission = value;
  30177. }
  30178. }
  30179. } );
  30180. Object.defineProperties( ShaderMaterial.prototype, {
  30181. derivatives: {
  30182. get: function () {
  30183. console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
  30184. return this.extensions.derivatives;
  30185. },
  30186. set: function ( value ) {
  30187. console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
  30188. this.extensions.derivatives = value;
  30189. }
  30190. }
  30191. } );
  30192. //
  30193. Object.assign( WebGLRenderer.prototype, {
  30194. clearTarget: function ( renderTarget, color, depth, stencil ) {
  30195. console.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );
  30196. this.setRenderTarget( renderTarget );
  30197. this.clear( color, depth, stencil );
  30198. },
  30199. animate: function ( callback ) {
  30200. console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );
  30201. this.setAnimationLoop( callback );
  30202. },
  30203. getCurrentRenderTarget: function () {
  30204. console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
  30205. return this.getRenderTarget();
  30206. },
  30207. getMaxAnisotropy: function () {
  30208. console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
  30209. return this.capabilities.getMaxAnisotropy();
  30210. },
  30211. getPrecision: function () {
  30212. console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
  30213. return this.capabilities.precision;
  30214. },
  30215. resetGLState: function () {
  30216. console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
  30217. return this.state.reset();
  30218. },
  30219. supportsFloatTextures: function () {
  30220. console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
  30221. return this.extensions.get( 'OES_texture_float' );
  30222. },
  30223. supportsHalfFloatTextures: function () {
  30224. console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
  30225. return this.extensions.get( 'OES_texture_half_float' );
  30226. },
  30227. supportsStandardDerivatives: function () {
  30228. console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
  30229. return this.extensions.get( 'OES_standard_derivatives' );
  30230. },
  30231. supportsCompressedTextureS3TC: function () {
  30232. console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
  30233. return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
  30234. },
  30235. supportsCompressedTexturePVRTC: function () {
  30236. console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
  30237. return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
  30238. },
  30239. supportsBlendMinMax: function () {
  30240. console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
  30241. return this.extensions.get( 'EXT_blend_minmax' );
  30242. },
  30243. supportsVertexTextures: function () {
  30244. console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
  30245. return this.capabilities.vertexTextures;
  30246. },
  30247. supportsInstancedArrays: function () {
  30248. console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
  30249. return this.extensions.get( 'ANGLE_instanced_arrays' );
  30250. },
  30251. enableScissorTest: function ( boolean ) {
  30252. console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
  30253. this.setScissorTest( boolean );
  30254. },
  30255. initMaterial: function () {
  30256. console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
  30257. },
  30258. addPrePlugin: function () {
  30259. console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
  30260. },
  30261. addPostPlugin: function () {
  30262. console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
  30263. },
  30264. updateShadowMap: function () {
  30265. console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
  30266. },
  30267. setFaceCulling: function () {
  30268. console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
  30269. },
  30270. allocTextureUnit: function () {
  30271. console.warn( 'THREE.WebGLRenderer: .allocTextureUnit() has been removed.' );
  30272. },
  30273. setTexture: function () {
  30274. console.warn( 'THREE.WebGLRenderer: .setTexture() has been removed.' );
  30275. },
  30276. setTexture2D: function () {
  30277. console.warn( 'THREE.WebGLRenderer: .setTexture2D() has been removed.' );
  30278. },
  30279. setTextureCube: function () {
  30280. console.warn( 'THREE.WebGLRenderer: .setTextureCube() has been removed.' );
  30281. },
  30282. getActiveMipMapLevel: function () {
  30283. console.warn( 'THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().' );
  30284. return this.getActiveMipmapLevel();
  30285. }
  30286. } );
  30287. Object.defineProperties( WebGLRenderer.prototype, {
  30288. shadowMapEnabled: {
  30289. get: function () {
  30290. return this.shadowMap.enabled;
  30291. },
  30292. set: function ( value ) {
  30293. console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
  30294. this.shadowMap.enabled = value;
  30295. }
  30296. },
  30297. shadowMapType: {
  30298. get: function () {
  30299. return this.shadowMap.type;
  30300. },
  30301. set: function ( value ) {
  30302. console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
  30303. this.shadowMap.type = value;
  30304. }
  30305. },
  30306. shadowMapCullFace: {
  30307. get: function () {
  30308. console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
  30309. return undefined;
  30310. },
  30311. set: function ( /* value */ ) {
  30312. console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
  30313. }
  30314. },
  30315. context: {
  30316. get: function () {
  30317. console.warn( 'THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.' );
  30318. return this.getContext();
  30319. }
  30320. },
  30321. vr: {
  30322. get: function () {
  30323. console.warn( 'THREE.WebGLRenderer: .vr has been renamed to .xr' );
  30324. return this.xr;
  30325. }
  30326. },
  30327. gammaInput: {
  30328. get: function () {
  30329. console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
  30330. return false;
  30331. },
  30332. set: function () {
  30333. console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
  30334. }
  30335. },
  30336. gammaOutput: {
  30337. get: function () {
  30338. console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
  30339. return false;
  30340. },
  30341. set: function ( value ) {
  30342. console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
  30343. this.outputEncoding = ( value === true ) ? sRGBEncoding : LinearEncoding;
  30344. }
  30345. },
  30346. toneMappingWhitePoint: {
  30347. get: function () {
  30348. console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
  30349. return 1.0;
  30350. },
  30351. set: function () {
  30352. console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
  30353. }
  30354. },
  30355. } );
  30356. Object.defineProperties( WebGLShadowMap.prototype, {
  30357. cullFace: {
  30358. get: function () {
  30359. console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
  30360. return undefined;
  30361. },
  30362. set: function ( /* cullFace */ ) {
  30363. console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
  30364. }
  30365. },
  30366. renderReverseSided: {
  30367. get: function () {
  30368. console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
  30369. return undefined;
  30370. },
  30371. set: function () {
  30372. console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
  30373. }
  30374. },
  30375. renderSingleSided: {
  30376. get: function () {
  30377. console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
  30378. return undefined;
  30379. },
  30380. set: function () {
  30381. console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
  30382. }
  30383. }
  30384. } );
  30385. function WebGLRenderTargetCube( width, height, options ) {
  30386. console.warn( 'THREE.WebGLRenderTargetCube( width, height, options ) is now WebGLCubeRenderTarget( size, options ).' );
  30387. return new WebGLCubeRenderTarget( width, options );
  30388. }
  30389. //
  30390. Object.defineProperties( WebGLRenderTarget.prototype, {
  30391. wrapS: {
  30392. get: function () {
  30393. console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
  30394. return this.texture.wrapS;
  30395. },
  30396. set: function ( value ) {
  30397. console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
  30398. this.texture.wrapS = value;
  30399. }
  30400. },
  30401. wrapT: {
  30402. get: function () {
  30403. console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
  30404. return this.texture.wrapT;
  30405. },
  30406. set: function ( value ) {
  30407. console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
  30408. this.texture.wrapT = value;
  30409. }
  30410. },
  30411. magFilter: {
  30412. get: function () {
  30413. console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
  30414. return this.texture.magFilter;
  30415. },
  30416. set: function ( value ) {
  30417. console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
  30418. this.texture.magFilter = value;
  30419. }
  30420. },
  30421. minFilter: {
  30422. get: function () {
  30423. console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
  30424. return this.texture.minFilter;
  30425. },
  30426. set: function ( value ) {
  30427. console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
  30428. this.texture.minFilter = value;
  30429. }
  30430. },
  30431. anisotropy: {
  30432. get: function () {
  30433. console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
  30434. return this.texture.anisotropy;
  30435. },
  30436. set: function ( value ) {
  30437. console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
  30438. this.texture.anisotropy = value;
  30439. }
  30440. },
  30441. offset: {
  30442. get: function () {
  30443. console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
  30444. return this.texture.offset;
  30445. },
  30446. set: function ( value ) {
  30447. console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
  30448. this.texture.offset = value;
  30449. }
  30450. },
  30451. repeat: {
  30452. get: function () {
  30453. console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
  30454. return this.texture.repeat;
  30455. },
  30456. set: function ( value ) {
  30457. console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
  30458. this.texture.repeat = value;
  30459. }
  30460. },
  30461. format: {
  30462. get: function () {
  30463. console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
  30464. return this.texture.format;
  30465. },
  30466. set: function ( value ) {
  30467. console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
  30468. this.texture.format = value;
  30469. }
  30470. },
  30471. type: {
  30472. get: function () {
  30473. console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
  30474. return this.texture.type;
  30475. },
  30476. set: function ( value ) {
  30477. console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
  30478. this.texture.type = value;
  30479. }
  30480. },
  30481. generateMipmaps: {
  30482. get: function () {
  30483. console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
  30484. return this.texture.generateMipmaps;
  30485. },
  30486. set: function ( value ) {
  30487. console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
  30488. this.texture.generateMipmaps = value;
  30489. }
  30490. }
  30491. } );
  30492. //
  30493. Object.defineProperties( Audio.prototype, {
  30494. load: {
  30495. value: function ( file ) {
  30496. console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
  30497. const scope = this;
  30498. const audioLoader = new AudioLoader();
  30499. audioLoader.load( file, function ( buffer ) {
  30500. scope.setBuffer( buffer );
  30501. } );
  30502. return this;
  30503. }
  30504. },
  30505. startTime: {
  30506. set: function () {
  30507. console.warn( 'THREE.Audio: .startTime is now .play( delay ).' );
  30508. }
  30509. }
  30510. } );
  30511. AudioAnalyser.prototype.getData = function () {
  30512. console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
  30513. return this.getFrequencyData();
  30514. };
  30515. //
  30516. CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
  30517. console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
  30518. return this.update( renderer, scene );
  30519. };
  30520. CubeCamera.prototype.clear = function ( renderer, color, depth, stencil ) {
  30521. console.warn( 'THREE.CubeCamera: .clear() is now .renderTarget.clear().' );
  30522. return this.renderTarget.clear( renderer, color, depth, stencil );
  30523. };
  30524. //
  30525. const GeometryUtils = {
  30526. merge: function ( geometry1, geometry2, materialIndexOffset ) {
  30527. console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
  30528. let matrix;
  30529. if ( geometry2.isMesh ) {
  30530. geometry2.matrixAutoUpdate && geometry2.updateMatrix();
  30531. matrix = geometry2.matrix;
  30532. geometry2 = geometry2.geometry;
  30533. }
  30534. geometry1.merge( geometry2, matrix, materialIndexOffset );
  30535. },
  30536. center: function ( geometry ) {
  30537. console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
  30538. return geometry.center();
  30539. }
  30540. };
  30541. ImageUtils.crossOrigin = undefined;
  30542. ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {
  30543. console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
  30544. const loader = new TextureLoader();
  30545. loader.setCrossOrigin( this.crossOrigin );
  30546. const texture = loader.load( url, onLoad, undefined, onError );
  30547. if ( mapping ) texture.mapping = mapping;
  30548. return texture;
  30549. };
  30550. ImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {
  30551. console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
  30552. const loader = new CubeTextureLoader();
  30553. loader.setCrossOrigin( this.crossOrigin );
  30554. const texture = loader.load( urls, onLoad, undefined, onError );
  30555. if ( mapping ) texture.mapping = mapping;
  30556. return texture;
  30557. };
  30558. ImageUtils.loadCompressedTexture = function () {
  30559. console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
  30560. };
  30561. ImageUtils.loadCompressedTextureCube = function () {
  30562. console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
  30563. };
  30564. //
  30565. function CanvasRenderer() {
  30566. console.error( 'THREE.CanvasRenderer has been removed' );
  30567. }
  30568. //
  30569. function JSONLoader() {
  30570. console.error( 'THREE.JSONLoader has been removed.' );
  30571. }
  30572. //
  30573. const SceneUtils = {
  30574. createMultiMaterialObject: function ( /* geometry, materials */ ) {
  30575. console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
  30576. },
  30577. detach: function ( /* child, parent, scene */ ) {
  30578. console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
  30579. },
  30580. attach: function ( /* child, scene, parent */ ) {
  30581. console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
  30582. }
  30583. };
  30584. //
  30585. function LensFlare() {
  30586. console.error( 'THREE.LensFlare has been moved to /examples/jsm/objects/Lensflare.js' );
  30587. }
  30588. if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
  30589. /* eslint-disable no-undef */
  30590. __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
  30591. revision: REVISION,
  30592. } } ) );
  30593. /* eslint-enable no-undef */
  30594. }
  30595. var THREE$1 = /*#__PURE__*/Object.freeze({
  30596. __proto__: null,
  30597. ACESFilmicToneMapping: ACESFilmicToneMapping,
  30598. AddEquation: AddEquation,
  30599. AddOperation: AddOperation,
  30600. AdditiveAnimationBlendMode: AdditiveAnimationBlendMode,
  30601. AdditiveBlending: AdditiveBlending,
  30602. AlphaFormat: AlphaFormat,
  30603. AlwaysDepth: AlwaysDepth,
  30604. AlwaysStencilFunc: AlwaysStencilFunc,
  30605. AmbientLight: AmbientLight,
  30606. AmbientLightProbe: AmbientLightProbe,
  30607. AnimationClip: AnimationClip,
  30608. AnimationLoader: AnimationLoader,
  30609. AnimationMixer: AnimationMixer,
  30610. AnimationObjectGroup: AnimationObjectGroup,
  30611. AnimationUtils: AnimationUtils,
  30612. ArcCurve: ArcCurve,
  30613. ArrayCamera: ArrayCamera,
  30614. ArrowHelper: ArrowHelper,
  30615. Audio: Audio,
  30616. AudioAnalyser: AudioAnalyser,
  30617. AudioContext: AudioContext,
  30618. AudioListener: AudioListener,
  30619. AudioLoader: AudioLoader,
  30620. AxesHelper: AxesHelper,
  30621. AxisHelper: AxisHelper,
  30622. BackSide: BackSide,
  30623. BasicDepthPacking: BasicDepthPacking,
  30624. BasicShadowMap: BasicShadowMap,
  30625. BinaryTextureLoader: BinaryTextureLoader,
  30626. Bone: Bone,
  30627. BooleanKeyframeTrack: BooleanKeyframeTrack,
  30628. BoundingBoxHelper: BoundingBoxHelper,
  30629. Box2: Box2,
  30630. Box3: Box3,
  30631. Box3Helper: Box3Helper,
  30632. BoxBufferGeometry: BoxBufferGeometry,
  30633. BoxGeometry: BoxGeometry,
  30634. BoxHelper: BoxHelper,
  30635. BufferAttribute: BufferAttribute,
  30636. BufferGeometry: BufferGeometry,
  30637. BufferGeometryLoader: BufferGeometryLoader,
  30638. ByteType: ByteType,
  30639. Cache: Cache,
  30640. Camera: Camera,
  30641. CameraHelper: CameraHelper,
  30642. CanvasRenderer: CanvasRenderer,
  30643. CanvasTexture: CanvasTexture,
  30644. CatmullRomCurve3: CatmullRomCurve3,
  30645. CineonToneMapping: CineonToneMapping,
  30646. CircleBufferGeometry: CircleBufferGeometry,
  30647. CircleGeometry: CircleGeometry,
  30648. ClampToEdgeWrapping: ClampToEdgeWrapping,
  30649. Clock: Clock,
  30650. ClosedSplineCurve3: ClosedSplineCurve3,
  30651. Color: Color,
  30652. ColorKeyframeTrack: ColorKeyframeTrack,
  30653. CompressedTexture: CompressedTexture,
  30654. CompressedTextureLoader: CompressedTextureLoader,
  30655. ConeBufferGeometry: ConeBufferGeometry,
  30656. ConeGeometry: ConeGeometry,
  30657. CubeCamera: CubeCamera,
  30658. CubeGeometry: BoxGeometry,
  30659. CubeReflectionMapping: CubeReflectionMapping,
  30660. CubeRefractionMapping: CubeRefractionMapping,
  30661. CubeTexture: CubeTexture,
  30662. CubeTextureLoader: CubeTextureLoader,
  30663. CubeUVReflectionMapping: CubeUVReflectionMapping,
  30664. CubeUVRefractionMapping: CubeUVRefractionMapping,
  30665. CubicBezierCurve: CubicBezierCurve,
  30666. CubicBezierCurve3: CubicBezierCurve3,
  30667. CubicInterpolant: CubicInterpolant,
  30668. CullFaceBack: CullFaceBack,
  30669. CullFaceFront: CullFaceFront,
  30670. CullFaceFrontBack: CullFaceFrontBack,
  30671. CullFaceNone: CullFaceNone,
  30672. Curve: Curve,
  30673. CurvePath: CurvePath,
  30674. CustomBlending: CustomBlending,
  30675. CustomToneMapping: CustomToneMapping,
  30676. CylinderBufferGeometry: CylinderBufferGeometry,
  30677. CylinderGeometry: CylinderGeometry,
  30678. Cylindrical: Cylindrical,
  30679. DataTexture: DataTexture,
  30680. DataTexture2DArray: DataTexture2DArray,
  30681. DataTexture3D: DataTexture3D,
  30682. DataTextureLoader: DataTextureLoader,
  30683. DataUtils: DataUtils,
  30684. DecrementStencilOp: DecrementStencilOp,
  30685. DecrementWrapStencilOp: DecrementWrapStencilOp,
  30686. DefaultLoadingManager: DefaultLoadingManager,
  30687. DepthFormat: DepthFormat,
  30688. DepthStencilFormat: DepthStencilFormat,
  30689. DepthTexture: DepthTexture,
  30690. DirectionalLight: DirectionalLight,
  30691. DirectionalLightHelper: DirectionalLightHelper,
  30692. DiscreteInterpolant: DiscreteInterpolant,
  30693. DodecahedronBufferGeometry: DodecahedronBufferGeometry,
  30694. DodecahedronGeometry: DodecahedronGeometry,
  30695. DoubleSide: DoubleSide,
  30696. DstAlphaFactor: DstAlphaFactor,
  30697. DstColorFactor: DstColorFactor,
  30698. DynamicBufferAttribute: DynamicBufferAttribute,
  30699. DynamicCopyUsage: DynamicCopyUsage,
  30700. DynamicDrawUsage: DynamicDrawUsage,
  30701. DynamicReadUsage: DynamicReadUsage,
  30702. EdgesGeometry: EdgesGeometry,
  30703. EdgesHelper: EdgesHelper,
  30704. EllipseCurve: EllipseCurve,
  30705. EqualDepth: EqualDepth,
  30706. EqualStencilFunc: EqualStencilFunc,
  30707. EquirectangularReflectionMapping: EquirectangularReflectionMapping,
  30708. EquirectangularRefractionMapping: EquirectangularRefractionMapping,
  30709. Euler: Euler,
  30710. EventDispatcher: EventDispatcher,
  30711. ExtrudeBufferGeometry: ExtrudeBufferGeometry,
  30712. ExtrudeGeometry: ExtrudeGeometry,
  30713. Face3: Face3,
  30714. Face4: Face4,
  30715. FaceColors: FaceColors,
  30716. FileLoader: FileLoader,
  30717. FlatShading: FlatShading$1,
  30718. Float16BufferAttribute: Float16BufferAttribute,
  30719. Float32Attribute: Float32Attribute,
  30720. Float32BufferAttribute: Float32BufferAttribute,
  30721. Float64Attribute: Float64Attribute,
  30722. Float64BufferAttribute: Float64BufferAttribute,
  30723. FloatType: FloatType,
  30724. Fog: Fog,
  30725. FogExp2: FogExp2,
  30726. Font: Font,
  30727. FontLoader: FontLoader,
  30728. FrontSide: FrontSide,
  30729. Frustum: Frustum,
  30730. GLBufferAttribute: GLBufferAttribute,
  30731. GLSL1: GLSL1,
  30732. GLSL3: GLSL3,
  30733. GammaEncoding: GammaEncoding,
  30734. Geometry: Geometry,
  30735. GeometryUtils: GeometryUtils,
  30736. GreaterDepth: GreaterDepth,
  30737. GreaterEqualDepth: GreaterEqualDepth,
  30738. GreaterEqualStencilFunc: GreaterEqualStencilFunc,
  30739. GreaterStencilFunc: GreaterStencilFunc,
  30740. GridHelper: GridHelper,
  30741. Group: Group,
  30742. HalfFloatType: HalfFloatType,
  30743. HemisphereLight: HemisphereLight,
  30744. HemisphereLightHelper: HemisphereLightHelper,
  30745. HemisphereLightProbe: HemisphereLightProbe,
  30746. IcosahedronBufferGeometry: IcosahedronBufferGeometry,
  30747. IcosahedronGeometry: IcosahedronGeometry,
  30748. ImageBitmapLoader: ImageBitmapLoader,
  30749. ImageLoader: ImageLoader,
  30750. ImageUtils: ImageUtils,
  30751. ImmediateRenderObject: ImmediateRenderObject,
  30752. IncrementStencilOp: IncrementStencilOp,
  30753. IncrementWrapStencilOp: IncrementWrapStencilOp,
  30754. InstancedBufferAttribute: InstancedBufferAttribute,
  30755. InstancedBufferGeometry: InstancedBufferGeometry,
  30756. InstancedInterleavedBuffer: InstancedInterleavedBuffer,
  30757. InstancedMesh: InstancedMesh,
  30758. Int16Attribute: Int16Attribute,
  30759. Int16BufferAttribute: Int16BufferAttribute,
  30760. Int32Attribute: Int32Attribute,
  30761. Int32BufferAttribute: Int32BufferAttribute,
  30762. Int8Attribute: Int8Attribute,
  30763. Int8BufferAttribute: Int8BufferAttribute,
  30764. IntType: IntType,
  30765. InterleavedBuffer: InterleavedBuffer,
  30766. InterleavedBufferAttribute: InterleavedBufferAttribute,
  30767. Interpolant: Interpolant,
  30768. InterpolateDiscrete: InterpolateDiscrete,
  30769. InterpolateLinear: InterpolateLinear,
  30770. InterpolateSmooth: InterpolateSmooth,
  30771. InvertStencilOp: InvertStencilOp,
  30772. JSONLoader: JSONLoader,
  30773. KeepStencilOp: KeepStencilOp,
  30774. KeyframeTrack: KeyframeTrack,
  30775. LOD: LOD,
  30776. LatheBufferGeometry: LatheBufferGeometry,
  30777. LatheGeometry: LatheGeometry,
  30778. Layers: Layers,
  30779. LensFlare: LensFlare,
  30780. LessDepth: LessDepth,
  30781. LessEqualDepth: LessEqualDepth,
  30782. LessEqualStencilFunc: LessEqualStencilFunc,
  30783. LessStencilFunc: LessStencilFunc,
  30784. Light: Light,
  30785. LightProbe: LightProbe,
  30786. Line: Line,
  30787. Line3: Line3,
  30788. LineBasicMaterial: LineBasicMaterial,
  30789. LineCurve: LineCurve,
  30790. LineCurve3: LineCurve3,
  30791. LineDashedMaterial: LineDashedMaterial,
  30792. LineLoop: LineLoop,
  30793. LinePieces: LinePieces,
  30794. LineSegments: LineSegments,
  30795. LineStrip: LineStrip,
  30796. LinearEncoding: LinearEncoding,
  30797. LinearFilter: LinearFilter,
  30798. LinearInterpolant: LinearInterpolant,
  30799. LinearMipMapLinearFilter: LinearMipMapLinearFilter,
  30800. LinearMipMapNearestFilter: LinearMipMapNearestFilter,
  30801. LinearMipmapLinearFilter: LinearMipmapLinearFilter,
  30802. LinearMipmapNearestFilter: LinearMipmapNearestFilter,
  30803. LinearToneMapping: LinearToneMapping,
  30804. Loader: Loader,
  30805. LoaderUtils: LoaderUtils,
  30806. LoadingManager: LoadingManager,
  30807. LogLuvEncoding: LogLuvEncoding,
  30808. LoopOnce: LoopOnce,
  30809. LoopPingPong: LoopPingPong,
  30810. LoopRepeat: LoopRepeat,
  30811. LuminanceAlphaFormat: LuminanceAlphaFormat,
  30812. LuminanceFormat: LuminanceFormat,
  30813. MOUSE: MOUSE,
  30814. Material: Material,
  30815. MaterialLoader: MaterialLoader,
  30816. Math: MathUtils$1,
  30817. MathUtils: MathUtils$1,
  30818. Matrix3: Matrix3,
  30819. Matrix4: Matrix4,
  30820. MaxEquation: MaxEquation,
  30821. Mesh: Mesh,
  30822. MeshBasicMaterial: MeshBasicMaterial,
  30823. MeshDepthMaterial: MeshDepthMaterial,
  30824. MeshDistanceMaterial: MeshDistanceMaterial,
  30825. MeshFaceMaterial: MeshFaceMaterial,
  30826. MeshLambertMaterial: MeshLambertMaterial,
  30827. MeshMatcapMaterial: MeshMatcapMaterial,
  30828. MeshNormalMaterial: MeshNormalMaterial,
  30829. MeshPhongMaterial: MeshPhongMaterial,
  30830. MeshPhysicalMaterial: MeshPhysicalMaterial,
  30831. MeshStandardMaterial: MeshStandardMaterial,
  30832. MeshToonMaterial: MeshToonMaterial,
  30833. MinEquation: MinEquation,
  30834. MirroredRepeatWrapping: MirroredRepeatWrapping,
  30835. MixOperation: MixOperation,
  30836. MultiMaterial: MultiMaterial,
  30837. MultiplyBlending: MultiplyBlending,
  30838. MultiplyOperation: MultiplyOperation,
  30839. NearestFilter: NearestFilter,
  30840. NearestMipMapLinearFilter: NearestMipMapLinearFilter,
  30841. NearestMipMapNearestFilter: NearestMipMapNearestFilter,
  30842. NearestMipmapLinearFilter: NearestMipmapLinearFilter,
  30843. NearestMipmapNearestFilter: NearestMipmapNearestFilter,
  30844. NeverDepth: NeverDepth,
  30845. NeverStencilFunc: NeverStencilFunc,
  30846. NoBlending: NoBlending,
  30847. NoColors: NoColors,
  30848. NoToneMapping: NoToneMapping,
  30849. NormalAnimationBlendMode: NormalAnimationBlendMode,
  30850. NormalBlending: NormalBlending,
  30851. NotEqualDepth: NotEqualDepth,
  30852. NotEqualStencilFunc: NotEqualStencilFunc,
  30853. NumberKeyframeTrack: NumberKeyframeTrack,
  30854. Object3D: Object3D,
  30855. ObjectLoader: ObjectLoader,
  30856. ObjectSpaceNormalMap: ObjectSpaceNormalMap,
  30857. OctahedronBufferGeometry: OctahedronBufferGeometry,
  30858. OctahedronGeometry: OctahedronGeometry,
  30859. OneFactor: OneFactor,
  30860. OneMinusDstAlphaFactor: OneMinusDstAlphaFactor,
  30861. OneMinusDstColorFactor: OneMinusDstColorFactor,
  30862. OneMinusSrcAlphaFactor: OneMinusSrcAlphaFactor,
  30863. OneMinusSrcColorFactor: OneMinusSrcColorFactor,
  30864. OrthographicCamera: OrthographicCamera,
  30865. PCFShadowMap: PCFShadowMap,
  30866. PCFSoftShadowMap: PCFSoftShadowMap,
  30867. PMREMGenerator: PMREMGenerator,
  30868. ParametricBufferGeometry: ParametricBufferGeometry,
  30869. ParametricGeometry: ParametricGeometry,
  30870. Particle: Particle,
  30871. ParticleBasicMaterial: ParticleBasicMaterial,
  30872. ParticleSystem: ParticleSystem,
  30873. ParticleSystemMaterial: ParticleSystemMaterial,
  30874. Path: Path,
  30875. PerspectiveCamera: PerspectiveCamera,
  30876. Plane: Plane,
  30877. PlaneBufferGeometry: PlaneBufferGeometry,
  30878. PlaneGeometry: PlaneGeometry,
  30879. PlaneHelper: PlaneHelper,
  30880. PointCloud: PointCloud,
  30881. PointCloudMaterial: PointCloudMaterial,
  30882. PointLight: PointLight,
  30883. PointLightHelper: PointLightHelper,
  30884. Points: Points,
  30885. PointsMaterial: PointsMaterial,
  30886. PolarGridHelper: PolarGridHelper,
  30887. PolyhedronBufferGeometry: PolyhedronBufferGeometry,
  30888. PolyhedronGeometry: PolyhedronGeometry,
  30889. PositionalAudio: PositionalAudio,
  30890. PropertyBinding: PropertyBinding,
  30891. PropertyMixer: PropertyMixer,
  30892. QuadraticBezierCurve: QuadraticBezierCurve,
  30893. QuadraticBezierCurve3: QuadraticBezierCurve3,
  30894. Quaternion: Quaternion,
  30895. QuaternionKeyframeTrack: QuaternionKeyframeTrack,
  30896. QuaternionLinearInterpolant: QuaternionLinearInterpolant,
  30897. REVISION: REVISION,
  30898. RGBADepthPacking: RGBADepthPacking,
  30899. RGBAFormat: RGBAFormat,
  30900. RGBAIntegerFormat: RGBAIntegerFormat,
  30901. RGBA_ASTC_10x10_Format: RGBA_ASTC_10x10_Format,
  30902. RGBA_ASTC_10x5_Format: RGBA_ASTC_10x5_Format,
  30903. RGBA_ASTC_10x6_Format: RGBA_ASTC_10x6_Format,
  30904. RGBA_ASTC_10x8_Format: RGBA_ASTC_10x8_Format,
  30905. RGBA_ASTC_12x10_Format: RGBA_ASTC_12x10_Format,
  30906. RGBA_ASTC_12x12_Format: RGBA_ASTC_12x12_Format,
  30907. RGBA_ASTC_4x4_Format: RGBA_ASTC_4x4_Format,
  30908. RGBA_ASTC_5x4_Format: RGBA_ASTC_5x4_Format,
  30909. RGBA_ASTC_5x5_Format: RGBA_ASTC_5x5_Format,
  30910. RGBA_ASTC_6x5_Format: RGBA_ASTC_6x5_Format,
  30911. RGBA_ASTC_6x6_Format: RGBA_ASTC_6x6_Format,
  30912. RGBA_ASTC_8x5_Format: RGBA_ASTC_8x5_Format,
  30913. RGBA_ASTC_8x6_Format: RGBA_ASTC_8x6_Format,
  30914. RGBA_ASTC_8x8_Format: RGBA_ASTC_8x8_Format,
  30915. RGBA_BPTC_Format: RGBA_BPTC_Format,
  30916. RGBA_ETC2_EAC_Format: RGBA_ETC2_EAC_Format,
  30917. RGBA_PVRTC_2BPPV1_Format: RGBA_PVRTC_2BPPV1_Format,
  30918. RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format,
  30919. RGBA_S3TC_DXT1_Format: RGBA_S3TC_DXT1_Format$1,
  30920. RGBA_S3TC_DXT3_Format: RGBA_S3TC_DXT3_Format,
  30921. RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format$1,
  30922. RGBDEncoding: RGBDEncoding,
  30923. RGBEEncoding: RGBEEncoding,
  30924. RGBEFormat: RGBEFormat,
  30925. RGBFormat: RGBFormat,
  30926. RGBIntegerFormat: RGBIntegerFormat,
  30927. RGBM16Encoding: RGBM16Encoding,
  30928. RGBM7Encoding: RGBM7Encoding,
  30929. RGB_ETC1_Format: RGB_ETC1_Format,
  30930. RGB_ETC2_Format: RGB_ETC2_Format,
  30931. RGB_PVRTC_2BPPV1_Format: RGB_PVRTC_2BPPV1_Format,
  30932. RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format,
  30933. RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format,
  30934. RGFormat: RGFormat,
  30935. RGIntegerFormat: RGIntegerFormat,
  30936. RawShaderMaterial: RawShaderMaterial,
  30937. Ray: Ray,
  30938. Raycaster: Raycaster,
  30939. RectAreaLight: RectAreaLight,
  30940. RedFormat: RedFormat,
  30941. RedIntegerFormat: RedIntegerFormat,
  30942. ReinhardToneMapping: ReinhardToneMapping,
  30943. RepeatWrapping: RepeatWrapping,
  30944. ReplaceStencilOp: ReplaceStencilOp,
  30945. ReverseSubtractEquation: ReverseSubtractEquation,
  30946. RingBufferGeometry: RingBufferGeometry,
  30947. RingGeometry: RingGeometry,
  30948. SRGB8_ALPHA8_ASTC_10x10_Format: SRGB8_ALPHA8_ASTC_10x10_Format,
  30949. SRGB8_ALPHA8_ASTC_10x5_Format: SRGB8_ALPHA8_ASTC_10x5_Format,
  30950. SRGB8_ALPHA8_ASTC_10x6_Format: SRGB8_ALPHA8_ASTC_10x6_Format,
  30951. SRGB8_ALPHA8_ASTC_10x8_Format: SRGB8_ALPHA8_ASTC_10x8_Format,
  30952. SRGB8_ALPHA8_ASTC_12x10_Format: SRGB8_ALPHA8_ASTC_12x10_Format,
  30953. SRGB8_ALPHA8_ASTC_12x12_Format: SRGB8_ALPHA8_ASTC_12x12_Format,
  30954. SRGB8_ALPHA8_ASTC_4x4_Format: SRGB8_ALPHA8_ASTC_4x4_Format,
  30955. SRGB8_ALPHA8_ASTC_5x4_Format: SRGB8_ALPHA8_ASTC_5x4_Format,
  30956. SRGB8_ALPHA8_ASTC_5x5_Format: SRGB8_ALPHA8_ASTC_5x5_Format,
  30957. SRGB8_ALPHA8_ASTC_6x5_Format: SRGB8_ALPHA8_ASTC_6x5_Format,
  30958. SRGB8_ALPHA8_ASTC_6x6_Format: SRGB8_ALPHA8_ASTC_6x6_Format,
  30959. SRGB8_ALPHA8_ASTC_8x5_Format: SRGB8_ALPHA8_ASTC_8x5_Format,
  30960. SRGB8_ALPHA8_ASTC_8x6_Format: SRGB8_ALPHA8_ASTC_8x6_Format,
  30961. SRGB8_ALPHA8_ASTC_8x8_Format: SRGB8_ALPHA8_ASTC_8x8_Format,
  30962. Scene: Scene,
  30963. SceneUtils: SceneUtils,
  30964. ShaderChunk: ShaderChunk,
  30965. ShaderLib: ShaderLib,
  30966. ShaderMaterial: ShaderMaterial,
  30967. ShadowMaterial: ShadowMaterial,
  30968. Shape: Shape,
  30969. ShapeBufferGeometry: ShapeBufferGeometry,
  30970. ShapeGeometry: ShapeGeometry,
  30971. ShapePath: ShapePath,
  30972. ShapeUtils: ShapeUtils,
  30973. ShortType: ShortType,
  30974. Skeleton: Skeleton,
  30975. SkeletonHelper: SkeletonHelper,
  30976. SkinnedMesh: SkinnedMesh,
  30977. SmoothShading: SmoothShading,
  30978. Sphere: Sphere,
  30979. SphereBufferGeometry: SphereBufferGeometry,
  30980. SphereGeometry: SphereGeometry,
  30981. Spherical: Spherical,
  30982. SphericalHarmonics3: SphericalHarmonics3,
  30983. Spline: Spline,
  30984. SplineCurve: SplineCurve,
  30985. SplineCurve3: SplineCurve3,
  30986. SpotLight: SpotLight,
  30987. SpotLightHelper: SpotLightHelper,
  30988. Sprite: Sprite$1,
  30989. SpriteMaterial: SpriteMaterial,
  30990. SrcAlphaFactor: SrcAlphaFactor,
  30991. SrcAlphaSaturateFactor: SrcAlphaSaturateFactor,
  30992. SrcColorFactor: SrcColorFactor,
  30993. StaticCopyUsage: StaticCopyUsage,
  30994. StaticDrawUsage: StaticDrawUsage,
  30995. StaticReadUsage: StaticReadUsage,
  30996. StereoCamera: StereoCamera,
  30997. StreamCopyUsage: StreamCopyUsage,
  30998. StreamDrawUsage: StreamDrawUsage,
  30999. StreamReadUsage: StreamReadUsage,
  31000. StringKeyframeTrack: StringKeyframeTrack,
  31001. SubtractEquation: SubtractEquation,
  31002. SubtractiveBlending: SubtractiveBlending,
  31003. TOUCH: TOUCH,
  31004. TangentSpaceNormalMap: TangentSpaceNormalMap,
  31005. TetrahedronBufferGeometry: TetrahedronBufferGeometry,
  31006. TetrahedronGeometry: TetrahedronGeometry,
  31007. TextBufferGeometry: TextBufferGeometry,
  31008. TextGeometry: TextGeometry,
  31009. Texture: Texture,
  31010. TextureLoader: TextureLoader,
  31011. TorusBufferGeometry: TorusBufferGeometry,
  31012. TorusGeometry: TorusGeometry,
  31013. TorusKnotBufferGeometry: TorusKnotBufferGeometry,
  31014. TorusKnotGeometry: TorusKnotGeometry,
  31015. Triangle: Triangle,
  31016. TriangleFanDrawMode: TriangleFanDrawMode,
  31017. TriangleStripDrawMode: TriangleStripDrawMode,
  31018. TrianglesDrawMode: TrianglesDrawMode,
  31019. TubeBufferGeometry: TubeBufferGeometry,
  31020. TubeGeometry: TubeGeometry,
  31021. UVMapping: UVMapping,
  31022. Uint16Attribute: Uint16Attribute,
  31023. Uint16BufferAttribute: Uint16BufferAttribute,
  31024. Uint32Attribute: Uint32Attribute,
  31025. Uint32BufferAttribute: Uint32BufferAttribute,
  31026. Uint8Attribute: Uint8Attribute,
  31027. Uint8BufferAttribute: Uint8BufferAttribute,
  31028. Uint8ClampedAttribute: Uint8ClampedAttribute,
  31029. Uint8ClampedBufferAttribute: Uint8ClampedBufferAttribute,
  31030. Uniform: Uniform,
  31031. UniformsLib: UniformsLib,
  31032. UniformsUtils: UniformsUtils,
  31033. UnsignedByteType: UnsignedByteType,
  31034. UnsignedInt248Type: UnsignedInt248Type$1,
  31035. UnsignedIntType: UnsignedIntType,
  31036. UnsignedShort4444Type: UnsignedShort4444Type,
  31037. UnsignedShort5551Type: UnsignedShort5551Type,
  31038. UnsignedShort565Type: UnsignedShort565Type,
  31039. UnsignedShortType: UnsignedShortType,
  31040. VSMShadowMap: VSMShadowMap,
  31041. Vector2: Vector2,
  31042. Vector3: Vector3,
  31043. Vector4: Vector4,
  31044. VectorKeyframeTrack: VectorKeyframeTrack,
  31045. Vertex: Vertex,
  31046. VertexColors: VertexColors,
  31047. VideoTexture: VideoTexture,
  31048. WebGL1Renderer: WebGL1Renderer,
  31049. WebGLCubeRenderTarget: WebGLCubeRenderTarget,
  31050. WebGLMultisampleRenderTarget: WebGLMultisampleRenderTarget,
  31051. WebGLRenderTarget: WebGLRenderTarget,
  31052. WebGLRenderTargetCube: WebGLRenderTargetCube,
  31053. WebGLRenderer: WebGLRenderer,
  31054. WebGLUtils: WebGLUtils,
  31055. WireframeGeometry: WireframeGeometry,
  31056. WireframeHelper: WireframeHelper,
  31057. WrapAroundEnding: WrapAroundEnding,
  31058. XHRLoader: XHRLoader,
  31059. ZeroCurvatureEnding: ZeroCurvatureEnding,
  31060. ZeroFactor: ZeroFactor,
  31061. ZeroSlopeEnding: ZeroSlopeEnding,
  31062. ZeroStencilOp: ZeroStencilOp,
  31063. sRGBEncoding: sRGBEncoding
  31064. });
  31065. var points = [];
  31066. var lines = [];
  31067. var rings = [];
  31068. var precision = 0.1; //容错精度 //正常是0.01 但是在编辑时容易出现交错的线看不出来,导致需要getSliceLines 然后多出新增点
  31069. var getPoint = function(o, type){
  31070. var point;
  31071. if(typeof o == "string" || typeof o == "number")point = points.find(p=> p.ids.includes(o));
  31072. else {
  31073. point = points.find(p=> math.closeTo(p.x , o.x, precision) && math.closeTo(p.y , o.y, precision) );
  31074. if(!point) point = new Point(o.x, o.y,{record:true, id:o.id}, type);
  31075. else {
  31076. //console.log('addPoint', point, o)
  31077. point.addPoint(o.id);
  31078. }
  31079. }
  31080. if(!point){
  31081. console.log("no point!");
  31082. }
  31083. return point
  31084. };
  31085. var getLine = function(id){
  31086. return lines.find(line=> line.ids.includes(id));
  31087. };
  31088. var getAngleInfo = function(points){
  31089. var info = {};
  31090. info.angle = points[1].clone().sub(points[0]).angle();
  31091. if(math.closeTo(info.angle, Math.PI*2)){ //如360-0.01
  31092. info.angle -= Math.PI*2; //有可能得到负数-0.001
  31093. }else if(info.angle > Math.PI || math.closeTo(info.angle, Math.PI)){//如180+-0.01
  31094. info.angle -= Math.PI;
  31095. info.reverse = true;
  31096. }
  31097. return info //结果大约是 0 - 3.14
  31098. };
  31099. class Point extends Vector2{
  31100. constructor(x, y, o={}){
  31101. super(x, y);
  31102. if(o.record){
  31103. this.id = o.id;
  31104. if(this.id == void 0) this.id = "add_"+points.length;
  31105. this.ids = [this.id] ;//存储拥有该坐标的点原始数据的id
  31106. points.push(this);
  31107. }
  31108. this.type = o.type || "";
  31109. this.lines = [];
  31110. }
  31111. addPoint(id){
  31112. this.ids.push(id);
  31113. }
  31114. searchLineByFactor(dir, type, comeLine){
  31115. var lines = this.lines.filter(line=>line.searchTime<2);
  31116. if(lines.length==0)return;
  31117. else if(lines.length==1)return lines[0];
  31118. else lines = lines.filter(line=>line!=comeLine);
  31119. if(lines.length==1)return lines[0];
  31120. var result;
  31121. lines.forEach(line=>{
  31122. var vec = line.getVector();
  31123. if(line.points[1] == this) vec.negate();
  31124. var factor = math.getVec2Angle(dir, vec);
  31125. if(new Vector3(dir.x, dir.y, 0).cross(new Vector3(vec.x, vec.y, 0)).z<0) factor*= -1; /////
  31126. if(!result){
  31127. result = {line, factor};
  31128. }
  31129. else {
  31130. if(type == "min" && factor<result.factor || type == "max" && factor>result.factor) result = {line, factor};
  31131. }
  31132. });
  31133. return result.line;
  31134. }
  31135. }
  31136. var lineLen=0;
  31137. class Line$1{
  31138. constructor(o){
  31139. if(o.points[0] == o.points[1])return;
  31140. this.points = o.points;
  31141. this.type = o.type || 'line';
  31142. if(this.type == 'line'){
  31143. var oldLine = lines.find(line=>line.points.includes(o.points[0]) && line.points.includes(o.points[1]));
  31144. if(oldLine){
  31145. o.id != void 0 && oldLine.ids.push(o.id);
  31146. return oldLine;
  31147. }
  31148. this.id = o.id == void 0 ? ("line"+lineLen ++) : o.id;
  31149. this.ids = [this.id];
  31150. o.dontWriteToPoint || this.points.forEach((point)=>{point.lines.push(this);});
  31151. o.isChild || lines.push(this);
  31152. this.searchTime = 0; // 最多两次
  31153. }
  31154. this.children = [];//分割
  31155. this.parents = [];//分割
  31156. this.match = [];
  31157. }
  31158. getAngleInfo(){
  31159. var angleInfo = getAngleInfo(this.points);
  31160. this.angle = angleInfo.angle;
  31161. this.reverse = angleInfo.reverse;
  31162. }
  31163. getIntersectWithLine(line, precision){
  31164. var joint = line.points.find(point=>this.points.includes(point));
  31165. if(joint)return {point:joint, type:"joint"};
  31166. var intersect = math.isLineIntersect( line.points , this.points , false, precision );
  31167. if(intersect) return {point: intersect, type:"intersect"};
  31168. }
  31169. writeToPoint(){
  31170. this.points.forEach((point)=>{point.lines.includes(this) || point.lines.push(this);});
  31171. }
  31172. checkIfParent(line){
  31173. if(this == line){
  31174. return true;//原因就是slice的点和端点很近 误差导致
  31175. }
  31176. else return this.parents.find(e=>e.checkIfParent(line))
  31177. }
  31178. splitByPoint(point){
  31179. var line1 = new Line$1({points:[point, this.points[0]], dontWriteToPoint:true, hasntsure:true});
  31180. var line2 = new Line$1({points:[point, this.points[1]], dontWriteToPoint:true, hasntsure:true});
  31181. if(!line1.points || !line2.points){//有至少一个是点相同的,没写到group.lines里
  31182. console.warn('splitByPoint 线有点相同');
  31183. return;
  31184. }
  31185. if(this.checkIfParent(line1)||this.checkIfParent(line2) || line1.checkIfParent(this) || line2.checkIfParent(this)){
  31186. console.warn("splitByPoint 发现parent和children一样");//,请检查getSliceWalls,尤其 if(math.closeTo(line1.angle,line2.angle)){ 处
  31187. return;
  31188. }
  31189. var deal = (line)=>{
  31190. this.children.push(line);
  31191. line.parents.push(this);
  31192. if(!lines.includes(line))lines.push(line);
  31193. line.writeToPoint();
  31194. };
  31195. deal(line1);
  31196. deal(line2);
  31197. var index = this.points[0].lines.indexOf(this);
  31198. index > -1 && this.points[0].lines.splice(index,1);
  31199. var index = this.points[1].lines.indexOf(this);
  31200. index > -1 && this.points[1].lines.splice(index,1);
  31201. return [line1,line2]
  31202. }
  31203. splitByPoints(points){
  31204. points = points.map(point=>{return {dis:point.distanceTo(this.points[0]), point:point}});
  31205. points.sort((point1, point2)=>{return point1.dis - point2.dis});
  31206. var children = [];
  31207. points.forEach((point, index)=>{
  31208. var line1 = new Line$1({points:[point.point, index==0?this.points[0]:points[index-1].point ],group:this.group , dontWriteToPoint:true, hasntsure:true});
  31209. children.push(line1);
  31210. });
  31211. var line2 = new Line$1({points:[points[points.length-1].point, this.points[1] ],group:this.group , dontWriteToPoint:true, hasntsure:true});
  31212. children.push(line2);
  31213. var a = children.find(line=> !line.points || this.checkIfParent(line) || line.checkIfParent(this));
  31214. if(a){
  31215. console.error("splitByPoints return");
  31216. return;
  31217. }
  31218. children.forEach(line=>{
  31219. this.children.push(line);
  31220. line.parents.push(this);
  31221. if(!lines.includes(line))lines.push(line);
  31222. line.writeToPoint();
  31223. line.writeToPoint();
  31224. });
  31225. var index = this.points[0].lines.indexOf(this);
  31226. index > -1 && this.points[0].lines.splice(index,1);
  31227. var index = this.points[1].lines.indexOf(this);
  31228. index > -1 && this.points[1].lines.splice(index,1);
  31229. }
  31230. getAllSlices(){//如果有被分割的片段 就返回片段,否则返回自身
  31231. var children = [];
  31232. var traverse = function(elem){
  31233. if(elem.children.length == 0) children.push(elem);
  31234. else elem.children.forEach(traverse);
  31235. };
  31236. traverse(this);
  31237. return children
  31238. }
  31239. getVector(){
  31240. return this.points[1].clone().sub(this.points[0]);
  31241. }
  31242. getLength(){
  31243. return this.points[0].distanceTo(this.points[1])
  31244. }
  31245. getCenter(){
  31246. return this.points[1].clone().add(this.points[0]).multiplyScalar(.5);
  31247. }
  31248. }
  31249. var getMixedSet = function(arr1, arr2){//交集
  31250. return arr1.filter(item=>arr2.includes(item));
  31251. };
  31252. var getUnionSet = function(arr1, arr2){//并集
  31253. return arr1.concat(arr2.filter(item=>!arr1.includes(item)))
  31254. };
  31255. var getDifferenceSet = function(arr1, arr2){//差集
  31256. var arr11 = arr1.filter(item=>!arr2.includes(item));
  31257. var arr22 = arr2.filter(item=>!arr1.includes(item));
  31258. return arr11.concat(arr22)
  31259. };
  31260. var getDifferenceSetMuti = function(arr){//收集绝对没有重复的元素,也就是判断出现次数=1的
  31261. var set = [];
  31262. arr.forEach(arr1=>{
  31263. arr1.forEach(item=>{
  31264. var index = set.indexOf(item);
  31265. if(index>-1){
  31266. set.splice(index, 1);
  31267. }else {
  31268. set.push(item);
  31269. }
  31270. });
  31271. });
  31272. return set;
  31273. };
  31274. function DoorAtWhichLine(points, lines){
  31275. var mid = points[0].clone().add(points[1]).multiplyScalar(0.5);
  31276. lines = lines.filter(line=>math.ifPointAtLineBound(mid, line.points, precision));
  31277. if(lines.length == 0)return
  31278. var result = {line:null, dis:Infinity};
  31279. lines.forEach(line=>{
  31280. var foot = math.getFootPoint(mid, line.points[0], line.points[1] );
  31281. var dis = foot.distanceTo(mid);
  31282. if(dis<result.dis){
  31283. result.line = line; result.dis = dis;
  31284. }
  31285. });
  31286. return result
  31287. }
  31288. var ringLen = 0;
  31289. class Ring{
  31290. constructor(o){
  31291. this.id = ringLen ++;
  31292. this.type = o.type || 'normal';
  31293. this.points = o.points;
  31294. this.lines = o.lines;
  31295. rings.push(this);
  31296. this.child = [];//包含的环
  31297. this.parent = [];//被包含的环
  31298. this.smallNeibours = [];//相邻最小环(存在和它有一个以上的相同边的最小环)
  31299. var area = math.getArea(this.points);
  31300. this.area = Math.abs(area);
  31301. this.isClockwise = area<0;//是否逆时针。一般都是逆时针得到的,如果是顺时针,可能是贪吃蛇的情况,可能不是最小环,需要去掉。
  31302. }
  31303. }
  31304. var findLine = function(p1,p2){
  31305. return lines.find(line=>line.points.includes(p1) && line.points.includes(p2) )
  31306. };
  31307. var ifSamePart = function(checkPart , part){//checkPart中所包含的part片段是否和基准part的顺序一样(逆序也可以, 中间有其他数也可以,起始不同也行。比如 01234和204一样的)
  31308. var axis, startIndex, newCheckPart=[];
  31309. for(var j=0,len1 = checkPart.length; j<len1; j++){//将checkPart中比part多的数除去,使两个数组中包含的数完全相同。
  31310. if(part.indexOf(checkPart[j])>-1)newCheckPart.push(checkPart[j]);
  31311. }
  31312. for(var i=0,len = part.length; i<len; i++){
  31313. var index = newCheckPart.indexOf(part[i]);
  31314. if(index == -1)return false;
  31315. if(i == 0) startIndex = index;//标记第一个查找点对应的index
  31316. else if(i == 1){//标记查找顺序是正还是逆
  31317. axis = index - startIndex;
  31318. if(axis == len - 1) axis = -1;//刚好是首和尾
  31319. else if(axis == 1- len) axis = 1;
  31320. if(axis != -1 && axis != 1){
  31321. return false
  31322. }
  31323. }else {//判断是否是按顺序的
  31324. if(index != ((startIndex+axis * i + len) % len) ) return false;
  31325. }
  31326. }
  31327. return {sameAxis:axis>0}; //如果一样的话返回正逆是否相同
  31328. };
  31329. //或者判断是否有相同边(但是相同点是可以组成不同环)
  31330. var ifSameRing = function(ring1, ring2){//判断两个环是否相等。 除了可以逆向外顺序要对
  31331. if(ring1 instanceof Ring)ring1 = ring1.points;
  31332. if(ring2 instanceof Ring)ring2 = ring2.points;
  31333. if(ring1.length != ring2.length)return false;
  31334. if(ring1.lines && ring2.lines){
  31335. if(getDifferenceSet(ring1.lines , ring2.lines).length == 0)return true;//差集个数为0
  31336. }else {
  31337. if(ifSamePart(ring1, ring2))return true
  31338. }
  31339. };
  31340. var atWhichChildLine = function(point, line, precision){
  31341. if(line.children.length == 0){//这里可能要放低精度 保证能找到
  31342. if(math.ifPointAtLineBound(point, line.points, precision)) return line;
  31343. }else {
  31344. for(var i=0;i<line.children.length;i++){
  31345. var at = atWhichChildLine(point, line.children[i], precision);
  31346. if(at)return at
  31347. }
  31348. }
  31349. };
  31350. function getSliceLines(){
  31351. var len = lines.length;
  31352. var deal = function(line1,line2){
  31353. if(line1 == line2)return;
  31354. if(line1.angle == void 0) line1.getAngleInfo();
  31355. if(line2.angle == void 0) line2.getAngleInfo();
  31356. var intersect = line1.getIntersectWithLine(line2, precision);
  31357. if(intersect){
  31358. var point; //得到交点
  31359. if(intersect.type == "intersect"){
  31360. point = getPoint(intersect.point, "whenGetSliceLines");
  31361. var line1_ = atWhichChildLine(point, line1);
  31362. var line2_ = atWhichChildLine(point, line2);
  31363. //重合的情况还没考虑(平行)
  31364. if(!line1_) line1_ = atWhichChildLine(point, line1, precision);//降低精度
  31365. if(!line1_) line1_ = atWhichChildLine(point, line1, precision*2);//降低精度
  31366. if(!line2_) line2_ = atWhichChildLine(point, line2, precision);
  31367. if(!line2_) line2_ = atWhichChildLine(point, line2, precision*2);//降低精度
  31368. //拆分线条:
  31369. //如果还报错,找不到ChildLine,就直接返回吧 或者搞个循环 逐渐降低精度
  31370. if(!line1_ || !line2_){
  31371. console.warn("atWhichChildLine仍旧找不到 :" + line1.id + ',' + line2.id + ", pointId: "+point.id);
  31372. line1_ || console.warn("找不到line1");
  31373. line2_ || console.warn("找不到line2");
  31374. return;
  31375. }
  31376. if(line1_.points.find(p=>p == point) && line2_.points.find(p=>p == point)){//这个点是line1_、 line2_端点,不做处理
  31377. //console.log("joint型 "+point.id)
  31378. }else if(line1_.points.find(p=>p == point)){//T型交叉
  31379. line2_.splitByPoint(point);//加入到母线中,之后还先用母线判断交点
  31380. //console.log("T型交叉1 "+point.id)
  31381. }else if(line2_.points.find(p=>p == point)){//T型交叉
  31382. line1_.splitByPoint(point);
  31383. //console.log("T型交叉2 "+point.id)
  31384. }else {//十字交叉
  31385. line1_.splitByPoint(point);
  31386. line2_.splitByPoint(point);
  31387. }
  31388. }else {
  31389. point = intersect.point;//交点是端点
  31390. if(math.closeTo(line1.angle,line2.angle)){ //重合一部分
  31391. var children1 = line1.getAllSlices();
  31392. var children2 = line2.getAllSlices();
  31393. if(children1.length>1 || children2.length>1){ //使用最小分割片段来比较
  31394. children1.forEach(child1=>{
  31395. children2.forEach(child2=>{
  31396. deal(child1, child2);
  31397. });
  31398. });
  31399. return;
  31400. }
  31401. var anotherPoint1 = line1.points.find(point_=>point_!=point);
  31402. var anotherPoint2 = line2.points.find(point_=>point_!=point);
  31403. if(math.ifPointAtLineBound(anotherPoint1, line2.points)){
  31404. line2.splitByPoint(anotherPoint1);
  31405. }else if(math.ifPointAtLineBound(anotherPoint2, line1.points)){
  31406. line1.splitByPoint(anotherPoint2);
  31407. }
  31408. }
  31409. }
  31410. }else if(math.closeTo(line1.angle,line2.angle)){
  31411. var vec1 = line1.getVector();
  31412. var vec = line1.points[0].clone().sub(line2.points[0]);
  31413. var cos = math.getVec2Cos(vec1, vec);
  31414. if(math.closeTo(cos, -1, 1e-4) || math.closeTo(cos, 1, 1e-4)){ //共线
  31415. var children1 = line1.getAllSlices();
  31416. var children2 = line2.getAllSlices();
  31417. if(children1.length>1 || children2.length>1){ //使用最小分割片段来比较
  31418. children1.forEach(child1=>{
  31419. children2.forEach(child2=>{
  31420. deal(child1, child2);
  31421. });
  31422. });
  31423. return;
  31424. }
  31425. //判断是否重叠
  31426. var A = line1.points[0];
  31427. var C = line1.reverse == line2.reverse ? line2.points[0] : line2.points[1];
  31428. var B = line1.points[1];
  31429. var D = line1.reverse == line2.reverse ? line2.points[1] : line2.points[0];
  31430. var BC = C.clone().sub(B);
  31431. var AD = D.clone().sub(A);
  31432. if(BC.length()<AD.length()){
  31433. var BA = A.clone().sub(B);
  31434. if(math.getVec2Angle(BC, BA) >= 1.57 )return;//没有重叠部分
  31435. }else {
  31436. var AB = B.clone().sub(A);
  31437. if(math.getVec2Angle(AD, AB) >= 1.57 )return;
  31438. }
  31439. var f = function(line1,line2){
  31440. var one = math.ifPointAtLineBound(line1.points[0], line2.points);
  31441. var two = math.ifPointAtLineBound(line1.points[1], line2.points);
  31442. if(one && two){//line1在line2上
  31443. line2.splitByPoints( line1.points );
  31444. return true
  31445. }else if(one || two){//错开
  31446. var point1 = one ? line1.points[0] : line1.points[1];
  31447. var anotherPoint1 = one ? line1.points[1] : line1.points[0];
  31448. var dis1 = line2.points[0].distanceTo(anotherPoint1);
  31449. var dis2 = line2.points[1].distanceTo(anotherPoint1);
  31450. var point2 = dis1 < dis2 ? line2.points[0] : line2.points[1];
  31451. line1.splitByPoint(point2);
  31452. line2.splitByPoint(point1);
  31453. return true
  31454. }
  31455. };
  31456. f(line1, line2) || f(line2, line1);
  31457. }
  31458. }
  31459. };
  31460. for(let i=0;i<len;i++){
  31461. let line1 = lines[i];
  31462. for(let j=i+1;j<len;j++){
  31463. let line2 = lines[j];
  31464. deal(line1,line2);
  31465. }
  31466. }
  31467. //console.log("原有线条个数:"+len)
  31468. //lines = lines.filter((line)=>{return line.children.length == 0})
  31469. //console.log("现有线条个数:"+lines.length)
  31470. }
  31471. var bound = new Box2();
  31472. var build = function(o){
  31473. //融合了相近点
  31474. //根据bound 处理precision
  31475. o.points.forEach(p=>{
  31476. bound.expandByPoint(new Vector2(p.x,p.y));
  31477. });
  31478. if(o.precision != void 0){
  31479. precision = o.precision;
  31480. }else {
  31481. var boundSize = bound.getSize(new Vector2);
  31482. precision = MathUtils$1.clamp(Math.max(boundSize.x, boundSize.y) / 70, 0.2, 2);
  31483. }
  31484. o.points.forEach(point=>getPoint(point));//{x:..,y:..}
  31485. o.lines.forEach(line=>{ //{p1:id1. p2:id2}
  31486. new Line$1({points:[getPoint(line.p1), getPoint(line.p2)], id:line.id });
  31487. });
  31488. //注意:不能出现一条线的两个点坐标一致,否则寻路时方向出错。 所以手动融合下相近点。
  31489. };
  31490. var searchRings = function(o={}){
  31491. points = [];
  31492. lines = [];
  31493. rings = [];
  31494. lineLen = ringLen = 0;
  31495. o.points = o.points || [];
  31496. o.lines = o.lines || [];
  31497. build(o);
  31498. if(!o.dontSliceLines){
  31499. getSliceLines();
  31500. }
  31501. //查找最小回路:
  31502. //参考: 引入方向因子的最小回路、最大回路搜索算法.pdf
  31503. //方法: 逆时针寻找(标记)最外层大环 -->从走过的点开始逆时针寻找最小环(直到所有可走的路被走过两次)-->逆时针寻找最外层大环(直到所有可走的路被走过两次)-->..
  31504. //其中找大环时选择方向因子最小的路, 而小环则相反(但只有开始第一条路是一样的, 都是选择最左边的点的因子最小的路)。
  31505. //标记方法: 每条线需要被搜索两次才算完毕。搜索完毕的线退出搜索。(依据:搜索完全部最小回路后 , 在无向图中删除搜索过 2 次的边及孤立节点得到退化图 , 恰好构成最大回路。)
  31506. var searchTime = 0;
  31507. var addRingJudgeCount = 0;
  31508. var addRingJudge = function(ring, lines, connectedLines, type){// 处理拣出的片段
  31509. addRingJudgeCount++;
  31510. //console.log("addRingJudge points("+ type+"):"+ ring.map(point=>point.id) )
  31511. if(o.onlyGetOutRing && type == "small")return
  31512. if(type == "small" || o.onlyGetOutRing){//挑出回路:
  31513. var newRings = [];
  31514. while(ring.length){
  31515. var road = [];
  31516. var turnBack = false;
  31517. for(let i=0;i<ring.length;i++){
  31518. if(road.includes(ring[i])){//如果走到方才的点,可能形成回路。 无论是不是回路都要摘去这段。
  31519. var index = road.indexOf(ring[i]);
  31520. var pointArr = ring.slice(index, i);
  31521. var linesArr = lines.slice(index, i);
  31522. ring.splice(index,i-index);
  31523. lines.splice(index,i-index);
  31524. if(pointArr.length>2){// 如果只有两个数,代表原路返回, 如 1->2(->1)
  31525. if( !rings.find(ring_=>ifSameRing(pointArr, ring_))) newRings.push( new Ring({points: pointArr, lines:linesArr}) );
  31526. }
  31527. turnBack = true;
  31528. break;
  31529. }else {
  31530. road.push(ring[i]);
  31531. turnBack = false;
  31532. }
  31533. }
  31534. if(!turnBack){//没有重复的点,那么就直接处理整条。
  31535. if(ring.length>2){// 如果只有两个数,代表原路返回, 如 1->2(->1)
  31536. if( !rings.find(ring_=>ifSameRing(ring, ring_))) newRings.push( new Ring({points: ring, lines}) );
  31537. }
  31538. break;
  31539. }
  31540. }
  31541. if(type != 'small'){
  31542. newRings.forEach(e=>e.isOutRing = true);
  31543. }
  31544. //console.log(newRings)
  31545. }else {
  31546. return ring
  31547. }
  31548. };
  31549. var search = function(point2d, comeRoad, type, connectedLines){
  31550. searchTime++;
  31551. var goLine;
  31552. var direction;
  31553. if(type.includes("big")){
  31554. if(!comeRoad){
  31555. if(type.includes("Left")){//逆时针
  31556. direction = new Vector2(1,0);
  31557. }else {
  31558. direction = new Vector2(-1,0);
  31559. }
  31560. goLine = point2d.searchLineByFactor(direction,"min");
  31561. }else {
  31562. var lastPoint = comeRoad.points[comeRoad.points.length-1];
  31563. direction = point2d.clone().sub(lastPoint);
  31564. goLine = point2d.searchLineByFactor(direction,"min", findLine(point2d, lastPoint));
  31565. }
  31566. }else {
  31567. if(!comeRoad){
  31568. //似乎找最小环时,第一条线也是找最小的因子,这样才能保证逆时针(除非只有顺时针一条路)
  31569. direction = new Vector2(1,0);
  31570. goLine = point2d.searchLineByFactor(direction,"min");
  31571. }else {
  31572. var lastPoint = comeRoad.points[comeRoad.points.length-1];
  31573. direction = point2d.clone().sub(lastPoint);
  31574. goLine = point2d.searchLineByFactor(direction,"max", findLine(point2d, lastPoint));
  31575. }
  31576. }
  31577. if(!goLine)return
  31578. goLine.searchTime++;
  31579. connectedLines.includes(goLine) || connectedLines.push(goLine);
  31580. var nextPoint = goLine.points.find( point => point2d!=point );
  31581. //if( comeRoad && comeRoad.points[comeRoad.points.length - 1] == nextPoint ) return;//不能查找来时的方向(反方向)
  31582. //走不通就原路返回
  31583. var roadPoints = comeRoad ? comeRoad.points.concat([point2d]) : [point2d];//每个分叉都能构成一条新的road
  31584. var roadLines = comeRoad ? comeRoad.lines.concat([goLine]) : [goLine];
  31585. //走到第一个点就算停止,这时候可能得到一个环、或者一段走了两遍的线、或者一条线上带了些环。
  31586. if(nextPoint == roadPoints[0]) return addRingJudge(roadPoints, roadLines, connectedLines, type) //形成环
  31587. else {
  31588. /* var len = roadPoints.indexOf(nextPoint);
  31589. if( len > -1){ //走到走过的路的某一点 构成这段路的回路
  31590. var points = roadPoints.slice(len, roadPoints.length);
  31591. var lines = roadLines.slice(len, roadPoints.length);
  31592. addRingJudge(points, lines)
  31593. }else{ */
  31594. return search(nextPoint, {lines:roadLines, points:roadPoints}, type, connectedLines);//继续寻路
  31595. //}
  31596. }
  31597. };
  31598. while(1){//搜寻一次大环
  31599. var connectedLines = [];//被搜寻过的且searchTime<2的线。一旦全部搜完就说明该连通区域搜寻完毕,继续查下一个连通区域。
  31600. var startPoint = null;
  31601. points.forEach(point=>{//找出x最小的点
  31602. if(!point.lines.find(line=>line.searchTime<2))return;
  31603. if(!startPoint)startPoint = point;
  31604. else if(point.x < startPoint.x)startPoint = point;
  31605. });
  31606. if(!startPoint)break; //说明全部找完
  31607. var ring = search(startPoint, null, "bigLeft", connectedLines);//逆时针
  31608. //search(startPoint, null, "bigRight", connectedLines);//顺时针(为了防止最外层不是回路之前写了顺时针,但如果是回路就会走重复。后来发现只要逆时针即可,因为走完后剩下的可以再次找大环)
  31609. connectedLines = connectedLines.filter(line=>line.searchTime<2);
  31610. while(connectedLines.length>0){//目标是顺着connectedLines把所有连通的小环都找到
  31611. let points_ = [];//connectedLines中所有的点
  31612. connectedLines.forEach(line=>line.points.forEach(point=>{if(!points_.includes(point))points_.push(point); }));
  31613. var startPoint = null;
  31614. points_.forEach(point=>{//找出x最小的点
  31615. if(!point.lines.find(line=>line.searchTime<2))return;
  31616. if(!startPoint)startPoint = point;
  31617. else if(point.x < startPoint.x)startPoint = point;
  31618. });
  31619. if(!startPoint)break;
  31620. search(startPoint, null, "small", connectedLines);
  31621. connectedLines = connectedLines.filter(line=>line.searchTime<2);
  31622. }
  31623. }
  31624. /* if(o.onlyGetOutRing){
  31625. rings = rings.filter(e=>e.isOutRing)
  31626. } */
  31627. //console.log("searchTime "+searchTime + ", addRingJudgeCount " +addRingJudgeCount)
  31628. //找出所有的相邻关系,包括公共边
  31629. var len = rings.length;
  31630. for(let i=0; i<len; i++){
  31631. let ring1 = rings[i];
  31632. for(let j=i+1; j<len; j++){
  31633. let ring2 = rings[j];
  31634. var bothHasLines = getMixedSet(ring1.lines, ring2.lines);
  31635. if(bothHasLines.length){//ring1oíring2?àáú
  31636. ring1.smallNeibours.push(ring2);
  31637. ring2.smallNeibours.push(ring1);
  31638. }else {
  31639. }
  31640. }
  31641. }
  31642. rings.forEach(ring1=>{
  31643. for(let i=0; i<len; i++){
  31644. var ring2 = rings[i];
  31645. if(ring1 == ring2 || ring1.smallNeibours.includes(ring2))continue;
  31646. let inside;
  31647. for(let u=0;u<ring1.points.length;u++){
  31648. inside = math.isPointInArea(ring2.points, null, ring1.points[u]);
  31649. if(!inside)break
  31650. else if(inside && !inside.atLine){
  31651. break
  31652. }
  31653. }
  31654. if(inside){ //只要其中一个点在ring2内,就说明ring1是内环
  31655. if(inside.atLine){//(还是会存在点全在线上的情况,这时候判断中心点)
  31656. var center = math.getCenterOfGravityPoint(ring1.points);
  31657. let inside1 = math.isPointInArea(ring2.points, null, center);
  31658. if(!inside1){
  31659. continue
  31660. }
  31661. }
  31662. ring2.child.push(ring1);
  31663. ring1.parent.push(ring2);
  31664. }
  31665. }
  31666. });
  31667. //去除非最小的ring 是否应该检测parent child?
  31668. /*
  31669. like this:
  31670. |———————————————————————|
  31671. |———|———————|———————| |
  31672. | | | | |
  31673. | |———————|———————| |
  31674. |———————————————————————|
  31675. */
  31676. var wiseRings = rings.filter(r=>!r.isClockwise);//一般都是逆时针得到的,如果是顺时针,可能是贪吃蛇的情况,可能不是最小环,需要去掉。
  31677. if(wiseRings.length > 0){
  31678. //console.log('%c存在非最小的ring! 进行处理:',"color:#00f");
  31679. wiseRings.forEach(ring=>{ //(此案例验证出smallNeibours就是它的最小构成,可以再看看别的案例)
  31680. if(ring.smallNeibours.length>0){//另:如果内部只有一个,说明它是最小环,不需要处理
  31681. var is = false;
  31682. var difference = getDifferenceSet(ring.lines , getDifferenceSetMuti(ring.smallNeibours.concat(ring.child).map(ring=>ring.lines)));//获取所有smallNeibours和child的边中没有重复过的边(就是outline) 和该ring的线比较
  31683. is = difference.every(line=> ring.child.find(r=>r.lines.includes(line)) ); //多出的线只能是child中的线
  31684. if(is){
  31685. console.log('%c删除非最小环 ring'+ring.id,"color:#00f");
  31686. console.log(ring);
  31687. rings.splice(rings.indexOf(ring), 1);
  31688. ring.child.forEach(c=>{var index = c.parent.indexOf(ring);index>-1 && c.parent.splice(index,1);});
  31689. ring.parent.forEach(c=>{var index = c.child.indexOf(ring);index>-1 && c.child.splice(index,1);});
  31690. ring.smallNeibours.forEach(c=>{var index = c.smallNeibours.indexOf(ring);index>-1 && c.smallNeibours.splice(index,1);});
  31691. }
  31692. }
  31693. });
  31694. }
  31695. /* rings = rings.filter(ring=>{
  31696. rings = rings.filter(ring=>{
  31697. var enoughSize = ring.area > 0.5
  31698. if(!enoughSize){console.log('因面积过小去除ring '+ring.id + " , area: "+ring.area)}
  31699. return enoughSize
  31700. })
  31701. rings.forEach(ring=>{
  31702. if(ring.closetChilds){
  31703. ring.closetChilds = ring.closetChilds.filter(e=>rings.includes(e))
  31704. }
  31705. })
  31706. return rings
  31707. }) */ //在dealRings前不能随意删除rings,因为判断是否是最小环时需要全部的环
  31708. rings.forEach(ring=>{ //这里和cad中的不太一样, cad中双数个parent算外环,单数内环; 这里不分内外, 只看有无parent child
  31709. if(ring.parent.length){
  31710. ring.closetParent = ring.parent.find(ring_ => ring_.parent.length == ring.parent.length - 1);//最近一层的大环就是比它的parent个数少一的
  31711. ring.closetParent.closetChilds || (ring.closetParent.closetChilds = []);//内环可能多个
  31712. ring.closetParent.closetChilds.push(ring);
  31713. }
  31714. });
  31715. //console.log(rings)
  31716. var _ring = rings.map(ring=>{
  31717. var data = {
  31718. id: ring.id,
  31719. points: ring.points.map(point=>{return {id: point.ids[0], x:point.x, y:point.y}}),
  31720. /* doors : o.doors.filter(door=>{
  31721. if(ring.closetChilds){
  31722. var childOutLines = getDifferenceSetMuti(ring.closetChilds.map(ring=>ring.lines)) //最近子环的外边
  31723. return ring.lines.concat(childOutLines).includes(door.atLine)
  31724. }else{
  31725. return ring.lines.includes(door.atLine)
  31726. }
  31727. }), */
  31728. area:ring.area,
  31729. closetParent : ring.closetParent && ring.closetParent.id,
  31730. closetChilds : ring.closetChilds && ring.closetChilds.map(e=>e.id)
  31731. };
  31732. return data
  31733. });
  31734. //console.log(JSON.stringify(_ring))
  31735. return _ring
  31736. };
  31737. var easing = {};
  31738. //渐变曲线函数,反应加速度的变化
  31739. //currentTime:x轴当前时间(从0-到duration), startY:起始点, duration:总时长, wholeY:路程 (即endY-startY)
  31740. //参数基本是 x, 0, 1, 1
  31741. /*
  31742. easeOut 基本是y= m * (x-dur)^k + n, 若k为偶数,m<0, 若k为奇数,m>0; (因为偶数的话必须开口向下才能获得斜率递减的递增的那段,而奇数是对称的,单调递增. )
  31743. 根据x=0时y=0, x=dur时y=S , 得 n = S,m = -S/(-dur)^k
  31744. */
  31745. easing.getEaseOut = function(k){// k 是>=2的整数. 越大变化率越大, 相同初始速度所需要时间越久
  31746. let easeFun;
  31747. k = Math.round(k);
  31748. if(k<2){
  31749. k = Math.PI / 2;
  31750. easeFun = easing.easeOutSine;
  31751. }else {
  31752. easeFun = function(currentTime, startY, wholeY, duration) {
  31753. if(k>2){
  31754. console.log(k);
  31755. }
  31756. return -wholeY/Math.pow(-duration, k) * Math.pow(currentTime-duration, k) + wholeY
  31757. };
  31758. }
  31759. return {
  31760. k,
  31761. easeFun
  31762. }
  31763. };
  31764. easing.linearTween = function(currentTime, startY, wholeY, duration) {
  31765. return wholeY * currentTime / duration + startY
  31766. }
  31767. ,
  31768. easing.easeInQuad = function(currentTime, startY, wholeY, duration) {
  31769. return currentTime /= duration,
  31770. wholeY * currentTime * currentTime + startY
  31771. }
  31772. ,
  31773. easing.easeOutQuad = function(currentTime, startY, wholeY, duration) { // 如套上实际的距离S和时长dur, y = - S / dur *(x^2-2x) 当s为1,dur为1时,是 y = -(x-1)^2 + 1 , 在0-1中是斜率递减的递增函数. 导数- S / dur *(2x-2 ) 可求出实时速度 故在0这一时刻,速度为 2S/dur
  31774. return currentTime /= duration,
  31775. -wholeY * currentTime * (currentTime - 2) + startY
  31776. }
  31777. ,
  31778. easing.easeInOutQuad = function(currentTime, startY, wholeY, duration) {
  31779. return currentTime /= duration / 2,
  31780. currentTime < 1 ? wholeY / 2 * currentTime * currentTime + startY : (currentTime--,
  31781. -wholeY / 2 * (currentTime * (currentTime - 2) - 1) + startY)
  31782. }
  31783. ,
  31784. easing.easeInCubic = function(currentTime, startY, wholeY, duration) {
  31785. return currentTime /= duration,
  31786. wholeY * currentTime * currentTime * currentTime + startY
  31787. }
  31788. ,
  31789. easing.easeOutCubic = function(currentTime, startY, wholeY, duration) {// y = S / dur^3 *(x-dur)^3 + S,对称中心是(dur,S),从0-dur是 斜率递减的递增函数,导数为3S/dur^3 * (x-dur)^2, 0时速度为3S/dur
  31790. return currentTime /= duration,
  31791. currentTime--,
  31792. wholeY * (currentTime * currentTime * currentTime + 1) + startY
  31793. }
  31794. ,
  31795. easing.easeInOutCubic = function(currentTime, startY, wholeY, duration) {
  31796. return currentTime /= duration / 2,
  31797. currentTime < 1 ? wholeY / 2 * currentTime * currentTime * currentTime + startY : (currentTime -= 2,
  31798. wholeY / 2 * (currentTime * currentTime * currentTime + 2) + startY)
  31799. }
  31800. ,
  31801. easing.easeInQuart = function(currentTime, startY, wholeY, duration) {
  31802. return currentTime /= duration,
  31803. wholeY * currentTime * currentTime * currentTime * currentTime + startY
  31804. }
  31805. ,
  31806. easing.easeOutQuart = function(currentTime, startY, wholeY, duration) {//根据上面的计算,估计0时速度应该是4S/dur吧……
  31807. return currentTime /= duration,
  31808. currentTime--,
  31809. -wholeY * (currentTime * currentTime * currentTime * currentTime - 1) + startY
  31810. }
  31811. ,
  31812. easing.easeInOutQuart = function(currentTime, startY, wholeY, duration) {
  31813. return currentTime /= duration / 2,
  31814. currentTime < 1 ? wholeY / 2 * currentTime * currentTime * currentTime * currentTime + startY : (currentTime -= 2,
  31815. -wholeY / 2 * (currentTime * currentTime * currentTime * currentTime - 2) + startY)
  31816. }
  31817. ,
  31818. easing.easeInQuint = function(currentTime, startY, wholeY, duration) {
  31819. return currentTime /= duration,
  31820. wholeY * currentTime * currentTime * currentTime * currentTime * currentTime + startY
  31821. }
  31822. ,
  31823. easing.easeOutQuint = function(currentTime, startY, wholeY, duration) {
  31824. return currentTime /= duration,
  31825. currentTime--,
  31826. wholeY * (currentTime * currentTime * currentTime * currentTime * currentTime + 1) + startY
  31827. }
  31828. ,
  31829. easing.easeInOutQuint = function(currentTime, startY, wholeY, duration) {
  31830. return currentTime /= duration / 2,
  31831. currentTime < 1 ? wholeY / 2 * currentTime * currentTime * currentTime * currentTime * currentTime + startY : (currentTime -= 2,
  31832. wholeY / 2 * (currentTime * currentTime * currentTime * currentTime * currentTime + 2) + startY)
  31833. }
  31834. ,
  31835. easing.easeInSine = function(currentTime, startY, wholeY, duration) {
  31836. return -wholeY * Math.cos(currentTime / duration * (Math.PI / 2)) + wholeY + startY
  31837. }
  31838. ,
  31839. easing.easeOutSine = function(currentTime, startY, wholeY, duration) {// y' = S * PI / 2 / dur * cos(PI/2/dur * x)
  31840. return wholeY * Math.sin(currentTime / duration * (Math.PI / 2)) + startY
  31841. }
  31842. ,
  31843. easing.easeInOutSine = function(currentTime, startY, wholeY, duration) {
  31844. return -wholeY / 2 * (Math.cos(Math.PI * currentTime / duration) - 1) + startY
  31845. }
  31846. ,
  31847. easing.easeInExpo = function(currentTime, startY, wholeY, duration) {
  31848. return wholeY * Math.pow(2, 10 * (currentTime / duration - 1)) + startY
  31849. }
  31850. ,
  31851. easing.easeOutExpo = function(currentTime, startY, wholeY, duration) {
  31852. return wholeY * (-Math.pow(2, -10 * currentTime / duration) + 1) + startY
  31853. }
  31854. ,
  31855. easing.easeInOutExpo = function(currentTime, startY, wholeY, duration) {
  31856. return currentTime /= duration / 2,
  31857. currentTime < 1 ? wholeY / 2 * Math.pow(2, 10 * (currentTime - 1)) + startY : (currentTime--,
  31858. wholeY / 2 * (-Math.pow(2, -10 * currentTime) + 2) + startY)
  31859. }
  31860. ,
  31861. easing.easeInCirc = function(currentTime, startY, wholeY, duration) {
  31862. return currentTime /= duration,
  31863. -wholeY * (Math.sqrt(1 - currentTime * currentTime) - 1) + startY
  31864. }
  31865. ,
  31866. easing.easeOutCirc = function(currentTime, startY, wholeY, duration) {
  31867. return currentTime /= duration,
  31868. currentTime--,
  31869. wholeY * Math.sqrt(1 - currentTime * currentTime) + startY
  31870. }
  31871. ,
  31872. easing.easeInOutCirc = function(currentTime, startY, wholeY, duration) {
  31873. return currentTime /= duration / 2,
  31874. currentTime < 1 ? -wholeY / 2 * (Math.sqrt(1 - currentTime * currentTime) - 1) + startY : (currentTime -= 2,
  31875. wholeY / 2 * (Math.sqrt(1 - currentTime * currentTime) + 1) + startY)
  31876. }
  31877. ,
  31878. easing.easeInElastic = function(currentTime, startY, wholeY, duration) {
  31879. var r = 1.70158
  31880. , o = 0
  31881. , a = wholeY;
  31882. return 0 === currentTime ? startY : 1 === (currentTime /= duration) ? startY + wholeY : (o || (o = .3 * duration),
  31883. a < Math.abs(wholeY) ? (a = wholeY,
  31884. r = o / 4) : r = o / (2 * Math.PI) * Math.asin(wholeY / a),
  31885. -(a * Math.pow(2, 10 * (currentTime -= 1)) * Math.sin((currentTime * duration - r) * (2 * Math.PI) / o)) + startY)
  31886. }
  31887. ,
  31888. easing.easeOutElastic = function(currentTime, startY, wholeY, duration) {
  31889. var r = 1.70158
  31890. , o = 0
  31891. , a = wholeY;
  31892. return 0 === currentTime ? startY : 1 === (currentTime /= duration) ? startY + wholeY : (o || (o = .3 * duration),
  31893. a < Math.abs(wholeY) ? (a = wholeY,
  31894. r = o / 4) : r = o / (2 * Math.PI) * Math.asin(wholeY / a),
  31895. a * Math.pow(2, -10 * currentTime) * Math.sin((currentTime * duration - r) * (2 * Math.PI) / o) + wholeY + startY)
  31896. }
  31897. ,
  31898. easing.easeInOutElastic = function(currentTime, startY, wholeY, duration) {
  31899. var r = 1.70158
  31900. , o = 0
  31901. , a = wholeY;
  31902. return 0 === currentTime ? startY : 2 === (currentTime /= duration / 2) ? startY + wholeY : (o || (o = duration * (.3 * 1.5)),
  31903. a < Math.abs(wholeY) ? (a = wholeY,
  31904. r = o / 4) : r = o / (2 * Math.PI) * Math.asin(wholeY / a),
  31905. currentTime < 1 ? -.5 * (a * Math.pow(2, 10 * (currentTime -= 1)) * Math.sin((currentTime * duration - r) * (2 * Math.PI) / o)) + startY : a * Math.pow(2, -10 * (currentTime -= 1)) * Math.sin((currentTime * duration - r) * (2 * Math.PI) / o) * .5 + wholeY + startY)
  31906. }
  31907. ,
  31908. easing.easeInBack = function(currentTime, startY, wholeY, duration, r) {
  31909. return void 0 === r && (r = 1.70158),
  31910. wholeY * (currentTime /= duration) * currentTime * ((r + 1) * currentTime - r) + startY
  31911. }
  31912. ,
  31913. easing.easeOutBack = function(currentTime, startY, wholeY, duration, r) {
  31914. return void 0 === r && (r = 1.70158),
  31915. wholeY * ((currentTime = currentTime / duration - 1) * currentTime * ((r + 1) * currentTime + r) + 1) + startY
  31916. }
  31917. ,
  31918. easing.easeInOutBack = function(currentTime, startY, wholeY, duration, r) {
  31919. return void 0 === r && (r = 1.70158),
  31920. (currentTime /= duration / 2) < 1 ? wholeY / 2 * (currentTime * currentTime * (((r *= 1.525) + 1) * currentTime - r)) + startY : wholeY / 2 * ((currentTime -= 2) * currentTime * (((r *= 1.525) + 1) * currentTime + r) + 2) + startY
  31921. }
  31922. ,
  31923. easing.easeOutBounce = function(currentTime, startY, wholeY, duration) {
  31924. return (currentTime /= duration) < 1 / 2.75 ? wholeY * (7.5625 * currentTime * currentTime) + startY : currentTime < 2 / 2.75 ? wholeY * (7.5625 * (currentTime -= 1.5 / 2.75) * currentTime + .75) + startY : currentTime < 2.5 / 2.75 ? wholeY * (7.5625 * (currentTime -= 2.25 / 2.75) * currentTime + .9375) + startY : wholeY * (7.5625 * (currentTime -= 2.625 / 2.75) * currentTime + .984375) + startY
  31925. }
  31926. ,
  31927. easing.easeInBounce = function(currentTime, startY, wholeY, r) {
  31928. return wholeY - easing.easeOutBounce(r - currentTime, 0, wholeY, r) + startY
  31929. }
  31930. ,
  31931. easing.easeInOutBounce = function(currentTime, startY, wholeY, r) {
  31932. return currentTime < r / 2 ? .5 * easing.easeInBounce(2 * currentTime, 0, wholeY, r) + startY : .5 * easing.easeOutBounce(x, 2 * currentTime - r, 0, wholeY, r) + .5 * wholeY + startY
  31933. };
  31934. var lerp = {
  31935. /* vector: function(currentTime, startY, f) {//xzw change, add f
  31936. var wholeY = currentTime.clone();
  31937. return startY = startY.clone(),
  31938. function(duration) {
  31939. currentTime.set(wholeY.x * (1 - duration) + startY.x * duration, wholeY.y * (1 - duration) + startY.y * duration, wholeY.z * (1 - duration) + startY.z * duration)
  31940. f && f(currentTime,duration);
  31941. }
  31942. },
  31943. quaternion: function(currentTime, startY, f) {//xzw change, add f
  31944. var wholeY = currentTime.clone();
  31945. return function(duration) {
  31946. currentTime.copy(wholeY).slerp(startY, duration);
  31947. f && f(currentTime,duration);
  31948. }
  31949. },
  31950. property: function(currentTime, startY, wholeY, duration) {
  31951. var r = currentTime[startY];
  31952. return function(o) {
  31953. currentTime[startY] = r * (1 - o) + wholeY * o,
  31954. duration && duration(currentTime[startY])
  31955. }
  31956. },
  31957. uniform: function(currentTime, startY, wholeY) {
  31958. var duration = currentTime.material.uniforms[startY].value;
  31959. return function(r) {
  31960. try{
  31961. currentTime.material.uniforms[startY] && (currentTime.material.uniforms[startY].value = duration * (1 - r) + wholeY * r)
  31962. }catch(currentTime){
  31963. console.log(1)
  31964. }
  31965. }
  31966. },
  31967. allUniforms: function(currentTime, startY, wholeY) {
  31968. var duration = currentTime.map(function(currentTime) {
  31969. return this.uniform(currentTime, startY, wholeY)
  31970. }
  31971. .bind(this));
  31972. return function(currentTime) {
  31973. duration.forEach(function(startY) {
  31974. startY(currentTime)
  31975. })
  31976. }
  31977. } */
  31978. vector: function(t, i, f) {//xzw change, add f
  31979. var n = t.clone();
  31980. return i = i.clone(),
  31981. function(e, delta) {
  31982. t.set(n.x * (1 - e) + i.x * e, n.y * (1 - e) + i.y * e, n.z * (1 - e) + i.z * e);
  31983. f && f(t,e, delta);
  31984. }
  31985. },
  31986. quaternion: function(t, i, f) {//xzw change, add f
  31987. var n = t.clone();
  31988. return function(e) {
  31989. t.copy(n).slerp(i, e);
  31990. f && f(t,e);
  31991. }
  31992. },
  31993. property: function(t, i, n, r) {
  31994. var o = t[i];
  31995. return function(e) {
  31996. t[i] = o * (1 - e) + n * e,
  31997. r && r(t[i]);
  31998. }
  31999. },
  32000. uniform: function(t, i, n) {
  32001. var r = t.material.uniforms[i].value;
  32002. return function(e) {
  32003. t.material.uniforms[i] && (t.material.uniforms[i].value = r * (1 - e) + n * e);
  32004. }
  32005. },
  32006. matrix4: function(o, a) {
  32007. var s = o.clone();
  32008. return function(e) {
  32009. for (var t = o.elements, i = s.elements, n = a.elements, r = 0; r < 16; r++)
  32010. t[r] = i[r] * (1 - e) + n[r] * e;
  32011. }
  32012. },
  32013. allUniforms: function(e, t, i) {
  32014. var n = e.map(function(e) {
  32015. return this.uniform(e, t, i)
  32016. }
  32017. .bind(this));
  32018. return function(t) {
  32019. n.forEach(function(e) {
  32020. e(t);
  32021. });
  32022. }
  32023. }
  32024. };
  32025. /*
  32026. 渐变
  32027. */
  32028. var transitions = {
  32029. globalDone: null,
  32030. funcs: [],
  32031. counter: 0,
  32032. uniqueID: 0,
  32033. start: function(func, duration, done, delay, ease, name, id, cancelFun, ignoreFirstFrame=true, forbitCancel) {
  32034. return delay = delay || 0,
  32035. this.funcs.push({
  32036. func: func,
  32037. current: -delay * Math.abs(duration), //当前时间
  32038. duration: (1 - Math.max(delay, 0)) * Math.abs(duration), //总时长
  32039. done: done,
  32040. easing: ease || easing.linearTween, //渐变曲线
  32041. cycling: duration < 0,
  32042. running: !0,
  32043. debug: delay < 0,
  32044. name: name || "T" + this.counter,
  32045. id: void 0 === id ? this.counter : id,
  32046. paused: !1,
  32047. cancelFun : cancelFun, //取消时执行的函数
  32048. updateCount:0,
  32049. ignoreFirstFrame,
  32050. forbitCancel,
  32051. }),
  32052. func(0, 16),
  32053. this.counter += 1,
  32054. func
  32055. },
  32056. trigger: function(e) {
  32057. var t = void 0 === e.delayRatio ? 0 : e.delayRatio
  32058. , u = e.func || function() {}
  32059. , r = void 0 === e.duration ? 0 : e.duration;
  32060. void 0 !== e.cycling && e.cycling && (r = -Math.abs(r));
  32061. var o = e.done || null
  32062. , a = e.easing || easing.linearTween
  32063. , s = e.name || "R" + this.counter
  32064. , l = void 0 === e.id ? this.counter : e.id;
  32065. return this.start(u, r, o, t, a, s, l)
  32066. },
  32067. setTimeout: function(e, t, u) {
  32068. var duration = void 0 === u ? this.counter : u;
  32069. return this.trigger({
  32070. done: e,
  32071. duration: void 0 === t ? 0 : t,
  32072. name: "O" + this.counter,
  32073. id: duration
  32074. })
  32075. },
  32076. pause: function() {
  32077. this.paused = !0;
  32078. },
  32079. resume: function() {
  32080. this.paused = !1;
  32081. },
  32082. update: function(e) {
  32083. this.funcs.forEach(function(t) {
  32084. if(t.updateCount++ == 0 && t.ignoreFirstFrame) return //add start可能发生在一帧中任意时刻,而每次update的是在一帧中的固定时刻,所以从start到第一次update的时间并不是所传入的delta,该delta 是上一帧的update到这一帧的update的耗时。 故去掉了第一次的update,相当于延迟一帧再update.
  32085. if (!(t.paused || (t.current += 1e3 * e, t.current < 0))){
  32086. if (t.current >= t.duration && !t.cycling) {
  32087. var u = t.easing(1, 0, 1, 1);
  32088. t.func(u, 1e3 * e),
  32089. t.done && t.done(),
  32090. t.running = !1;
  32091. } else {
  32092. var duration = t.easing(t.current % t.duration / t.duration, 0, 1, 1)
  32093. , r = t.func(duration, 1e3 * e) || !1;
  32094. r && (t.done && t.done(),
  32095. t.running = !1);
  32096. }
  32097. }
  32098. });
  32099. var t = this.funcs.length;
  32100. this.funcs = this.funcs.filter(function(e) {
  32101. return e.running
  32102. });
  32103. var u = this.funcs.length;
  32104. if (t > 0 && 0 === u && this.globalDone) {
  32105. var duration = this.globalDone;
  32106. this.globalDone = null,
  32107. duration();
  32108. }
  32109. },
  32110. adjustSpeed: function(e, t) {
  32111. for (var u = this.getById(e), duration = 0; duration < u.length; duration++) {
  32112. var r = u[duration];
  32113. r.duration /= t,
  32114. r.current /= t;
  32115. }
  32116. },
  32117. getById: function(e) {
  32118. return this.funcs.filter(function(t) {
  32119. return e === t.id
  32120. })
  32121. },
  32122. get: function(e) {
  32123. for (var t = 0; t < this.funcs.length; t += 1)
  32124. if (this.funcs[t].func === e)
  32125. return this.funcs[t];
  32126. return null
  32127. },
  32128. isRunning: function(e) {
  32129. var t = this.get(e);
  32130. return null !== t && t.running
  32131. },
  32132. countActive: function() {
  32133. for (var e = 0, t = 0; t < this.funcs.length; t += 1)
  32134. e += this.funcs[t].running;
  32135. return e
  32136. },
  32137. listActive: function() {
  32138. for (var e = [], t = 0; t < this.funcs.length; t += 1)
  32139. this.funcs[t].running && e.push(this.funcs[t].name);
  32140. return e
  32141. },
  32142. done: function(e) {
  32143. this.globalDone = e;
  32144. },
  32145. cancelById: function(e, dealCancelFun) { //xzw add dealDone
  32146. var t = void 0 === e ? 0 : e;
  32147. let cancels = [];
  32148. this.funcs = this.funcs.filter(function(e) {
  32149. var is = e.id == t && !e.forbitCancel;
  32150. if(is && dealCancelFun){
  32151. e.cancelFun && cancels.push(e.cancelFun);
  32152. //e.cancelFun && e.cancelFun()
  32153. }
  32154. return !is
  32155. });
  32156. cancels.forEach(e=>{e();}); //先从funcs中去除后再执行
  32157. },
  32158. cancel: function(e) {
  32159. this.funcs = this.funcs.filter(function(t) {
  32160. return t.func !== e
  32161. });
  32162. },
  32163. getUniqueId: function() {
  32164. return this.uniqueID -= 1,
  32165. this.uniqueID
  32166. }
  32167. };
  32168. var Common$1 = {
  32169. sortByScore: function(list, request, rank){
  32170. var i = request ? Common$1.filterAll(list, request) : list;
  32171. return 0 === i.length ? [] : i = i.map(function(e) {
  32172. let results = rank.map(function(f){return f(e)});
  32173. let scores = results.map(e=>e.score != void 0 ? e.score : e);
  32174. let logs = results.map(e=>e.log);
  32175. return {
  32176. item: e,
  32177. scores,
  32178. logs,
  32179. score: scores.reduce(function(t, i) {//总分
  32180. return t + i
  32181. }, 0)
  32182. }
  32183. }).sort(function(e, t) {
  32184. return t.score - e.score;
  32185. })
  32186. }
  32187. ,
  32188. filterAll: function(e, t) {
  32189. return e.filter(function (e) {
  32190. return t.every(function (t) {
  32191. return t(e)
  32192. })
  32193. })
  32194. },
  32195. //---------------
  32196. find : function(list, request, rank, sortByScore ) {
  32197. if(sortByScore){
  32198. var r = this.sortByScore(list, request, rank);
  32199. return r[0] && r[0].item
  32200. }else {
  32201. var i = request ? Common$1.filterAll(list, request) : list;
  32202. return 0 === i.length ? null : (rank && rank.forEach(function(e) {
  32203. i = Common$1.stableSort(i, e);
  32204. }),
  32205. i[0])
  32206. }
  32207. }
  32208. ,
  32209. stableSort: function(e, f) {//用到排序函数,涉及到两个item相减
  32210. return e.map(function(e, i) {
  32211. return {
  32212. value: e,
  32213. index: i
  32214. }
  32215. }).sort(function(e, u) {
  32216. var n = f(e.value, u.value);
  32217. return 0 !== n ? n : e.index - u.index //似乎就是加多了这一步:若差距为0,按照原顺序
  32218. }).map(function(e) {
  32219. return e.value
  32220. })
  32221. },
  32222. average: function (e, t) {
  32223. if (0 === e.length)
  32224. return null;
  32225. for (var i = 0, n = 0, r = 0; r < e.length; r++) {
  32226. var o = t ? e[r][t] : e[r];
  32227. i += o,
  32228. n++;
  32229. }
  32230. return i / n
  32231. },
  32232. //---------------------------
  32233. getMixedSet : function(arr1, arr2){//交集
  32234. return arr1.filter(item=>arr2.includes(item));
  32235. },
  32236. getUnionSet : function(arr1, arr2){//并集
  32237. return arr1.concat(arr2.filter(item=>!arr1.includes(item)))
  32238. },
  32239. getDifferenceSet : function(arr1, arr2){//差集 不能识别重复的,如getDifferenceSet([1,2,2],[1,1,2]) 为空
  32240. var arr11 = arr1.filter(item=>!arr2.includes(item));
  32241. var arr22 = arr2.filter(item=>!arr1.includes(item));
  32242. return arr11.concat(arr22)
  32243. },
  32244. getDifferenceSetMuti : function(arr){//收集绝对没有重复的元素,也就是判断出现次数=1的
  32245. var set = [];
  32246. arr.forEach(arr1=>{
  32247. arr1.forEach(item=>{
  32248. var index = set.indexOf(item);
  32249. if(index>-1){
  32250. set.splice(index, 1);
  32251. }else {
  32252. set.push(item);
  32253. }
  32254. });
  32255. });
  32256. return set;
  32257. }
  32258. ,
  32259. CloneJson : function(data){
  32260. var str = JSON.stringify(data);
  32261. return JSON.parse(str)
  32262. }
  32263. ,
  32264. CloneObject : function(copyObj, result, isSimpleCopy, simpleCopyList=[]) {
  32265. //isSimpleCopy 只复制最外层
  32266. //复制json result的可能:普通数字或字符串、普通数组、复杂对象
  32267. simpleCopyList.push(Object3D); //遇到simpleCopyList中的类直接使用不拷贝
  32268. if(!copyObj || typeof copyObj == 'number' || typeof copyObj == 'string' || copyObj instanceof Function || simpleCopyList.some(className => copyObj instanceof className)){
  32269. return copyObj
  32270. }
  32271. result = result || {};
  32272. if (copyObj instanceof Array) {
  32273. return copyObj.map(e=>{
  32274. return this.CloneObject(e)
  32275. })
  32276. }else {
  32277. if(copyObj.clone instanceof Function ){ //解决一部分
  32278. return copyObj.clone()
  32279. }
  32280. }
  32281. for (var key in copyObj) {
  32282. if (copyObj[key] instanceof Object && !isSimpleCopy)
  32283. result[key] = this.CloneObject(copyObj[key]);
  32284. else
  32285. result[key] = copyObj[key];
  32286. //如果是函数类同基本数据,即复制引用
  32287. }
  32288. return result;
  32289. }
  32290. ,
  32291. CloneClassObject :function(copyObj, {ignoreList=[],simpleCopyList=[]}={}){//复杂类对象
  32292. var newobj = new copyObj.constructor();
  32293. this.CopyClassObject(newobj, copyObj, {ignoreList,simpleCopyList});
  32294. return newobj
  32295. }
  32296. ,
  32297. CopyClassObject :function(targetObj, copyObj, {ignoreList=[],simpleCopyList=[]}={}){//复杂类对象
  32298. for(let i in copyObj){
  32299. if(i in copyObj.__proto__)break; //到函数了跳出
  32300. if(ignoreList.includes(i)){
  32301. continue;
  32302. }else if(simpleCopyList.includes(i)){
  32303. targetObj[i] = copyObj[i];
  32304. }else {
  32305. targetObj[i] = this.CloneObject(copyObj[i], null, false, simpleCopyList );
  32306. }
  32307. /* else if(copyObj[i].clone instanceof Function ){
  32308. targetObj[i] = copyObj[i].clone()
  32309. }else{
  32310. targetObj[i] = copyObj[i];
  32311. } */
  32312. }
  32313. }
  32314. ,
  32315. ifSame : function(object1, object2, simpleEqualClass=[]){ //对于复杂的类对象,若能简单判断就直接写进simpleEqualClass
  32316. if(object1 == object2 )return true // 0 != undefined , 0 == ''
  32317. else if(!object1 || !object2) return false
  32318. else if(object1.constructor != object2.constructor){
  32319. return false
  32320. }else if(simpleEqualClass.some(className => object1 instanceof className)){
  32321. return object1 == object2
  32322. }else if(object1 instanceof Array ) {
  32323. if(object1.length != object2.length)return false;
  32324. var _object2 = object2.slice(0);
  32325. for(let i=0;i<object1.length;i++){
  32326. var u = _object2.find(e=>Common$1.ifSame(object1[i], e, simpleEqualClass));
  32327. if(u == void 0 && !_object2.includes(u) && !object1.includes(u))return false;
  32328. else {
  32329. let index = _object2.indexOf(u);
  32330. _object2.splice(index,1);
  32331. }
  32332. }
  32333. return true
  32334. }else if(object1.equals instanceof Function ){//复杂数据仅支持这种,其他的可能卡住?
  32335. return object1.equals(object2)
  32336. }else if(typeof object1 == 'number' || typeof object1 == 'string'){
  32337. if(isNaN(object1) && isNaN(object2))return true
  32338. else return object1 == object2
  32339. }else if(typeof object1 == "object"){
  32340. var keys1 = Object.keys(object1);
  32341. var keys2 = Object.keys(object2);
  32342. if(!Common$1.ifSame(keys1,keys2,simpleEqualClass))return false;
  32343. for(let i in object1){
  32344. var same = Common$1.ifSame(object1[i], object2[i],simpleEqualClass);
  32345. if(!same)return false
  32346. }
  32347. return true
  32348. }else {
  32349. console.log('isSame出现例外');
  32350. }
  32351. }
  32352. ,
  32353. replaceAll : function (str, f, e) {
  32354. //f全部替换成e
  32355. var reg = new RegExp(f, "g"); //创建正则RegExp对象
  32356. return str.replace(reg, e);
  32357. }
  32358. ,
  32359. downloadFile : function(data, filename, cb) {
  32360. var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
  32361. save_link.href = data;
  32362. save_link.download = filename;
  32363. var event = document.createEvent('MouseEvents');
  32364. event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  32365. save_link.dispatchEvent(event);
  32366. cb && cb();
  32367. },
  32368. dealURL(url){
  32369. return this.replaceAll(url, "\\+", "%2B");// 浏览器似乎不支持访问带+的地址
  32370. },
  32371. getNameFromURL(url){
  32372. let get = (e)=>{
  32373. return e.split('/').pop()
  32374. };
  32375. if(url instanceof Array){
  32376. return url.map(e=>get(e))
  32377. }
  32378. return get(url)
  32379. },
  32380. //---------------------------
  32381. intervalTool:{ //延时update,防止卡顿
  32382. list:[],
  32383. /* isWaiting:function(name, func, delayTime ){
  32384. let item = this.list.find(e=>e.name == name)
  32385. if(!item){ //如果没有该项, 则加入循环
  32386. let ifContinue = func()
  32387. item = {name}
  32388. this.list.push(item);
  32389. setTimeout(()=>{
  32390. var a = this.list.indexOf(item);
  32391. this.list.splice(a,1);
  32392. if(item.requestUpdate || ifContinue ) this.isWaiting(name, func, delayTime) //循环
  32393. },delayTime)
  32394. }else{//如果有该项,说明现在请求下一次继续更新
  32395. //if(delayTime == 0){//想立刻更新一次
  32396. // func()
  32397. //}else{
  32398. item.requestUpdate = true
  32399. //}
  32400. }
  32401. }, */
  32402. isWaiting:function(name, func, delayTime/* , autoCycle */){
  32403. let item = this.list.find(e=>e.name == name);
  32404. if(!item){ //如果没有该项, 则加入循环
  32405. let ifContinue = func();
  32406. item = {name, func, delayTime};
  32407. this.list.push(item);
  32408. setTimeout(()=>{
  32409. var a = this.list.indexOf(item);
  32410. this.list.splice(a,1);
  32411. let {func, delayTime} = item;
  32412. if(item.requestUpdate || ifContinue ) this.isWaiting(name, func, delayTime); //循环
  32413. },delayTime);
  32414. }else {//如果有该项,说明现在请求下一次继续更新
  32415. //if(delayTime == 0){//想立刻更新一次
  32416. // func()
  32417. //}else{
  32418. //更新属性
  32419. item.func = func;
  32420. item.delayTime = delayTime;
  32421. item.requestUpdate = true;
  32422. //}
  32423. }
  32424. },
  32425. }
  32426. ,
  32427. pushToGroupAuto : function(items, groups, recognizeFunction){//自动分组。 items是将分到一起的组合。items.length = 1 or 2.
  32428. recognizeFunction = recognizeFunction || function(){};
  32429. var atGroups = groups.filter(group=>group.find(
  32430. item => items[0] == item || recognizeFunction(item, items[0]) || items[1] == item || items[1] && recognizeFunction(item, items[1])
  32431. ));
  32432. if(atGroups.length){//在不同组
  32433. //因为items是一组的,所以先都放入组1
  32434. items.forEach(item=> {if(!atGroups[0].includes(item)) atGroups[0].push(item);});
  32435. if(atGroups.length>1){//如果在不同组,说明这两个组需要合并
  32436. var combineGroup = [];
  32437. atGroups.forEach(group=>{
  32438. combineGroup = Common$1.getUnionSet(combineGroup, group);
  32439. groups.splice(groups.indexOf(group),1);
  32440. });
  32441. groups.push(combineGroup);
  32442. }
  32443. }else {//直接加入为一组
  32444. groups.push(items);
  32445. }
  32446. },
  32447. getBestCount : function(name, minCount=1,maxCount=6, durBound1 = 1.2, durBound2 = 10, ifLog){
  32448. let timeStamp = performance.getEntriesByName("loop-start");
  32449. let count;
  32450. if(timeStamp.length){
  32451. let dur = performance.now() - timeStamp[timeStamp.length-1].startTime; //dur在iphoneX中静止有7,pc是2
  32452. count = Math.round(math.linearClamp(dur, durBound1,durBound2, maxCount, minCount));
  32453. if(ifLog){//注意,console.log本身用时挺高, 降4倍时可能占用0.5毫秒
  32454. name && count && console.log(name, count , ' ,dur:', dur.toFixed(3));
  32455. }
  32456. }else {
  32457. count = maxCount; // ?
  32458. }
  32459. //主要在手机端有效果。
  32460. return count
  32461. },
  32462. batchHandling : {//分批处理
  32463. lists:[],
  32464. getSlice : function(name, items , {stopWhenAllUsed, min=5,max=100, durBound1 , durBound2, useEquals , maxUseCount}){
  32465. if(items.length == 0 ||
  32466. ((maxUseCount = maxUseCount == void 0 ? Common$1.getBestCount(name, min,max , durBound1, durBound2 /* , true */ ) : maxUseCount), !maxUseCount) //本次最多可以使用的个数
  32467. ){
  32468. return {list:[]}
  32469. }
  32470. if(!this.lists[name]) this.lists[name] = {list:[] };
  32471. //更新列表项目,但不变原来的顺序
  32472. let list = this.lists[name].list.filter(a=>items.some(item=> useEquals ? a.item.equals(item) : a.item == item));//去掉已经不在items里的项目
  32473. this.lists[name].list = list;
  32474. items.forEach(item=>{//增加新的项目。
  32475. if(!list.some(a=>useEquals ? a.item.equals(item) : a.item == item )){
  32476. list.push({item, count:0});
  32477. }
  32478. });
  32479. //至此,在后排的都是未使用的
  32480. let unUsed = list.filter(e=>e.count == 0);//未使用的项目(count为0)优先
  32481. let result = [];
  32482. unUsed.slice(0,maxUseCount).forEach(e=>{
  32483. result.push(e.item);
  32484. e.count ++;
  32485. });
  32486. if(unUsed.length > maxUseCount){
  32487. //还是剩有未使用的项目,等待下一次
  32488. }else {
  32489. //所有项目都能使用一次
  32490. if(!stopWhenAllUsed){ //若不是全部使用就停止
  32491. let wholeCount = Math.min(items.length, maxUseCount);
  32492. let restCount = wholeCount - result.length; //补齐
  32493. list.slice(0,restCount).forEach(e=>{
  32494. result.push(e.item);
  32495. e.count ++;
  32496. });
  32497. }
  32498. list.forEach(e=>e.count--); //复原,等待新的循环
  32499. }
  32500. /* result.forEach((e,i)=>{//有重复的
  32501. if( result.slice(0,i).some(a=>a.equals(e)) || result.slice(i+1).some(a=>a.equals(e)) ) {
  32502. console.log(e)
  32503. }
  32504. }) */
  32505. return {list:result }
  32506. }
  32507. },
  32508. watch: function(object, propName, initialValue){ //监听某个属性的变化
  32509. let v = initialValue;
  32510. Object.defineProperty(object, propName, {
  32511. get: function() {
  32512. return v
  32513. },
  32514. set: function(e) {
  32515. console.warn('watch:',propName, e);
  32516. v = e;
  32517. }
  32518. });
  32519. },
  32520. };
  32521. Potree.Common = Common$1;
  32522. class View{//base
  32523. constructor () {
  32524. this.position = new Vector3(0, 0, 0);
  32525. this.yaw = Math.PI / 4;
  32526. this._pitch = -Math.PI / 4;
  32527. this.radius = 1;
  32528. this.maxPitch = Math.PI / 2;
  32529. this.minPitch = -Math.PI / 2;
  32530. }
  32531. clone () {
  32532. let c = new View();
  32533. c.yaw = this.yaw;
  32534. c._pitch = this.pitch;
  32535. c.radius = this.radius;
  32536. c.maxPitch = this.maxPitch;
  32537. c.minPitch = this.minPitch;
  32538. return c;
  32539. }
  32540. get pitch () {
  32541. return this._pitch;
  32542. }
  32543. set pitch (angle) {
  32544. this._pitch = Math.max(Math.min(angle, this.maxPitch), this.minPitch);
  32545. }
  32546. get direction () {
  32547. let dir = new Vector3(0, 1, 0);
  32548. dir.applyAxisAngle(new Vector3(1, 0, 0), this.pitch);
  32549. dir.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  32550. return dir;
  32551. }
  32552. set direction (dir) {
  32553. dir = dir.clone().normalize();//add
  32554. if(dir.x === 0 && dir.y === 0){
  32555. this.pitch = Math.PI / 2 * Math.sign(dir.z);
  32556. //this.yaw = 0
  32557. //console.log('yaw没变',this.yaw)
  32558. }else {
  32559. let yaw = Math.atan2(dir.y, dir.x) - Math.PI / 2;
  32560. let pitch = Math.atan2(dir.z, Math.sqrt(dir.x * dir.x + dir.y * dir.y));
  32561. this.yaw = yaw;
  32562. this.pitch = pitch;
  32563. }
  32564. }
  32565. lookAt(t){//setPivot
  32566. let V;
  32567. if(arguments.length === 1){
  32568. V = new Vector3().subVectors(t, this.position);
  32569. }else if(arguments.length === 3){
  32570. V = new Vector3().subVectors(new Vector3(...arguments), this.position);
  32571. }
  32572. let radius = V.length();
  32573. let dir = V.normalize();
  32574. this.radius = radius;
  32575. this.direction = dir;
  32576. }
  32577. getPivot () {
  32578. return new Vector3().addVectors(this.position, this.direction.multiplyScalar(this.radius));
  32579. }
  32580. getSide () {
  32581. let side = new Vector3(1, 0, 0);
  32582. side.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  32583. return side;
  32584. }
  32585. pan (x, y) {
  32586. let dir = new Vector3(0, 1, 0);
  32587. dir.applyAxisAngle(new Vector3(1, 0, 0), this.pitch);
  32588. dir.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  32589. // let side = new THREE.Vector3(1, 0, 0);
  32590. // side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
  32591. let side = this.getSide();
  32592. let up = side.clone().cross(dir);
  32593. let pan = side.multiplyScalar(x).add(up.multiplyScalar(y));
  32594. this.position = this.position.add(pan);
  32595. // this.target = this.target.add(pan);
  32596. }
  32597. translate (x, y, z) {
  32598. let dir = new Vector3(0, 1, 0);
  32599. dir.applyAxisAngle(new Vector3(1, 0, 0), this.pitch);
  32600. dir.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  32601. let side = new Vector3(1, 0, 0);
  32602. side.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  32603. let up = side.clone().cross(dir);
  32604. let t = side.multiplyScalar(x)
  32605. .add(dir.multiplyScalar(y))
  32606. .add(up.multiplyScalar(z));
  32607. this.position = this.position.add(t);
  32608. }
  32609. translateWorld (x, y, z) {
  32610. this.position.x += x;
  32611. this.position.y += y;
  32612. this.position.z += z;
  32613. }
  32614. setView(position, target, duration = 0, callback = null){
  32615. let endPosition = null;
  32616. if(position instanceof Array){
  32617. endPosition = new Vector3(...position);
  32618. }else if(position.x != null){
  32619. endPosition = position.clone();
  32620. }
  32621. let endTarget = null;
  32622. if(target instanceof Array){
  32623. endTarget = new Vector3(...target);
  32624. }else if(target.x != null){
  32625. endTarget = target.clone();
  32626. }
  32627. const startPosition = this.position.clone();
  32628. const startTarget = this.getPivot();
  32629. //const endPosition = position.clone();
  32630. //const endTarget = target.clone();
  32631. let easing = TWEEN.Easing.Quartic.Out;
  32632. if(duration === 0){
  32633. this.position.copy(endPosition);
  32634. this.lookAt(endTarget);
  32635. }else {
  32636. let value = {x: 0};
  32637. let tween = new TWEEN.Tween(value).to({x: 1}, duration);
  32638. tween.easing(easing);
  32639. //this.tweens.push(tween);
  32640. tween.onUpdate(() => {
  32641. let t = value.x;
  32642. //console.log(t);
  32643. const pos = new Vector3(
  32644. (1 - t) * startPosition.x + t * endPosition.x,
  32645. (1 - t) * startPosition.y + t * endPosition.y,
  32646. (1 - t) * startPosition.z + t * endPosition.z,
  32647. );
  32648. const target = new Vector3(
  32649. (1 - t) * startTarget.x + t * endTarget.x,
  32650. (1 - t) * startTarget.y + t * endTarget.y,
  32651. (1 - t) * startTarget.z + t * endTarget.z,
  32652. );
  32653. this.position.copy(pos);
  32654. this.lookAt(target);
  32655. });
  32656. tween.start();
  32657. tween.onComplete(() => {
  32658. if(callback){
  32659. callback();
  32660. }
  32661. });
  32662. }
  32663. }
  32664. };
  32665. let sid = 0;
  32666. class ExtendView extends View {
  32667. constructor () {
  32668. super();
  32669. this.yaw = 0; //Math.PI / 4; // = 4dkk lon + 90
  32670. this._pitch = 0; //-Math.PI / 4; //上下旋转 = 4dkk lat
  32671. this.sid = sid++;
  32672. this.LookTransition = 'LookTransition'+this.sid;
  32673. this.FlyTransition = 'FlyTransition'+this.sid;
  32674. }
  32675. //add------
  32676. applyToCamera(camera){
  32677. camera.position.copy(this.position);
  32678. camera.rotation.copy(this.rotation);
  32679. camera.updateMatrix();
  32680. camera.updateMatrixWorld();
  32681. //camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
  32682. }
  32683. get rotation(){
  32684. var rotation = new Euler;
  32685. rotation.order = "ZXY";
  32686. rotation.x = Math.PI / 2 + this.pitch;
  32687. rotation.z = this.yaw;
  32688. return rotation
  32689. }
  32690. set rotation(rotation){//这个在数字很小(垂直向上看)的时候水平旋转精度可能损失,导致突变到另一个角度去了,用 set quaternion比较好
  32691. //因为 rotation的y不一定是0 , 所以不能直接逆着写。
  32692. this.direction = new Vector3(0,0,-1).applyEuler(rotation);
  32693. }
  32694. get quaternion(){
  32695. return new Quaternion().setFromEuler(this.rotation)
  32696. }
  32697. set quaternion(q){
  32698. this.direction = new Vector3(0,0,-1).applyQuaternion(q); //注意如果得到的dir.x==dir.y==0, yaw不会变为0, 导致算的quaternion和q不一致
  32699. }
  32700. copy(a){
  32701. Common$1.CopyClassObject(this, a, {ignoreList: ['_listeners']});
  32702. }
  32703. clone () {
  32704. return Common$1.CloneClassObject(this, {ignoreList: ['_listeners']})
  32705. }
  32706. //----------
  32707. setCubeView(dir) {
  32708. switch(dir) {
  32709. case "front":
  32710. this.yaw = 0;
  32711. this.pitch = 0;
  32712. break;
  32713. case "back":
  32714. this.yaw = Math.PI;
  32715. this.pitch = 0;
  32716. break;
  32717. case "left":
  32718. this.yaw = -Math.PI / 2;
  32719. this.pitch = 0;
  32720. break;
  32721. case "right":
  32722. this.yaw = Math.PI / 2;
  32723. this.pitch = 0;
  32724. break;
  32725. case "top":
  32726. this.yaw = 0;
  32727. this.pitch = -Math.PI / 2;
  32728. break;
  32729. case "bottom":
  32730. this.yaw = -Math.PI;
  32731. this.pitch = Math.PI / 2;
  32732. break;
  32733. }
  32734. }
  32735. /* pan (x, y) {
  32736. let dir = new THREE.Vector3(0, 1, 0);
  32737. dir.applyAxisAngle(new THREE.Vector3(1, 0, 0), this.pitch);
  32738. dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
  32739. // let side = new THREE.Vector3(1, 0, 0);
  32740. // side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
  32741. let side = this.getSide();
  32742. let up = side.clone().cross(dir);
  32743. let pan = side.multiplyScalar(x).add(up.multiplyScalar(y));
  32744. this.position = this.position.add(pan);
  32745. // this.target = this.target.add(pan);
  32746. } */
  32747. pan (x, y) { //发现pan其实就是translate
  32748. this.translate(x, 0, y);
  32749. }
  32750. translate (x, y, z, forceHorizon ) {
  32751. //相机方向
  32752. let dir = new Vector3(0, 1, 0);
  32753. dir.applyAxisAngle(new Vector3(1, 0, 0), forceHorizon ? 0 : this.pitch); //上下角度
  32754. dir.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);//水平角度
  32755. let side = new Vector3(1, 0, 0);
  32756. side.applyAxisAngle(new Vector3(0, 0, 1), this.yaw); //垂直于相机当前水平朝向的 左右方向
  32757. let up = side.clone().cross(dir); //垂直于相机当前水平朝向的 向上方向
  32758. let t = side.multiplyScalar(x) //x影响 左右分量
  32759. .add(dir.multiplyScalar(y)) //y影响 前后分量
  32760. .add(up.multiplyScalar(z)); //z影响 上下分量
  32761. this.position = this.position.add(t);
  32762. if((!math.closeTo(x, 0, 1e-4) || !math.closeTo(y, 0, 1e-4) || !math.closeTo(z, 0, 1e-4)) && Potree.settings.displayMode != 'showPanos'){
  32763. this.cancelFlying('pos');
  32764. }
  32765. this.restrictPos();
  32766. }
  32767. translateWorld (x, y, z) {
  32768. super.translateWorld(x, y, z);
  32769. if((!math.closeTo(x, 0, 1e-4) || !math.closeTo(y, 0, 1e-4) || !math.closeTo(z, 0, 1e-4)) && Potree.settings.displayMode != 'showPanos'){
  32770. this.cancelFlying('pos');
  32771. }
  32772. this.restrictPos();
  32773. }
  32774. restrictPos(position){//add
  32775. if(this.limitBound){
  32776. (position || this.position).clamp(this.limitBound.min, this.limitBound.max);
  32777. }
  32778. }
  32779. isFlying(type='all'){
  32780. let a = transitions.getById(this.FlyTransition).length > 0;
  32781. let b = transitions.getById(this.LookTransition).length > 0;
  32782. return type == 'pos' ? a : type == 'rotate' ? b : (a || b)
  32783. }
  32784. cancelFlying(type='all', dealCancel=true){//外界只能通过这个来cancel
  32785. type == 'pos' ? transitions.cancelById(this.FlyTransition, dealCancel )
  32786. : type == 'rotate' ? transitions.cancelById(this.LookTransition, dealCancel )
  32787. : (transitions.cancelById(this.FlyTransition, dealCancel ), transitions.cancelById(this.LookTransition, dealCancel ));
  32788. //console.log('cancelFlying ' , this.sid, type)
  32789. }
  32790. setView( info = {}){
  32791. // position, target, duration = 0, callback = null, onUpdate = null, Easing='', cancelFun
  32792. this.cancelFlying();
  32793. if(this.isFlying()){
  32794. if(info.cancelFun)info.cancelFun();
  32795. return ;//取消失败
  32796. }
  32797. let posWaitDone, rotWaitDone , dir;
  32798. let posDone = ()=>{
  32799. rotWaitDone || done();
  32800. posWaitDone = false;
  32801. };
  32802. let rotDone = ()=>{
  32803. if(endTarget){
  32804. this.lookAt(endTarget); //compute radius for orbitcontrol
  32805. }else if(endQuaternion){
  32806. this.rotation = new Euler().setFromQuaternion(endQuaternion);
  32807. }else if(endYaw != void 0){
  32808. this.yaw = endYaw, this.pitch = endPitch;
  32809. }
  32810. //if(dir.x == 0 && dir.y == 0)this.yaw = 0 //统一一下 朝上的话是正的。朝下的一般不是0,会保留一个接近0的小数所以不用管
  32811. posWaitDone || done();
  32812. rotWaitDone = false;
  32813. };
  32814. let done = ()=>{ //一定要旋转和位移都结束了才能执行
  32815. let f = ()=>{
  32816. this.position.copy(endPosition); //因为延时1后control的update会导致位置改变
  32817. info.callback && info.callback();
  32818. this.dispatchEvent('flyingDone');
  32819. viewer.dispatchEvent('content_changed');
  32820. };
  32821. if(info.duration){
  32822. setTimeout(f,1);//延迟是为了使isFlying先为false
  32823. }else {
  32824. f(); //有的需要迅速执行回调
  32825. }
  32826. };
  32827. let endPosition = new Vector3().copy(info.position);
  32828. let startPosition = this.position.clone();
  32829. let startQuaternion, endQuaternion, endTarget = null,
  32830. endYaw, startYaw, endPitch, startPitch ;
  32831. this.restrictPos(endPosition);
  32832. if(info.endYaw != void 0) {
  32833. startPitch = this.pitch;
  32834. endPitch = info.endPitch;
  32835. let a = math.getStandardYaw(this.yaw, info.endYaw );
  32836. startYaw = a[0]; endYaw = a[1];
  32837. }else if(info.target ){
  32838. endTarget = new Vector3().copy(info.target);
  32839. endQuaternion = math.getQuaFromPosAim(endPosition,endTarget); //若为垂直,会自动偏向x负的方向
  32840. dir = new Vector3().subVectors(endTarget, endPosition).normalize();
  32841. //console.log(dir, this.direction)
  32842. }else if(info.quaternion){
  32843. endQuaternion = info.quaternion.clone();
  32844. }
  32845. if(endQuaternion){
  32846. startQuaternion = this.quaternion;
  32847. }
  32848. if(!info.duration){
  32849. this.position.copy(endPosition);
  32850. this.restrictPos();
  32851. posWaitDone = true, rotWaitDone = true;
  32852. info.onUpdate && info.onUpdate(1);
  32853. posDone();
  32854. rotDone();
  32855. }else {
  32856. info.onUpdate && info.onUpdate(0); //初始化progress
  32857. let posChange = !this.position.equals(endPosition);
  32858. if(posChange){
  32859. posWaitDone = true;
  32860. transitions.start(lerp.vector(this.position, endPosition, (pos, progress, delta)=>{
  32861. info.onUpdate && info.onUpdate(progress, delta);
  32862. }), info.duration, posDone , 0, info.Easing ? easing[info.Easing] : easing.easeInOutSine ,null, this.FlyTransition, ()=>{
  32863. //中途取消
  32864. if(endTarget ){
  32865. /* endPosition = new THREE.Vector3().copy(this.position)//更改旋转的endQuaternion
  32866. endQuaternion = math.getQuaFromPosAim(endPosition,endTarget) */
  32867. //直接改变endQuaternion会突变,所以还是cancel吧
  32868. this.cancelFlying('rotate');
  32869. }
  32870. posWaitDone = false;
  32871. info.cancelFun && info.cancelFun();
  32872. }, info.ignoreFirstFrame,info.forbitCancel);
  32873. }
  32874. if(endQuaternion || endYaw != void 0){
  32875. rotWaitDone = true;
  32876. transitions.start( (progress, delta )=>{
  32877. if(endYaw != void 0){
  32878. this.yaw = startYaw * (1-progress) + endYaw * progress;
  32879. this.pitch = startPitch * (1-progress) + endPitch * progress;
  32880. }else {
  32881. let quaternion = (new Quaternion()).copy(startQuaternion);
  32882. lerp.quaternion(quaternion, endQuaternion)(progress); //在垂直的视角下的角度突变的厉害,这时候可能渐变yaw比较好
  32883. //console.log(quaternion)
  32884. //this.rotation = new THREE.Euler().setFromQuaternion(quaternion)
  32885. this.quaternion = quaternion;
  32886. }
  32887. posChange || info.onUpdate && info.onUpdate(progress, delta);
  32888. }, info.duration, rotDone , 0, info.Easing ? easing[info.Easing] : easing.easeInOutSine ,null, this.LookTransition, ()=>{
  32889. //中途取消
  32890. rotWaitDone = false;
  32891. info.cancelFun && info.cancelFun();
  32892. }, info.ignoreFirstFrame, info.forbitCancel);
  32893. }
  32894. }
  32895. }
  32896. //平移Ortho相机
  32897. moveOrthoCamera(viewport, info, duration, easeName){//boundSize优先于endZoom。
  32898. let camera = info.camera || viewport.camera;
  32899. let startZoom = camera.zoom;
  32900. let endPosition = info.endPosition || info.position;
  32901. let boundSize = info.boundSize;
  32902. let endZoom = info.endZoom;
  32903. let margin = info.margin || {x:0,y:0};/* 200 */ //像素
  32904. let onUpdate = info.onUpdate;
  32905. if(info.bound){//需要修改boundSize以适应相机的旋转,当相机不在xy水平面上朝向z时
  32906. endPosition = endPosition || info.bound.getCenter(new Vector3());
  32907. let matrixRot = new Matrix4().makeRotationFromEuler(this.rotation).invert();
  32908. let boundingBox = info.bound.clone().applyMatrix4(matrixRot);
  32909. boundSize = boundingBox.getSize(new Vector3());
  32910. }
  32911. if(boundSize && boundSize.x == 0 && boundSize.y == 0){
  32912. boundSize.set(1,1); //避免infinity
  32913. }
  32914. this.setView( Object.assign(info, { position:endPosition, duration,
  32915. onUpdate:(progress, delta)=>{
  32916. if(boundSize || endZoom){
  32917. if(boundSize){
  32918. let aspect = boundSize.x / boundSize.y;
  32919. let w, h;
  32920. if(camera.aspect > aspect){//视野更宽则用bound的纵向来决定
  32921. h = boundSize.y;
  32922. endZoom = (viewport.resolution.y - margin.y) / h; //注意,要在resolution不为0时执行
  32923. }else {
  32924. w = boundSize.x;
  32925. endZoom = (viewport.resolution.x - margin.x) / w;
  32926. }
  32927. //onUpdate时更新endzoom是因为画布大小可能更改
  32928. }
  32929. camera.zoom = endZoom * progress + startZoom * (1 - progress);
  32930. camera.updateProjectionMatrix();
  32931. onUpdate && onUpdate(progress, delta);
  32932. }
  32933. },
  32934. Easing:easeName
  32935. }));
  32936. }
  32937. zoomOrthoCamera(camera, endZoom, pointer, duration, onProgress){//定点缩放
  32938. let startZoom = camera.zoom;
  32939. let pointerPos = new Vector3(pointer.x, pointer.y,0.5);
  32940. transitions.start(( progress)=>{
  32941. let oldPos = pointerPos.clone().unproject(camera);
  32942. camera.zoom = endZoom * progress + startZoom * (1 - progress);
  32943. camera.updateProjectionMatrix();
  32944. let newPos = pointerPos.clone().unproject(camera);
  32945. //定点缩放, 恢复一下鼠标所在位置的位置改变量
  32946. let moveVec = new Vector3().subVectors(newPos, oldPos);
  32947. camera.position.sub(moveVec);
  32948. this.position.copy(camera.position);
  32949. onProgress && onProgress();
  32950. } , duration, null/* done */, 0, easing.easeInOutSine, null, "zoomInView"/* , info.cancelFun */);
  32951. }
  32952. tranCamera(viewport, info, duration, easeName){
  32953. viewport.camera = info.midCamera;
  32954. //viewport.camera.matrixWorld = info.endCamera.matrixWorld
  32955. console.log('tranCamera');
  32956. //viewer.setCameraMode(CameraMode.ORTHOGRAPHIC)
  32957. info.midCamera.projectionMatrix.copy(info.startCamera.projectionMatrix);
  32958. let onUpdate = info.onUpdate;
  32959. info.onUpdate = (progress, delta)=>{
  32960. lerp.matrix4(info.midCamera.projectionMatrix, info.endCamera.projectionMatrix)(progress);
  32961. onUpdate && onUpdate(progress, delta);
  32962. };
  32963. let callback = info.callback;
  32964. info.callback = info.cancelFun = ()=>{
  32965. viewport.camera = info.endCamera;
  32966. viewer.scene.measurements.forEach((e)=>{
  32967. Potree.Utils.updateVisible(e, 'tranCamera', true);
  32968. });
  32969. this.applyToCamera(viewport.camera);
  32970. viewer.dispatchEvent({type:'camera_changed', viewport:viewer.mainViewport, changeInfo:{}});//update sprite
  32971. console.log('tranCamera end');
  32972. callback && callback();
  32973. };
  32974. info.forbitCancel = true;
  32975. viewer.scene.measurements.forEach((e)=>{
  32976. Potree.Utils.updateVisible(e, 'tranCamera', false); //含sprite且实时更新size的都要隐藏
  32977. });
  32978. info.camera = info.endCamera;
  32979. if(info.camera.type == "OrthographicCamera"){
  32980. this.moveOrthoCamera(viewport, info, duration, easeName);
  32981. }else {
  32982. this.setView( Object.assign(info, { duration}) );
  32983. }
  32984. }
  32985. };
  32986. var math = {
  32987. getBaseLog(x, y) {//返回以 x 为底 y 的对数(即 logx y) . Math.log 返回一个数的自然对数
  32988. return Math.log(y) / Math.log(x);
  32989. }
  32990. ,
  32991. convertVector : {
  32992. ZupToYup: function(e){//navvis -> 4dkk
  32993. return new Vector3(e.x,e.z,-e.y)
  32994. },
  32995. YupToZup: function(e){//4dkk -> navvis
  32996. return new Vector3(e.x,-e.z,e.y)
  32997. },
  32998. },
  32999. convertQuaternion: {
  33000. ZupToYup: function(e){//navvis -> 4dkk //不同于convertVisionQuaternion
  33001. let rotation = new Euler(-Math.PI/2,0,0);
  33002. let quaternion = new Quaternion().setFromEuler(rotation);
  33003. return e.clone().premultiply(quaternion)
  33004. //return new THREE.Quaternion(e.x,e.z,-e.y,e.w).multiply((new THREE.Quaternion).setFromAxisAngle(new THREE.Vector3(1,0,0), THREE.Math.degToRad(90)))
  33005. },
  33006. YupToZup: function(e){//4dkk -> navvis
  33007. let rotation = new Euler(Math.PI/2,0,0);
  33008. let quaternion = new Quaternion().setFromEuler(rotation);
  33009. return e.clone().premultiply(quaternion)
  33010. },
  33011. },
  33012. convertVisionQuaternion: function(e) {
  33013. return new Quaternion(e.x,e.z,-e.y,e.w).multiply((new Quaternion).setFromAxisAngle(new Vector3(0,1,0), MathUtils$1.degToRad(90)))
  33014. },
  33015. invertVisionQuaternion : function(e) {//反转给算法部
  33016. var a = e.clone().multiply((new Quaternion).setFromAxisAngle(new Vector3(0,1,0), MathUtils$1.degToRad(-90)));
  33017. return new Quaternion(a.x,-a.z,a.y,a.w)
  33018. },
  33019. //------------
  33020. getVec2Angle : function(dir1,dir2){
  33021. return Math.acos( MathUtils$1.clamp(this.getVec2Cos(dir1,dir2), -1,1) )
  33022. },
  33023. getVec2Cos : function(dir1,dir2){
  33024. return dir1.dot(dir2) / dir1.length() / dir2.length()
  33025. },
  33026. getAngle:function(vec1, vec2, axis){//带方向的角度 vector3
  33027. var angle = vec1.angleTo(vec2);
  33028. var axis_ = vec1.clone().cross(vec2);
  33029. if(typeof axis == 'string'){
  33030. if(axis_[axis] < 0){
  33031. angle *= -1;
  33032. }
  33033. }else {//vector3
  33034. if(axis_.dot(axis)< 0){
  33035. angle *= -1;
  33036. }
  33037. }
  33038. return angle
  33039. },
  33040. closeTo : function(a,b, precision=1e-6){
  33041. let f = (a,b)=>{
  33042. return Math.abs(a-b) < precision;
  33043. };
  33044. if(typeof (a) == 'number'){
  33045. return f(a, b);
  33046. }else {
  33047. let judge = (name)=>{
  33048. if(a[name] == void 0)return true //有值就判断,没值就不判断
  33049. else return f(a[name],b[name])
  33050. };
  33051. return judge('x') && judge('y') && judge('z') && judge('w')
  33052. }
  33053. },
  33054. toPrecision: function (e, t) {//xzw change 保留小数
  33055. var f = function (e, t) {
  33056. var i = Math.pow(10, t);
  33057. return Math.round(e * i) / i
  33058. };
  33059. if (e instanceof Array) {
  33060. for (var s = 0; s < e.length; s++) {
  33061. e[s] = f(e[s], t);
  33062. }
  33063. return e;
  33064. } else if (e instanceof Object) {
  33065. for (var s in e) {
  33066. e[s] = f(e[s], t);
  33067. }
  33068. return e;
  33069. } else if(typeof e == 'number'){
  33070. return f(e, t)
  33071. }else {
  33072. return e
  33073. }
  33074. },
  33075. isEmptyQuaternion: function(e) {
  33076. return 0 === Math.abs(e.x) && 0 === Math.abs(e.y) && 0 === Math.abs(e.z) && 0 === Math.abs(e.w)
  33077. },
  33078. projectPositionToCanvas: function(e, t, i) {
  33079. i = i || new Vector3,
  33080. i.copy(e);
  33081. var r = .5 * $('#player').width()
  33082. , o = .5 * $('#player').height();
  33083. return i.project(t),
  33084. i.x = i.x * r + r,
  33085. i.y = -(i.y * o) + o,
  33086. i
  33087. },
  33088. handelPadResize:false,
  33089. /* handelPadding : function () { //去除player左边和上面的宽高,因为pc的player左上有其他element 许钟文
  33090. var pads = [];//记录下来避免反复计算
  33091. var index = [];
  33092. var resetPad = function(){
  33093. pads = [];
  33094. index = [];
  33095. math.handelPadResize = false; //switchview时resized为true
  33096. }
  33097. if(config.isEdit && !config.isMobile){
  33098. window.addEventListener('resize',resetPad);
  33099. }
  33100. return function(x, y, domE){
  33101. if(!config.isEdit || config.isMobile) {
  33102. return {
  33103. x: x,
  33104. y: y
  33105. }
  33106. }
  33107. if(this.handelPadResize)resetPad();
  33108. domE = domE || $('#player')[0];
  33109. var pad;
  33110. var i = index.indexOf(domE);
  33111. if (i == -1){
  33112. index.push(domE);
  33113. pad = {
  33114. x: this.getOffset("left", domE),
  33115. y: this.getOffset("top", domE)
  33116. }
  33117. pads.push(pad)
  33118. }
  33119. else pad = pads[i];
  33120. return {
  33121. x: x - pad.x,
  33122. y: y - pad.y
  33123. }
  33124. }
  33125. }(), */
  33126. getOffset: function (type, element, parent) {//获取元素的边距 许钟文
  33127. var offset = (type == "left") ? element.offsetLeft : element.offsetTop;
  33128. if (!parent) parent = $("body")[0];
  33129. while (element = element.offsetParent) {
  33130. if (element == parent) break;
  33131. offset += (type == "left") ? element.offsetLeft : element.offsetTop;
  33132. }
  33133. return offset;
  33134. }
  33135. ,
  33136. constrainedTurn: function(e) {
  33137. var t = e % (2 * Math.PI);
  33138. return t = t > Math.PI ? t -= 2 * Math.PI : t < -Math.PI ? t += 2 * Math.PI : t
  33139. },
  33140. getFOVDotThreshold: function(e) {
  33141. return Math.cos(MathUtils$1.degToRad(e / 2))
  33142. },
  33143. transform2DForwardVectorByCubeFace: function(e, t, i, n) {
  33144. switch (e) {
  33145. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  33146. i.set(1, t.y, t.x);
  33147. break;
  33148. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  33149. i.set(-1, t.y, -t.x);
  33150. break;
  33151. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  33152. i.set(-t.x, 1, -t.y);
  33153. break;
  33154. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  33155. i.set(-t.x, -1, t.y);
  33156. break;
  33157. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  33158. i.set(-t.x, t.y, 1);
  33159. break;
  33160. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  33161. i.set(t.x, t.y, -1);
  33162. }
  33163. n && i.normalize();
  33164. },
  33165. getFootPoint : function(oldPos, p1, p2, restricInline){ //找oldPos在线段p1, p2上的垂足
  33166. /* if(isWorld){//输出全局坐标 需要考虑meshGroup.position
  33167. p1 = p1.clone();
  33168. p2 = p2.clone();
  33169. p1.y += mainDesign.meshGroup.position.y;
  33170. p2.y += mainDesign.meshGroup.position.y;
  33171. } */
  33172. if(p1.equals(p2))return p1.clone()
  33173. var op1 = oldPos.clone().sub(p1);
  33174. var p1p2 = p1.clone().sub(p2);
  33175. var p1p2Len = p1p2.length();
  33176. var leftLen = op1.dot(p1p2) / p1p2Len;
  33177. var pos = p1.clone().add(p1p2.multiplyScalar( leftLen/p1p2Len ));
  33178. if(restricInline && pos.clone().sub(p1).dot( pos.clone().sub(p2) ) > 0){//foot不在线段上
  33179. if(pos.distanceTo(p1) < pos.distanceTo(p2)) pos = p1.clone();
  33180. else pos = p2.clone();
  33181. }
  33182. return pos;
  33183. },
  33184. /**
  33185. * 计算多边形的重心
  33186. * @param {*} points
  33187. */
  33188. getCenterOfGravityPoint : function(mPoints){
  33189. var area = 0.0;//多边形面积
  33190. var Gx = 0.0, Gy = 0.0;// 重心的x、y
  33191. for (var i = 1; i <= mPoints.length; i++) {
  33192. var ix = mPoints[i % mPoints.length].x;
  33193. var iy = mPoints[i % mPoints.length].y;
  33194. var nx = mPoints[i - 1].x;
  33195. var ny = mPoints[i - 1].y;
  33196. var temp = (ix * ny - iy * nx) / 2.0;
  33197. area += temp;
  33198. Gx += temp * (ix + nx) / 3.0;
  33199. Gy += temp * (iy + ny) / 3.0;
  33200. }
  33201. Gx = Gx / area;
  33202. Gy = Gy / area;
  33203. return { x: Gx, y: Gy };
  33204. },
  33205. getBound : function(ring){
  33206. var bound = new Box2();
  33207. for(var j=0,len = ring.length; j<len; j++){
  33208. bound.expandByPoint(ring[j]);
  33209. }
  33210. return bound;
  33211. },
  33212. isPointInArea : function(ring, holes, point, ifAtLine){//判断点是否在某个环内, 若传递了holes代表还要不能在内环内
  33213. var bound = this.getBound(ring);
  33214. if(point.x < bound.min.x || point.x > bound.max.x || point.y < bound.min.y || point.y > bound.max.y)return false;
  33215. var inside = false;
  33216. var x = point.x,
  33217. y = point.y;
  33218. for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
  33219. var xi = ring[i].x,
  33220. yi = ring[i].y;
  33221. var xj = ring[j].x,
  33222. yj = ring[j].y;
  33223. if((xi - x)*(yj - y) == (xi - x)*(yi - y) && x>=Math.min(xi,xj) && x<=Math.max(xi,xj)//xzw add
  33224. && y>=Math.min(yi,yj) && y<=Math.max(yi,yj)
  33225. ){
  33226. //return !!ifAtLine;//在线段上,则判断为…… (默认在外)
  33227. return {atLine:true}
  33228. }
  33229. if (((yi > y) != (yj > y)) &&
  33230. (x < (xj - xi) * (y - yi) / (yj - yi) + xi)
  33231. ) {
  33232. inside = !inside;
  33233. }
  33234. }
  33235. if(inside && holes){
  33236. return !holes.some(ring=>this.isPointInArea(ring, null, point, ifAtLine) ) //不能存在于任何一个二级内环内
  33237. }else {
  33238. return inside;
  33239. }
  33240. },
  33241. getArea : function (ring) { //求面积 顺时针为正 来自three shape
  33242. for (var t = ring.length, i = 0, n = t - 1, r = 0; r < t; n = r++)
  33243. i += ring[n].x * ring[r].y - ring[r].x * ring[n].y;
  33244. return -.5 * i
  33245. },
  33246. isInBetween : function(a, b, c, precision) {
  33247. // 如果b几乎等于a或c,返回false.为了避免浮点运行时两值几乎相等,但存在相差0.00000...0001的这种情况出现使用下面方式进行避免
  33248. /* if (Math.abs(a - b) < 0.000001 || Math.abs(b - c) < 0.000001) {
  33249. return false;
  33250. }
  33251. return (a <= b && b <= c) || (c <= b && b <= a);*/
  33252. //更改:如果b和a或c中一个接近 就算在a和c之间
  33253. return (a <= b && b <= c) || (c <= b && b <= a) || this.closeTo(a,b,precision) || this.closeTo(b,c,precision);
  33254. },
  33255. ifPointAtLineBound:function(point, linePoints, precision){
  33256. //待验证 横线和竖线比较特殊
  33257. return math.isInBetween(linePoints[0].x, point.x, linePoints[1].x, precision) && math.isInBetween(linePoints[0].y, point.y, linePoints[1].y, precision)
  33258. }
  33259. ,
  33260. isLineIntersect: function (line1, line2, notSegment, precision) {//线段和线段是否有交点. notSegment代表是直线而不是线段
  33261. var a1 = line1[1].y - line1[0].y;
  33262. var b1 = line1[0].x - line1[1].x;
  33263. var c1 = a1 * line1[0].x + b1 * line1[0].y;
  33264. //转换成一般式: Ax+By = C
  33265. var a2 = line2[1].y - line2[0].y;
  33266. var b2 = line2[0].x - line2[1].x;
  33267. var c2 = a2 * line2[0].x + b2 * line2[0].y;
  33268. // 计算交点
  33269. var d = a1 * b2 - a2 * b1;
  33270. // 当d==0时,两线平行
  33271. if (d == 0) {
  33272. return false;
  33273. } else {
  33274. var x = (b2 * c1 - b1 * c2) / d;
  33275. var y = (a1 * c2 - a2 * c1) / d;
  33276. // 检测交点是否在两条线段上
  33277. /* if (notSegment || (isInBetween(line1[0].x, x, line1[1].x) || isInBetween(line1[0].y, y, line1[1].y)) &&
  33278. (isInBetween(line2[0].x, x, line2[1].x) || isInBetween(line2[0].y, y, line2[1].y))) {
  33279. return {x,y};
  33280. } */
  33281. if (notSegment || math.ifPointAtLineBound({x,y}, line1, precision) && math.ifPointAtLineBound({x,y}, line2, precision)){
  33282. return {x,y};
  33283. }
  33284. }
  33285. },
  33286. getNormal2d : function(o={} ){//获取二维法向量 方向向内
  33287. var x,y, x1,y1;
  33288. //line2d的向量
  33289. if(o.vec){
  33290. x1 = o.vec.x; y1 = o.vec.y;
  33291. }else {
  33292. x1 = o.p1.x - o.p2.x;
  33293. y1 = o.p1.y - o.p2.y;
  33294. }
  33295. //假设法向量的x或y固定为1或-1
  33296. if(y1 != 0){
  33297. x = 1;
  33298. y = - (x1 * x) / y1;
  33299. }else if(x1 != 0){//y如果为0,正常情况x不会是0
  33300. y = 1;
  33301. x = - (y1 * y) / x1;
  33302. }else {
  33303. console.log("两个点一样");
  33304. return null;
  33305. }
  33306. //判断方向里或者外:
  33307. var vNormal = new Vector3(x, 0, y);
  33308. var vLine = new Vector3(x1, 0, y1);
  33309. var vDir = vNormal.cross(vLine);
  33310. if(vDir.y>0){
  33311. x *= -1;
  33312. y *= -1;
  33313. }
  33314. return new Vector2(x, y).normalize();
  33315. },
  33316. getQuaBetween2Vector:function(oriVec, newVec, upVec){ //获取从oriVec旋转到newVec可以应用的quaternion
  33317. var angle = oriVec.angleTo(newVec);
  33318. var axis = oriVec.clone().cross( newVec).normalize();//两个up之间
  33319. if(axis.length() == 0){//当夹角为180 或 0 度时,得到的axis为(0,0,0),故使用备用的指定upVec
  33320. return new Quaternion().setFromAxisAngle( upVec, angle );
  33321. }
  33322. return new Quaternion().setFromAxisAngle( axis, angle );
  33323. } ,
  33324. /*
  33325. getQuaBetween2Vector2 : function(oriVec, newVec ){//not camera
  33326. var _ = (new THREE.Matrix4).lookAt( oriVec, new THREE.Vector3, new THREE.Vector3(0,1,0))
  33327. var aimQua = (new THREE.Quaternion).setFromRotationMatrix(_)
  33328. var _2 = (new THREE.Matrix4).lookAt( newVec, new THREE.Vector3, new THREE.Vector3(0,1,0))
  33329. var aimQua2 = (new THREE.Quaternion).setFromRotationMatrix(_2)
  33330. return aimQua2.multiply(aimQua.clone().inverse())
  33331. } */
  33332. getQuaByAim: function (aim, center=new Vector3) {
  33333. let forward = new Vector3(0, 1, 0);
  33334. let qua1 = new Quaternion().setFromUnitVectors(forward, aim.clone().sub(center).normalize());
  33335. /* var _ = (new THREE.Matrix4).lookAt(center,aim, new THREE.Vector3(0,1,0));
  33336. let qua2 = (new THREE.Quaternion).setFromRotationMatrix(_);
  33337. let rot1 = new THREE.Euler().setFromQuaternion(qua1)
  33338. let rot2 = new THREE.Euler().setFromQuaternion(qua2) //奇怪,qua2怎么都不对
  33339. console.log(rot1,rot2) */
  33340. return qua1
  33341. },
  33342. getAimByQua: function (quaternion, center=new Vector3) {
  33343. return new Vector3(0, 0, -1).applyQuaternion(quaternion).add(center)
  33344. },
  33345. getScaleForConstantSize : function(){ //获得规定二维大小的mesh的scale值。可以避免因camera的projection造成的mesh视觉大小改变。 来源:tag.updateDisc
  33346. var w;
  33347. var i = new Vector3, o = new Vector3, l = new Vector3, c = new Vector3, h = new Vector3;
  33348. return function(op={}){
  33349. if(op.width2d) w = op.width2d; //如果恒定二维宽度
  33350. else {//否则考虑上距离,加一丢丢近大远小的效果
  33351. var currentDis, nearBound, farBound;
  33352. if(op.camera.type == "OrthographicCamera"){
  33353. currentDis = 200 / op.camera.zoom; //(op.camera.right - op.camera.left) / op.camera.zoom
  33354. }else {
  33355. currentDis = op.position.distanceTo(op.camera.position);
  33356. }
  33357. w = op.maxSize - ( op.maxSize - op.minSize) * MathUtils$1.smoothstep(currentDis, op.nearBound, op.farBound);
  33358. //maxSize : mesh要表现的最大像素宽度; nearBound: 最近距离,若比nearBound近,则使用maxSize
  33359. }
  33360. i.copy(op.position).project(op.camera); //tag中心在屏幕上的二维坐标
  33361. o.set(op.resolution.x / 2, op.resolution.y / 2, 1).multiply(i); //转化成px -w/2 到 w/2的范围
  33362. l.set(w / 2, 0, 0).add(o); //加上tag宽度的一半
  33363. c.set(2 / op.resolution.x, 2 / op.resolution.y, 1).multiply(l); //再转回 -1 到 1的范围
  33364. h.copy(c).unproject(op.camera);//再转成三维坐标,求得tag边缘的位置
  33365. var g = h.distanceTo(op.position);//就能得到tag的三维半径
  33366. //这里使用的都是resolution2, 好处是手机端不会太小, 坏处是pc更改网页显示百分比时显示的大小会变(或许可以自己算出设备真实的deviceRatio, 因window.screen是不会改变的),但考虑到用户可以自行调节字大小也许是好的
  33367. return g //可能NAN 当相机和position重叠时
  33368. }
  33369. }()
  33370. ,
  33371. //W , H, left, top分别是rect的宽、高、左、上
  33372. getCrossPointAtRect : function(p1, aim, W , H, left, top){//求射线p1-aim在rect边界上的交点,其中aim在rect范围内,p1则不一定(交点在aim这边的延长线上)
  33373. var x,y, borderX;
  33374. var r = (aim.x - p1.x) / (aim.y - p1.y);//根据相似三角形原理先求出这个比值
  33375. var getX = function(y){
  33376. return r * (y-p1.y) + p1.x;
  33377. };
  33378. var getY = function(x){
  33379. return 1/r * (x-p1.x) + p1.y;
  33380. };
  33381. if(aim.x >= p1.x){
  33382. borderX = W+left;
  33383. }else {
  33384. borderX = left;
  33385. }
  33386. x = borderX;
  33387. y = getY(x);
  33388. if(y < top || y > top+H){
  33389. if(y < top){
  33390. y = top;
  33391. }else {
  33392. y = top+H;
  33393. }
  33394. x = getX(y);
  33395. }
  33396. return new Vector2(x, y);
  33397. },
  33398. getDirFromUV : function(uv){ //获取dir 反向计算 - - 二维转三维比较麻烦
  33399. var dirB; //所求 单位向量
  33400. var y = Math.cos(uv.y * Math.PI); //uv中纵向可以直接确定y, 根据上面getUVfromDir的反向计算
  33401. // 故 uv.y * Math.PI 就是到垂直线(向上)的夹角
  33402. var angle = 2 * Math.PI * uv.x - Math.PI; //x/z代表的是角度
  33403. var axisX, axisZ; //axis为1代表是正,-1是负数
  33404. if (-Math.PI <= angle && angle < 0) {
  33405. axisX = -1; //下半圆
  33406. } else {
  33407. axisX = 1; //上半圆
  33408. }
  33409. if (-Math.PI / 2 <= angle && angle < Math.PI / 2) {
  33410. axisZ = 1; //右半圆
  33411. } else {
  33412. axisZ = -1; //左半圆
  33413. }
  33414. var XDivideZ = Math.tan(angle);
  33415. var z = Math.sqrt((1 - y * y) / (1 + XDivideZ * XDivideZ));
  33416. var x = XDivideZ * z;
  33417. if (z * axisZ < 0) { //异号
  33418. z *= -1;
  33419. x *= -1;
  33420. if (x * axisX < 0) {
  33421. // console.log("wrong!!!!!??????????")
  33422. }
  33423. }
  33424. x *= -1; //计算完成后这里不能漏掉 *= -1
  33425. dirB = this.convertVector.YupToZup(new Vector3(x, y, z));
  33426. //理想状态下x和z和anotherDir相同
  33427. return dirB
  33428. },
  33429. getUVfromDir : function(dir) { //获取UV 同shader里的计算
  33430. var dir = this.convertVector.ZupToYup(dir);
  33431. dir.x *= -1; //计算前这里不能漏掉 *= -1 见shader
  33432. var tx = Math.atan2(dir.x, dir.z) / (Math.PI * 2.0) + 0.5; //atan2(y,x) 返回从 X 轴正向逆时针旋转到点 (x,y) 时经过的角度。区间是-PI 到 PI 之间的值
  33433. var ty = Math.acos(dir.y) / Math.PI;
  33434. return new Vector2(tx, ty)
  33435. //理想状态下tx相同
  33436. },
  33437. getDirByLonLat : function(lon,lat){
  33438. var dir = new Vector3;
  33439. var phi = MathUtils$1.degToRad(90 - lat);
  33440. var theta = MathUtils$1.degToRad(lon);
  33441. dir.x = Math.sin(phi) * Math.cos(theta);
  33442. dir.y = Math.cos(phi);
  33443. dir.z = Math.sin(phi) * Math.sin(theta);
  33444. return dir
  33445. } //0,0 => (1,0,0) 270=>(0,0,-1)
  33446. ,
  33447. projectPointAtPlane:function(o={}){//获取一个点在一个面上的投影 {facePoints:[a,b,c], point:}
  33448. var plane = new Plane().setFromCoplanarPoints(...o.facePoints);
  33449. return plane.projectPoint(o.point, new Vector3() )
  33450. }
  33451. ,
  33452. getPolygonsMixedRings:function( polygons, onlyGetOutRing){//{points:[vector2,...],holes:[[],[]]}
  33453. let points = [];
  33454. let lines = [];
  33455. let i = 0;
  33456. polygons.forEach(e=> points.push(...e.map(a=>new Vector2().copy(a) )) );
  33457. polygons.forEach((ps,j)=>{
  33458. let length = ps.length;
  33459. let index = 0;
  33460. while(index<length){
  33461. lines.push({p1:index+i,p2:(index+1)%length+i});
  33462. index ++;
  33463. }
  33464. i+=length;
  33465. });
  33466. points.forEach((p,j)=>{p.id = j;});
  33467. let rings = searchRings({
  33468. points,
  33469. lines,
  33470. onlyGetOutRing
  33471. });
  33472. //console.log(rings)
  33473. rings = rings.filter(e=>e.closetParent == void 0);// 子环不加,被外环包含了
  33474. return rings
  33475. },
  33476. getQuaFromPosAim( position, target ){
  33477. /* let matrix = (new THREE.Matrix4).lookAt(position, target, new THREE.Vector3(0,0,1)) //这里垂直的话会默认给一个右向所以不这么写
  33478. return (new THREE.Quaternion).setFromRotationMatrix(matrix) */
  33479. let view = new ExtendView();
  33480. view.direction = new Vector3().subVectors(target,position);
  33481. return view.quaternion
  33482. },
  33483. getBoundByPoints(points, minSize){
  33484. var bound = new Box3;
  33485. points.forEach(point=>{
  33486. bound.expandByPoint(point);
  33487. });
  33488. let center = bound.getCenter(new Vector3);
  33489. if(minSize){
  33490. let minBound = (new Box3()).setFromCenterAndSize(center, minSize);
  33491. bound.union(minBound);
  33492. }
  33493. return {
  33494. bounding:bound,
  33495. size: bound.getSize(new Vector3),
  33496. center,
  33497. }
  33498. },
  33499. linearClamp(value, x1,x2, y1, y2){//x为bound.min, bound.max
  33500. value = MathUtils$1.clamp(value, x1,x2);
  33501. return y1 + ( y2 - y1) * (value - x1) / (x2 - x1)
  33502. },
  33503. getStandardYaw(yaw1, yaw2) {
  33504. //使yaw1过渡到yaw2时朝角度差小的那边走。如果差距大于半个圆,就要反个方向转(把大的那个数字减去360度)
  33505. if (Math.abs(yaw1 - yaw2) > Math.PI) {
  33506. yaw1 > yaw2 ? (yaw1 -= Math.PI * 2) : (yaw2 -= Math.PI * 2);
  33507. }
  33508. return [yaw1, yaw2]
  33509. },
  33510. };
  33511. Potree.math = math;
  33512. function mobileVersion(e, t) {
  33513. //ios的版本
  33514. var i = window.navigator.userAgent,
  33515. n = i.match(e);
  33516. return (
  33517. (n = n ? n[1].split(t) : []),
  33518. {
  33519. major: parseInt(n[0]) || 0,
  33520. minor: parseInt(n[1]) || 0,
  33521. patch: parseInt(n[2]) || 0,
  33522. }
  33523. )
  33524. }
  33525. var browser = {
  33526. isFullscreen: function() {
  33527. return (
  33528. document.fullscreenElement ||
  33529. document.mozFullscreenElement ||
  33530. document.mozFullScreenElement ||
  33531. document.webkitFullscreenElement ||
  33532. document.msFullscreenElement
  33533. )
  33534. },
  33535. supportsFullscreen: function() {
  33536. return (
  33537. document.fullscreenEnabled ||
  33538. document.mozFullscreenEnabled ||
  33539. document.mozFullScreenEnabled ||
  33540. document.webkitFullscreenEnabled ||
  33541. document.msFullscreenEnabled
  33542. )
  33543. },
  33544. isPointerLocked: function() {
  33545. return (
  33546. document.pointerLockElement ||
  33547. document.mozPointerLockElement ||
  33548. document.webkitPointerLockElement
  33549. )
  33550. },
  33551. requestFullscreen: function(dom, t) {
  33552. dom.requestFullscreen ?
  33553. dom.requestFullscreen() :
  33554. dom.mozRequestFullScreen ?
  33555. dom.mozRequestFullScreen() :
  33556. dom.webkitRequestFullscreen ?
  33557. dom.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT) :
  33558. dom.msRequestFullscreen && dom.msRequestFullscreen(),
  33559. t &&
  33560. $(document).on(
  33561. "fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange",
  33562. browser.requestPointerLock
  33563. );
  33564. },
  33565. requestPointerLock: function() {
  33566. var e;
  33567. if (document.fullscreenElement) e = document.fullscreenElement();
  33568. else if (document.mozFullscreenElement) e = document.mozFullscreenElement();
  33569. else if (document.mozFullScreenElement) e = document.mozFullScreenElement();
  33570. else {
  33571. if (!document.webkitFullscreenElement) return
  33572. e = document.webkitFullscreenElement();
  33573. };
  33574. (e.requestPointerLock =
  33575. e.requestPointerLock || e.mozRequestPointerLock || e.webkitRequestPointerLock),
  33576. e.requestPointerLock(),
  33577. $(document).off(
  33578. "fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange",
  33579. this
  33580. );
  33581. },
  33582. exitPointerLock: function() {
  33583. ;
  33584. (document.exitPointerLock =
  33585. document.exitPointerLock ||
  33586. document.mozExitPointerLock ||
  33587. document.webkitExitPointerLock),
  33588. document.exitPointerLock();
  33589. },
  33590. exitFullscreen: function() {
  33591. document.exitFullscreen ?
  33592. document.exitFullscreen() :
  33593. document.msExitFullscreen ?
  33594. document.msExitFullscreen() :
  33595. document.mozCancelFullScreen ?
  33596. document.mozCancelFullScreen() :
  33597. document.webkitExitFullscreen && document.webkitExitFullscreen();
  33598. },
  33599. details: function() {
  33600. var e = navigator.userAgent.match("(Firefox|Chrome|Safari)/([\\d]+)");
  33601. return e ?
  33602. {
  33603. name: e[1],
  33604. version: parseInt(e[2]),
  33605. platform: navigator.platform,
  33606. } : {}
  33607. },
  33608. is: function(e) {
  33609. return this.details() && this.details().name === e
  33610. },
  33611. inIframe: function() {
  33612. return window.parent !== window
  33613. },
  33614. aspectRatio: function($elem) {
  33615. $elem = $elem || $("#player");
  33616. var e = $elem.width() / $elem.height();
  33617. return isFinite(e) ? e : 0
  33618. },
  33619. userAgent: function() {
  33620. return window.navigator.userAgent
  33621. },
  33622. isMobile: function() {
  33623. var e = navigator.userAgent || navigator.vendor || window.opera;
  33624. return (
  33625. /(android|bb\d+|meego).+mobile|android|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
  33626. e
  33627. ) ||
  33628. /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
  33629. e.substr(0, 4)
  33630. )
  33631. )
  33632. },
  33633. isLandscape: function() {
  33634. return this.isMobile && this.aspectRatio() > 1
  33635. },
  33636. isSmallScreen: function() {
  33637. var e = screen.width / window.devicePixelRatio;
  33638. return e < 240
  33639. },
  33640. detectIE: function() {
  33641. var e = window.navigator.userAgent,
  33642. t = e.indexOf("MSIE ");
  33643. return t !== -1 || !!navigator.userAgent.match(/Trident.*rv\:11\./)
  33644. },
  33645. detectSafari: function() {
  33646. var e = window.navigator.userAgent,
  33647. t = e.indexOf("Safari");
  33648. return t !== -1 && !this.detectOpera() && !this.detectChrome() //xzw add detectOpera
  33649. },
  33650. detectFirefox: function() {
  33651. var e = window.navigator.userAgent;
  33652. return e.indexOf("Firefox") !== -1
  33653. },
  33654. detectChrome: function() {
  33655. var e = window.navigator.userAgent;
  33656. return e.indexOf("Chrome") !== -1 && !this.detectOpera()
  33657. },
  33658. detectOpera: function() {
  33659. var e = window.navigator.userAgent;
  33660. return e.indexOf("OPR") !== -1
  33661. },
  33662. detectIOS: function() {
  33663. return this.detectIPhone() || this.detectIPad() || this.detectIPod()
  33664. },
  33665. detectIPad: function() {
  33666. var e = window.navigator.userAgent,
  33667. t = /iPad/;
  33668. return t.test(e)
  33669. },
  33670. detectIPod: function() {
  33671. var e = window.navigator.userAgent,
  33672. t = /iPod/;
  33673. return t.test(e)
  33674. },
  33675. detectIPhone: function() {
  33676. var e = window.navigator.userAgent,
  33677. t = /iPhone/;
  33678. return t.test(e)
  33679. },
  33680. detectAndroid: function() {
  33681. var e = window.navigator.userAgent;
  33682. return e.indexOf("Android") !== -1
  33683. },
  33684. detectAndroidMobile: function() {
  33685. var e = window.navigator.userAgent;
  33686. return this.detectAndroid() && e.indexOf("Mobile") !== -1
  33687. },
  33688. detectSamsungNative: function() {
  33689. var e = window.navigator.userAgent;
  33690. return (
  33691. e.indexOf("SM-G900H") !== -1 ||
  33692. e.indexOf("GT-I9500") !== -1 ||
  33693. e.indexOf("SM-N900") !== -1
  33694. )
  33695. },
  33696. detectSamsungS6: function() {
  33697. var e = window.navigator.userAgent;
  33698. return e.indexOf("SM-G92") !== -1
  33699. },
  33700. /************************************************************徐世廷*************************************************************/
  33701. detectHUAWEI5X: function() {
  33702. return -1 !== window.navigator.userAgent.indexOf("KIW-TL00H")
  33703. },
  33704. /*******************************************************************************************************************************/
  33705. detectWebVR: function() {
  33706. return !(!window.navigator.getVRDisplays || !window.VRDisplay)
  33707. },
  33708. getVRDisplay: function() {
  33709. var e = $.Deferred();
  33710. return this.detectWebVR() ?
  33711. (navigator.getVRDisplays().then(function(t) {
  33712. t.length >= 1 && e.resolve(t[0]), e.reject(null);
  33713. }),
  33714. e) :
  33715. e.reject(null)
  33716. },
  33717. iosVersion: function() {
  33718. if (!this.detectIOS()) throw new DeviceMismatchException("Did not detect an iDevice")
  33719. var e = /((?:\d+\_?){1,3}) like Mac OS/,
  33720. t = "_";
  33721. return mobileVersion(e, t)
  33722. },
  33723. androidVersion: function() {
  33724. if (!this.detectAndroid())
  33725. throw new DeviceMismatchException("Did not detect an Android based device")
  33726. var e = /Android ((?:\d+\.?){1,3})/,
  33727. t = ".";
  33728. return mobileVersion(e, t)
  33729. },
  33730. valueFromCookie: function(e, t) {
  33731. var i = new RegExp(e + "=([0-9a-f]+)(; ?|$)").exec(document.cookie);
  33732. if (!i) return t
  33733. var n = i[1];
  33734. return "boolean" == typeof t ?
  33735. "true" === n || "1" === n :
  33736. "number" == typeof t ?
  33737. parseFloat(n) :
  33738. n
  33739. },
  33740. valueFromHash: function(e, t) {
  33741. var i = new RegExp("[#&?]" + e + "=([^#&?]*)"),
  33742. n = i.exec(window.location.href);
  33743. if (!n) return t
  33744. var r = n[1];
  33745. return "boolean" == typeof t ?
  33746. "true" === r || "1" === r :
  33747. "number" == typeof t ?
  33748. parseFloat(r) :
  33749. window.decodeURIComponent(r)
  33750. },
  33751. //-------许钟文:-------------------------------------------------
  33752. getProjectNum: function() {
  33753. //获取场景projectNum
  33754. if (window.__ProjectNum && window.__ProjectNum != "__ProjectNum__") {
  33755. return window.__ProjectNum
  33756. }
  33757. var number = window.location.href.substring(window.location.href.indexOf("=") + 1);
  33758. if (number.indexOf("&") != -1) {
  33759. number = number.substring(0, number.indexOf("&"));
  33760. }
  33761. if (number.indexOf("#") != -1) {
  33762. number = number.substring(0, number.indexOf("#"));
  33763. }
  33764. return number
  33765. },
  33766. urlHasValue: function(key, isGetValue) {
  33767. // debugger
  33768. // if (getValue) { //得到类似n=1 的 1
  33769. // var b = window.location.href.substring(window.location.href.indexOf("?") + 1);
  33770. // var a = b.indexOf('&' + t + "=");
  33771. // if (a > -1) {
  33772. // var s = b.substring(a + ('&' + t + "=").length);
  33773. // s.indexOf("&") > -1 && (s = s.substring(0, s.indexOf("&")));
  33774. // s.indexOf("#") > -1 && (s = s.substring(0, s.indexOf("#")));
  33775. // return s;
  33776. // } else return false;
  33777. // } else return window.location.search.match("&" + t + "|\\?" + t) != null; //window.location.href.substring(window.location.href.indexOf("?") + 1).indexOf('&' + t) > -1;
  33778. //const value = window.location.search.match("&" + t + "|\\?" + t)
  33779. if (key === "m" && window.__ProjectNum && window.__ProjectNum != "__ProjectNum__") {
  33780. return window.__ProjectNum
  33781. }
  33782. let querys = window.location.search.substr(1).split("&");
  33783. if (isGetValue) {
  33784. for (let i = 0; i < querys.length; i++) {
  33785. let keypair = querys[i].split("=");
  33786. if (keypair.length === 2 && keypair[0] === key) {
  33787. return keypair[1]
  33788. }
  33789. }
  33790. return ""
  33791. } else {
  33792. //return window.location.search.match("&" + key + "|\\?" + key) != null 有bug
  33793. for (let i = 0; i < querys.length; i++) {
  33794. let keypair = querys[i].split("=");
  33795. if (keypair[0] == key) {
  33796. return true
  33797. }
  33798. }
  33799. return false
  33800. }
  33801. },
  33802. /**
  33803. * 获取查询参数的值
  33804. * @param {String} key
  33805. * @returns String
  33806. */
  33807. urlQueryValue(key) {
  33808. return this.urlHasValue(key, true) || ""
  33809. },
  33810. /**
  33811. * 获取hash参数的值
  33812. * @param {String} key
  33813. * @returns String
  33814. */
  33815. urlHashValue(key) {
  33816. let querys = window.location.hash.substr(1).replace('/?', '').split("&");
  33817. for (let i = 0; i < querys.length; i++) {
  33818. let keypair = querys[i].split("=");
  33819. if (keypair.length === 2 && keypair[0] === key) {
  33820. return keypair[1]
  33821. }
  33822. }
  33823. return ""
  33824. },
  33825. /**
  33826. * 判断是否存在hash
  33827. * @param {String} key
  33828. * @returns Boolean
  33829. */
  33830. urlIsHasHash(key) {
  33831. let querys = window.location.hash.substr(1).replace('/?', '').split("&");
  33832. return querys.includes(key)
  33833. },
  33834. islongPhone: function() {
  33835. //是否是刘海全面屏幕 仅仅根据比例判断 - -
  33836. //screen.height == 812 && screen.width == 375)
  33837. var r = screen.height / screen.width; //可能横屏
  33838. return this.isMobile() && (r > 1.99 || r < 0.502512) //18/9=2.165 //???
  33839. },
  33840. detectWeixin: function() {
  33841. //微信 包括PC的微信
  33842. return window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == "micromessenger"
  33843. },
  33844. detectWeixinMiniProgram: function() {
  33845. return window.navigator.userAgent.match("miniProgram")
  33846. },
  33847. detectEdge: function() {
  33848. return window.navigator.userAgent.indexOf("Edge") > -1
  33849. },
  33850. detectApp: function() {
  33851. return this.urlHasValue("app")
  33852. },
  33853. /**
  33854. * 判断标签页是否切换状态
  33855. */
  33856. isTabHidden: function() {
  33857. var prefixes = ["webkit", "moz", "ms", "o"];
  33858. if ("hidden" in document) return document.hidden
  33859. for (var i = 0; i < prefixes.length; i++) {
  33860. if (prefixes[i] + "Hidden" in document) return document[prefixes[i] + "Hidden"]
  33861. }
  33862. return false
  33863. },
  33864. };
  33865. WebGLRenderer.prototype.paramThreeToGL = function(e) {
  33866. var t, i = this.extensions, r = this.getContext();//context;
  33867. if (e === RepeatWrapping)
  33868. return r.REPEAT;
  33869. if (e === ClampToEdgeWrapping)
  33870. return r.CLAMP_TO_EDGE;
  33871. if (e === MirroredRepeatWrapping)
  33872. return r.MIRRORED_REPEAT;
  33873. if (e === NearestFilter)
  33874. return r.NEAREST;
  33875. if (e === NearestMipMapNearestFilter)
  33876. return r.NEAREST_MIPMAP_NEAREST;
  33877. if (e === NearestMipMapLinearFilter)
  33878. return r.NEAREST_MIPMAP_LINEAR;
  33879. if (e === LinearFilter)
  33880. return r.LINEAR;
  33881. if (e === LinearMipMapNearestFilter)
  33882. return r.LINEAR_MIPMAP_NEAREST;
  33883. if (e === LinearMipMapLinearFilter)
  33884. return r.LINEAR_MIPMAP_LINEAR;
  33885. if (e === UnsignedByteType)
  33886. return r.UNSIGNED_BYTE;
  33887. if (e === UnsignedShort4444Type)
  33888. return r.UNSIGNED_SHORT_4_4_4_4;
  33889. if (e === UnsignedShort5551Type)
  33890. return r.UNSIGNED_SHORT_5_5_5_1;
  33891. if (e === UnsignedShort565Type)
  33892. return r.UNSIGNED_SHORT_5_6_5;
  33893. if (e === ByteType)
  33894. return r.BYTE;
  33895. if (e === ShortType)
  33896. return r.SHORT;
  33897. if (e === UnsignedShortType)
  33898. return r.UNSIGNED_SHORT;
  33899. if (e === IntType)
  33900. return r.INT;
  33901. if (e === UnsignedIntType)
  33902. return r.UNSIGNED_INT;
  33903. if (e === FloatType)
  33904. return r.FLOAT;
  33905. if (t = i.get("OES_texture_half_float"),
  33906. null !== t && e === HalfFloatType)
  33907. return t.HALF_FLOAT_OES;
  33908. if (e === AlphaFormat)
  33909. return r.ALPHA;
  33910. if (e === RGBFormat)
  33911. return r.RGB;
  33912. if (e === RGBAFormat)
  33913. return r.RGBA;
  33914. if (e === LuminanceFormat)
  33915. return r.LUMINANCE;
  33916. if (e === LuminanceAlphaFormat)
  33917. return r.LUMINANCE_ALPHA;
  33918. if (e === AddEquation)
  33919. return r.FUNC_ADD;
  33920. if (e === SubtractEquation)
  33921. return r.FUNC_SUBTRACT;
  33922. if (e === ReverseSubtractEquation)
  33923. return r.FUNC_REVERSE_SUBTRACT;
  33924. if (e === ZeroFactor)
  33925. return r.ZERO;
  33926. if (e === OneFactor)
  33927. return r.ONE;
  33928. if (e === SrcColorFactor)
  33929. return r.SRC_COLOR;
  33930. if (e === OneMinusSrcColorFactor)
  33931. return r.ONE_MINUS_SRC_COLOR;
  33932. if (e === SrcAlphaFactor)
  33933. return r.SRC_ALPHA;
  33934. if (e === OneMinusSrcAlphaFactor)
  33935. return r.ONE_MINUS_SRC_ALPHA;
  33936. if (e === DstAlphaFactor)
  33937. return r.DST_ALPHA;
  33938. if (e === OneMinusDstAlphaFactor)
  33939. return r.ONE_MINUS_DST_ALPHA;
  33940. if (e === DstColorFactor)
  33941. return r.DST_COLOR;
  33942. if (e === OneMinusDstColorFactor)
  33943. return r.ONE_MINUS_DST_COLOR;
  33944. if (e === SrcAlphaSaturateFactor)
  33945. return r.SRC_ALPHA_SATURATE;
  33946. if (t = i.get("WEBGL_compressed_texture_s3tc"),
  33947. null !== t) {
  33948. if (e === RGB_S3TC_DXT1_Format)
  33949. return t.COMPRESSED_RGB_S3TC_DXT1_EXT;
  33950. if (e === RGBA_S3TC_DXT1_Format$1)
  33951. return t.COMPRESSED_RGBA_S3TC_DXT1_EXT;
  33952. if (e === RGBA_S3TC_DXT3_Format)
  33953. return t.COMPRESSED_RGBA_S3TC_DXT3_EXT;
  33954. if (e === RGBA_S3TC_DXT5_Format$1)
  33955. return t.COMPRESSED_RGBA_S3TC_DXT5_EXT
  33956. }
  33957. if (t = i.get("WEBGL_compressed_texture_pvrtc"),
  33958. null !== t) {
  33959. if (e === RGB_PVRTC_4BPPV1_Format)
  33960. return t.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  33961. if (e === RGB_PVRTC_2BPPV1_Format)
  33962. return t.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  33963. if (e === RGBA_PVRTC_4BPPV1_Format)
  33964. return t.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  33965. if (e === RGBA_PVRTC_2BPPV1_Format)
  33966. return t.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
  33967. }
  33968. if (t = i.get("WEBGL_compressed_texture_etc1"),
  33969. null !== t && e === RGB_ETC1_Format)
  33970. return t.COMPRESSED_RGB_ETC1_WEBGL;
  33971. if (t = i.get("EXT_blend_minmax"),
  33972. null !== t) {
  33973. if (e === MinEquation)
  33974. return t.MIN_EXT;
  33975. if (e === MaxEquation)
  33976. return t.MAX_EXT
  33977. }
  33978. return 0
  33979. };
  33980. EventDispatcher.prototype.addEventListener = function(type, listener, {importance=0, once}={}){ //add importance
  33981. if ( this._listeners === undefined ) this._listeners = {};
  33982. const listeners = this._listeners;
  33983. if ( listeners[ type ] === undefined ) {
  33984. listeners[ type ] = [];
  33985. }
  33986. if(type == 'flyingDone'){
  33987. console.log('addEventListener flyingDone');
  33988. }
  33989. if ( !listeners[ type ].some(e=>e.listener == listener ) ) {
  33990. listeners[type].push({ listener, importance, once});
  33991. listeners[type] = listeners[type].sort((e,a)=> a.importance - e.importance);//add
  33992. }
  33993. };
  33994. EventDispatcher.prototype.hasEventListener = function(type, listener){
  33995. if ( this._listeners === undefined ) return false;
  33996. const listeners = this._listeners;
  33997. return listeners[ type ] !== undefined && listeners[ type ].some(e=>e.listener == listener )
  33998. };
  33999. EventDispatcher.prototype.removeEventListener = function(type, listener){
  34000. if ( this._listeners === undefined ) return;
  34001. const listeners = this._listeners;
  34002. const listenerArray = listeners[ type ];
  34003. if ( listenerArray !== undefined ) {
  34004. /* const index = listenerArray.indexOf( listener );
  34005. if ( index !== - 1 ) {
  34006. listenerArray.splice( index, 1 );
  34007. } */
  34008. let item = listenerArray.find(e=>e.listener == listener);
  34009. item && listenerArray.splice(listenerArray.indexOf(item), 1);
  34010. }
  34011. };
  34012. EventDispatcher.prototype.removeEventListeners = function(type){ //add
  34013. if(this._listeners && this._listeners[type] !== undefined){
  34014. delete this._listeners[type];
  34015. }
  34016. };
  34017. EventDispatcher.prototype.removeAllListeners = function(){ //add
  34018. this._listeners = {};
  34019. };
  34020. EventDispatcher.prototype.dispatchEvent = function(event){
  34021. if(typeof event == 'string'){//add
  34022. event = {type:event};
  34023. }
  34024. if ( this._listeners === undefined ) return;
  34025. let type = event.type;
  34026. const listeners = this._listeners;
  34027. const listenerArray = listeners[type ];
  34028. if ( listenerArray !== undefined ) {
  34029. event.target = this;
  34030. // Make a copy, in case listeners are removed while iterating.
  34031. for(let {listener, once} of listenerArray.slice(0)){
  34032. if(once){
  34033. this.removeEventListener(type,listener);
  34034. }
  34035. let result = listener.call(this, event); //add stopContinue
  34036. if(result && result.stopContinue){
  34037. break
  34038. }
  34039. }
  34040. }
  34041. };
  34042. EventDispatcher.prototype.traverse = function(callback){
  34043. let result = callback( this );
  34044. if(result && result.stopContinue){//xzw add
  34045. return
  34046. }
  34047. const children = this.children;
  34048. if(children){
  34049. for ( let i = 0, l = children.length; i < l; i ++ ) {
  34050. children[ i ].traverse( callback );
  34051. }
  34052. }
  34053. };
  34054. Object3D.prototype.traverse = function ( callback ) {
  34055. let result = callback( this );
  34056. if(result && result.stopContinue){//xzw add
  34057. return
  34058. }
  34059. const children = this.children;
  34060. for ( let i = 0, l = children.length; i < l; i ++ ) {
  34061. children[ i ] && children[ i ].traverse( callback );
  34062. }
  34063. };
  34064. Material.prototype.setValues = function ( values ) {
  34065. if ( values === undefined ) return;
  34066. for ( const key in values ) {
  34067. const newValue = values[ key ];
  34068. if ( newValue === undefined ) {
  34069. console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
  34070. continue;
  34071. }
  34072. // for backward compatability if shading is set in the constructor
  34073. if ( key === 'shading' ) {
  34074. console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
  34075. this.flatShading = ( newValue === FlatShading ) ? true : false;
  34076. continue;
  34077. }
  34078. const currentValue = this[ key ];
  34079. /* if ( currentValue === undefined ) { //-----主要删了这段,否则很难和 set 一起使用
  34080. //console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
  34081. continue;
  34082. } */
  34083. if ( currentValue && currentValue.isColor ) {
  34084. currentValue.set( newValue );
  34085. } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
  34086. currentValue.copy( newValue );
  34087. } else {
  34088. this[ key ] = newValue;
  34089. }
  34090. }
  34091. };
  34092. function ascSort$1( a, b ) {
  34093. return a.distance - b.distance;
  34094. }
  34095. function intersectObject$1( object, raycaster, intersects, recursive, ignoreUnvisible ) {
  34096. if(ignoreUnvisible && !object.visible)return //add
  34097. if ( object.layers.test( raycaster.layers ) ) {
  34098. object.raycast( raycaster, intersects );
  34099. }
  34100. if ( recursive === true ) {
  34101. const children = object.children;
  34102. for ( let i = 0, l = children.length; i < l; i ++ ) {
  34103. intersectObject$1( children[ i ], raycaster, intersects, true, ignoreUnvisible);
  34104. }
  34105. }
  34106. }
  34107. Raycaster.prototype.intersectObject = function ( object, recursive, optionalTarget, ignoreUnvisible ) {
  34108. const intersects = optionalTarget || [];
  34109. intersectObject$1( object, this, intersects, recursive, ignoreUnvisible );
  34110. intersects.sort( ascSort$1 );
  34111. return intersects;
  34112. };
  34113. Raycaster.prototype.intersectObjects = function ( objects, recursive, optionalTarget, ignoreUnvisible ) {//add ignoreUnvisible 跳过不可见
  34114. const intersects = optionalTarget || [];
  34115. if ( Array.isArray( objects ) === false ) {
  34116. console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
  34117. return intersects;
  34118. }
  34119. for ( let i = 0, l = objects.length; i < l; i ++ ) {
  34120. intersectObject$1( objects[ i ], this, intersects, recursive, ignoreUnvisible );
  34121. }
  34122. intersects.sort( ascSort$1 );
  34123. return intersects;
  34124. };
  34125. Object3D.prototype.realVisible = function(){
  34126. let v = true;
  34127. let parent = this;
  34128. let lastParent;
  34129. while(parent){
  34130. if(parent.visible === false){
  34131. v = false;
  34132. break;
  34133. }
  34134. lastParent = parent;
  34135. parent = parent.parent;
  34136. }
  34137. if(v && !(lastParent instanceof Scene)){//已被删除
  34138. v = false;
  34139. }
  34140. return v
  34141. };
  34142. var MathLight = {};
  34143. MathLight.RADIANS_PER_DEGREE = Math.PI / 180;
  34144. MathLight.DEGREES_PER_RADIAN = 180 / Math.PI;
  34145. MathLight.Vector3 = function(e, t, i) {
  34146. this.x = e || 0,
  34147. this.y = t || 0,
  34148. this.z = i || 0;
  34149. };
  34150. MathLight.Matrix4 = function() {
  34151. this.elements = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
  34152. arguments.length > 0 && console.error("MathLight.Matrix4: the constructor no longer reads arguments. use .set() instead.");
  34153. };
  34154. MathLight.Matrix4.prototype = {
  34155. identity: function() {
  34156. return this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1),
  34157. this
  34158. },
  34159. copy: function(e) {
  34160. return this.elements.set(e.elements),
  34161. this
  34162. },
  34163. applyToVector3: function(e) {
  34164. var t = e.x
  34165. , i = e.y
  34166. , n = e.z
  34167. , r = this.elements;
  34168. return e.x = r[0] * t + r[4] * i + r[8] * n + r[12],
  34169. e.y = r[1] * t + r[5] * i + r[9] * n + r[13],
  34170. e.z = r[2] * t + r[6] * i + r[10] * n + r[14],
  34171. this
  34172. },
  34173. getInverse: function(e, t) {
  34174. var i = this.elements
  34175. , n = e.elements
  34176. , r = n[0]
  34177. , o = n[1]
  34178. , a = n[2]
  34179. , s = n[3]
  34180. , l = n[4]
  34181. , c = n[5]
  34182. , h = n[6]
  34183. , u = n[7]
  34184. , d = n[8]
  34185. , p = n[9]
  34186. , f = n[10]
  34187. , g = n[11]
  34188. , m = n[12]
  34189. , v = n[13]
  34190. , A = n[14]
  34191. , y = n[15]
  34192. , C = p * A * u - v * f * u + v * h * g - c * A * g - p * h * y + c * f * y
  34193. , I = m * f * u - d * A * u - m * h * g + l * A * g + d * h * y - l * f * y
  34194. , E = d * v * u - m * p * u + m * c * g - l * v * g - d * c * y + l * p * y
  34195. , b = m * p * h - d * v * h - m * c * f + l * v * f + d * c * A - l * p * A
  34196. , w = r * C + o * I + a * E + s * b;
  34197. if (0 === w) {
  34198. var _ = "MathLight.Matrix4.getInverse(): can't invert matrix, determinant is 0";
  34199. if (t)
  34200. throw new Error(_);
  34201. return console.warn(_),
  34202. this.identity()
  34203. }
  34204. var T = 1 / w;
  34205. return i[0] = C * T,
  34206. i[1] = (v * f * s - p * A * s - v * a * g + o * A * g + p * a * y - o * f * y) * T,
  34207. i[2] = (c * A * s - v * h * s + v * a * u - o * A * u - c * a * y + o * h * y) * T,
  34208. i[3] = (p * h * s - c * f * s - p * a * u + o * f * u + c * a * g - o * h * g) * T,
  34209. i[4] = I * T,
  34210. i[5] = (d * A * s - m * f * s + m * a * g - r * A * g - d * a * y + r * f * y) * T,
  34211. i[6] = (m * h * s - l * A * s - m * a * u + r * A * u + l * a * y - r * h * y) * T,
  34212. i[7] = (l * f * s - d * h * s + d * a * u - r * f * u - l * a * g + r * h * g) * T,
  34213. i[8] = E * T,
  34214. i[9] = (m * p * s - d * v * s - m * o * g + r * v * g + d * o * y - r * p * y) * T,
  34215. i[10] = (l * v * s - m * c * s + m * o * u - r * v * u - l * o * y + r * c * y) * T,
  34216. i[11] = (d * c * s - l * p * s - d * o * u + r * p * u + l * o * g - r * c * g) * T,
  34217. i[12] = b * T,
  34218. i[13] = (d * v * a - m * p * a + m * o * f - r * v * f - d * o * A + r * p * A) * T,
  34219. i[14] = (m * c * a - l * v * a - m * o * h + r * v * h + l * o * A - r * c * A) * T,
  34220. i[15] = (l * p * a - d * c * a + d * o * h - r * p * h - l * o * f + r * c * f) * T,
  34221. this
  34222. },
  34223. makeRotationFromQuaternion: function(e) {
  34224. var t = this.elements
  34225. , i = e.x
  34226. , n = e.y
  34227. , r = e.z
  34228. , o = e.w
  34229. , a = i + i
  34230. , s = n + n
  34231. , l = r + r
  34232. , c = i * a
  34233. , h = i * s
  34234. , u = i * l
  34235. , d = n * s
  34236. , p = n * l
  34237. , f = r * l
  34238. , g = o * a
  34239. , m = o * s
  34240. , v = o * l;
  34241. return t[0] = 1 - (d + f),
  34242. t[4] = h - v,
  34243. t[8] = u + m,
  34244. t[1] = h + v,
  34245. t[5] = 1 - (c + f),
  34246. t[9] = p - g,
  34247. t[2] = u - m,
  34248. t[6] = p + g,
  34249. t[10] = 1 - (c + d),
  34250. t[3] = 0,
  34251. t[7] = 0,
  34252. t[11] = 0,
  34253. t[12] = 0,
  34254. t[13] = 0,
  34255. t[14] = 0,
  34256. t[15] = 1,
  34257. this
  34258. }
  34259. };
  34260. MathLight.Quaternion = function(e, t, i, n) {
  34261. this._x = e || 0,
  34262. this._y = t || 0,
  34263. this._z = i || 0,
  34264. this._w = void 0 !== n ? n : 1;
  34265. };
  34266. MathLight.Quaternion.prototype = {
  34267. get x() {
  34268. return this._x
  34269. },
  34270. set x(e) {
  34271. this._x = e;
  34272. },
  34273. get y() {
  34274. return this._y
  34275. },
  34276. set y(e) {
  34277. this._y = e;
  34278. },
  34279. get z() {
  34280. return this._z
  34281. },
  34282. set z(e) {
  34283. this._z = e;
  34284. },
  34285. get w() {
  34286. return this._w
  34287. },
  34288. set w(e) {
  34289. this._w = e;
  34290. },
  34291. copy: function(e) {
  34292. this._x = e.x,
  34293. this._y = e.y,
  34294. this._z = e.z,
  34295. this._w = e.w;
  34296. },
  34297. inverse: function() {
  34298. return this.conjugate().normalize()
  34299. },
  34300. conjugate: function() {
  34301. return this._x *= -1,
  34302. this._y *= -1,
  34303. this._z *= -1,
  34304. this
  34305. },
  34306. length: function() {
  34307. return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w)
  34308. },
  34309. normalize: function() {
  34310. var e = this.length();
  34311. return 0 === e ? (this._x = 0,
  34312. this._y = 0,
  34313. this._z = 0,
  34314. this._w = 1) : (e = 1 / e,
  34315. this._x = this._x * e,
  34316. this._y = this._y * e,
  34317. this._z = this._z * e,
  34318. this._w = this._w * e),
  34319. this
  34320. },
  34321. setFromAxisAngle: function(e, t) {
  34322. var i = t / 2
  34323. , n = Math.sin(i);
  34324. return this._x = e.x * n,
  34325. this._y = e.y * n,
  34326. this._z = e.z * n,
  34327. this._w = Math.cos(i),
  34328. this
  34329. },
  34330. setFromUnitVectors: function() {
  34331. var e, t, i = 1e-6;
  34332. return function(n, o) {
  34333. return void 0 === e && (e = new MathLight.Vector3),
  34334. t = MathLight.dot(n, o) + 1,
  34335. t < i ? (t = 0,
  34336. Math.abs(n.x) > Math.abs(n.z) ? MathLight.setVector(e, -n.y, n.x, 0) : MathLight.setVector(e, 0, -n.z, n.y)) : MathLight.cross(n, o, e),
  34337. this._x = e.x,
  34338. this._y = e.y,
  34339. this._z = e.z,
  34340. this._w = t,
  34341. this.normalize()
  34342. }
  34343. }(),
  34344. multiply: function(e) {
  34345. return this.multiplyQuaternions(this, e)
  34346. },
  34347. premultiply: function(e) {
  34348. return this.multiplyQuaternions(e, this)
  34349. },
  34350. multiplyQuaternions: function(e, t) {
  34351. var i = e._x
  34352. , n = e._y
  34353. , r = e._z
  34354. , o = e._w
  34355. , a = t._x
  34356. , s = t._y
  34357. , l = t._z
  34358. , c = t._w;
  34359. return this._x = i * c + o * a + n * l - r * s,
  34360. this._y = n * c + o * s + r * a - i * l,
  34361. this._z = r * c + o * l + i * s - n * a,
  34362. this._w = o * c - i * a - n * s - r * l,
  34363. this
  34364. }
  34365. };
  34366. MathLight.convertWorkshopVector = function(e) {
  34367. return new MathLight.Vector3(-e.x,e.y,e.z)
  34368. };
  34369. MathLight.convertWorkshopQuaternion = function(e) {
  34370. return new MathLight.Quaternion(-e.x,e.y,e.z,-e.w).multiply(new MathLight.Quaternion(Math.sqrt(2) / 2,Math.sqrt(2) / 2,0,0))
  34371. };
  34372. MathLight.convertWorkshopOrthoZoom = function(e) {
  34373. //return e === -1 ? -1 : e / 16 * ($('#player').width() / $('#player').height()) / n.workshopApsect
  34374. return e === -1 ? -1 : e * ($("#player").width() / $("#player").height()) ;
  34375. };
  34376. MathLight.convertWorkshopPanoramaQuaternion = function(e) {
  34377. return new MathLight.Quaternion(e.x,-e.y,-e.z,e.w).normalize().multiply((new MathLight.Quaternion).setFromAxisAngle(new MathLight.Vector3(0,1,0), 270 * MathLight.RADIANS_PER_DEGREE))
  34378. };
  34379. MathLight.normalize = function(e) {
  34380. var t = e.x * e.x + e.y * e.y + e.z * e.z
  34381. , i = Math.sqrt(t);
  34382. e.x /= i,
  34383. e.y /= i,
  34384. e.z /= i;
  34385. };
  34386. MathLight.dot = function(e, t) {
  34387. return e.x * t.x + e.y * t.y + e.z * t.z
  34388. };
  34389. MathLight.cross = function(e, t, i) {
  34390. var n = e.x
  34391. , r = e.y
  34392. , o = e.z;
  34393. i.x = r * t.z - o * t.y,
  34394. i.y = o * t.x - n * t.z,
  34395. i.z = n * t.y - r * t.x;
  34396. };
  34397. MathLight.setVector = function(e, t, i, n) {
  34398. e.x = t,
  34399. e.y = i,
  34400. e.z = n;
  34401. };
  34402. MathLight.copyVector = function(e, t) {
  34403. t.x = e.x,
  34404. t.y = e.y,
  34405. t.z = e.z;
  34406. };
  34407. MathLight.addVector = function(e, t) {
  34408. e.x += t.x,
  34409. e.y += t.y,
  34410. e.z += t.z;
  34411. };
  34412. MathLight.subVector = function(e, t) {
  34413. e.x -= t.x,
  34414. e.y -= t.y,
  34415. e.z -= t.z;
  34416. };
  34417. MathLight.applyQuaternionToVector = function(e, t) {
  34418. var i = t.x
  34419. , n = t.y
  34420. , r = t.z
  34421. , o = e.x
  34422. , a = e.y
  34423. , s = e.z
  34424. , l = e.w
  34425. , c = l * i + a * r - s * n
  34426. , h = l * n + s * i - o * r
  34427. , u = l * r + o * n - a * i
  34428. , d = -o * i - a * n - s * r;
  34429. t.x = c * l + d * -o + h * -s - u * -a,
  34430. t.y = h * l + d * -a + u * -o - c * -s,
  34431. t.z = u * l + d * -s + c * -a - h * -o;
  34432. };
  34433. MathLight.angleBetweenVectors = function(e, t) {
  34434. return Math.acos(MathLight.dot(e, t))
  34435. };
  34436. var cameraLight = {
  34437. clampVFOV: function(currentFov, maxHFov, width, height) {//限制currentFov, 使之造成的横向fov不大于指定值maxHFov
  34438. var r = cameraLight.getHFOVFromVFOV(currentFov, width, height);
  34439. return r > maxHFov ? cameraLight.getVFOVFromHFOV(maxHFov, width, height) : currentFov
  34440. },
  34441. getHFOVForCamera: function(camera, getRad) {
  34442. return cameraLight.getHFOVByScreenPrecent(camera.fov, camera.aspect, getRad)
  34443. },
  34444. //add
  34445. getHFOVByScreenPrecent: function(fov, percent, getRad) { //当fov为占比百分百时,percent代表在屏幕上从中心到边缘的占比
  34446. let rad = 2 * Math.atan(percent * Math.tan(fov * MathLight.RADIANS_PER_DEGREE / 2));
  34447. if(getRad)return rad
  34448. else return rad * MathLight.DEGREES_PER_RADIAN;
  34449. }
  34450. };
  34451. const XHRFactory = {
  34452. config: {
  34453. withCredentials: false,
  34454. customHeaders: [
  34455. { header: null, value: null }
  34456. ]
  34457. },
  34458. createXMLHttpRequest: function () {
  34459. let xhr = new XMLHttpRequest();
  34460. if (this.config.customHeaders &&
  34461. Array.isArray(this.config.customHeaders) &&
  34462. this.config.customHeaders.length > 0) {
  34463. let baseOpen = xhr.open;
  34464. let customHeaders = this.config.customHeaders;
  34465. xhr.open = function () {
  34466. baseOpen.apply(this, [].slice.call(arguments));
  34467. customHeaders.forEach(function (customHeader) {
  34468. if (!!customHeader.header && !!customHeader.value) {
  34469. xhr.setRequestHeader(customHeader.header, customHeader.value);
  34470. }
  34471. });
  34472. };
  34473. }
  34474. return xhr;
  34475. }
  34476. };
  34477. class TextSprite$1 extends Object3D{//old
  34478. constructor(text){
  34479. super();
  34480. let texture = new Texture();
  34481. texture.minFilter = LinearFilter;
  34482. texture.magFilter = LinearFilter;
  34483. let spriteMaterial = new SpriteMaterial({
  34484. map: texture,
  34485. depthTest: false,
  34486. depthWrite: false});
  34487. this.texture = texture;
  34488. this.material = spriteMaterial;
  34489. //this.material = getRawMaterial(texture);
  34490. this.sprite = new Sprite$1(this.material);
  34491. this.add(this.sprite);
  34492. this.borderThickness = 4;
  34493. this.fontface = 'Arial';
  34494. this.fontsize = 28;
  34495. this.borderColor = { r: 0, g: 0, b: 0, a: 1.0 };
  34496. this.backgroundColor = { r: 255, g: 255, b: 255, a: 1.0 };
  34497. this.textColor = {r: 255, g: 255, b: 255, a: 1.0};
  34498. this.text = '';
  34499. this.setText(text);
  34500. }
  34501. setText(text){
  34502. if (this.text !== text){
  34503. this.text = text;
  34504. this.update();
  34505. }
  34506. }
  34507. setTextColor(color){
  34508. this.textColor = color;
  34509. this.update();
  34510. }
  34511. setBorderColor(color){
  34512. this.borderColor = color;
  34513. this.update();
  34514. }
  34515. setBackgroundColor(color){
  34516. this.backgroundColor = color;
  34517. this.update();
  34518. }
  34519. update(){
  34520. let canvas = document.createElement('canvas');
  34521. let context = canvas.getContext('2d');
  34522. context.font = 'Bold ' + this.fontsize + 'px ' + this.fontface;
  34523. // get size data (height depends only on font size)
  34524. let metrics = context.measureText(this.text);
  34525. let textWidth = metrics.width;
  34526. let margin = 5;
  34527. let spriteWidth = 2 * margin + textWidth + 2 * this.borderThickness;
  34528. let spriteHeight = this.fontsize * 1.4 + 2 * this.borderThickness;
  34529. context.canvas.width = spriteWidth;
  34530. context.canvas.height = spriteHeight;
  34531. context.font = 'Bold ' + this.fontsize + 'px ' + this.fontface;
  34532. // background color
  34533. context.fillStyle = 'rgba(' + this.backgroundColor.r + ',' + this.backgroundColor.g + ',' +
  34534. this.backgroundColor.b + ',' + this.backgroundColor.a + ')';
  34535. // border color
  34536. context.strokeStyle = 'rgba(' + this.borderColor.r + ',' + this.borderColor.g + ',' +
  34537. this.borderColor.b + ',' + this.borderColor.a + ')';
  34538. context.lineWidth = this.borderThickness;
  34539. this.roundRect(context, this.borderThickness / 2, this.borderThickness / 2,
  34540. textWidth + this.borderThickness + 2 * margin, this.fontsize * 1.4 + this.borderThickness, 6);
  34541. // text color
  34542. context.strokeStyle = 'rgba(0, 0, 0, 1.0)';
  34543. context.strokeText(this.text, this.borderThickness + margin, this.fontsize + this.borderThickness);
  34544. context.fillStyle = 'rgba(' + this.textColor.r + ',' + this.textColor.g + ',' +
  34545. this.textColor.b + ',' + this.textColor.a + ')';
  34546. context.fillText(this.text, this.borderThickness + margin, this.fontsize + this.borderThickness);
  34547. let texture = new Texture(canvas);
  34548. texture.minFilter = LinearFilter;
  34549. texture.magFilter = LinearFilter;
  34550. texture.needsUpdate = true;
  34551. //this.material.needsUpdate = true;
  34552. // { // screen-space sprite
  34553. // let [screenWidth, screenHeight] = [1620, 937];
  34554. // let uniforms = this.sprite.material.uniforms;
  34555. // let aspect = spriteHeight / spriteWidth;
  34556. // let factor = 0.5;
  34557. // let w = spriteWidth / screenWidth;
  34558. // let h = spriteHeight / screenHeight;
  34559. // uniforms.uScale.value = [2 * w, 2 * h];
  34560. // //uniforms.uScale.value = [factor * 1, factor * aspect];
  34561. // this.sprite.material.uniforms.map.value = texture;
  34562. // }
  34563. this.sprite.material.map = texture;
  34564. this.texture = texture;
  34565. this.sprite.scale.set(spriteWidth * 0.01, spriteHeight * 0.01, 1.0);
  34566. }
  34567. roundRect(ctx, x, y, w, h, r){
  34568. ctx.beginPath();
  34569. ctx.moveTo(x + r, y);
  34570. ctx.lineTo(x + w - r, y);
  34571. ctx.quadraticCurveTo(x + w, y, x + w, y + r);
  34572. ctx.lineTo(x + w, y + h - r);
  34573. ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
  34574. ctx.lineTo(x + r, y + h);
  34575. ctx.quadraticCurveTo(x, y + h, x, y + h - r);
  34576. ctx.lineTo(x, y + r);
  34577. ctx.quadraticCurveTo(x, y, x + r, y);
  34578. ctx.closePath();
  34579. ctx.fill();
  34580. ctx.stroke();
  34581. }
  34582. }
  34583. class Volume extends Object3D {
  34584. constructor (args = {}) {
  34585. super();
  34586. if(this.constructor.name === "Volume"){
  34587. console.warn("Can't create object of class Volume directly. Use classes BoxVolume or SphereVolume instead.");
  34588. }
  34589. //console.log(this);
  34590. //console.log(this.constructor);
  34591. //console.log(this.constructor.name);
  34592. this._clip = args.clip || false;
  34593. this._visible = true;
  34594. this.showVolumeLabel = true;
  34595. this._modifiable = args.modifiable || true;
  34596. this.label = new TextSprite$1('0');
  34597. this.label.setBorderColor({r: 0, g: 255, b: 0, a: 0.0});
  34598. this.label.setBackgroundColor({r: 0, g: 255, b: 0, a: 0.0});
  34599. this.label.material.depthTest = false;
  34600. this.label.material.depthWrite = false;
  34601. this.label.material.transparent = true;
  34602. this.label.position.y -= 0.5;
  34603. this.add(this.label);
  34604. this.label.updateMatrixWorld = () => {
  34605. let volumeWorldPos = new Vector3();
  34606. volumeWorldPos.setFromMatrixPosition(this.matrixWorld);
  34607. this.label.position.copy(volumeWorldPos);
  34608. this.label.updateMatrix();
  34609. this.label.matrixWorld.copy(this.label.matrix);
  34610. this.label.matrixWorldNeedsUpdate = false;
  34611. for (let i = 0, l = this.label.children.length; i < l; i++) {
  34612. this.label.children[ i ].updateMatrixWorld(true);
  34613. }
  34614. };
  34615. { // event listeners
  34616. this.addEventListener('select', e => {});
  34617. this.addEventListener('deselect', e => {});
  34618. }
  34619. }
  34620. get visible(){
  34621. return this._visible;
  34622. }
  34623. set visible(value){
  34624. if(this._visible !== value){
  34625. this._visible = value;
  34626. this.dispatchEvent({type: "visibility_changed", object: this});
  34627. }
  34628. }
  34629. getVolume () {
  34630. console.warn("override this in subclass");
  34631. }
  34632. update () {
  34633. };
  34634. raycast (raycaster, intersects) {
  34635. }
  34636. get clip () {
  34637. return this._clip;
  34638. }
  34639. set clip (value) {
  34640. if(this._clip !== value){
  34641. this._clip = value;
  34642. this.update();
  34643. this.dispatchEvent({
  34644. type: "clip_changed",
  34645. object: this
  34646. });
  34647. }
  34648. }
  34649. get modifieable () {
  34650. return this._modifiable;
  34651. }
  34652. set modifieable (value) {
  34653. this._modifiable = value;
  34654. this.update();
  34655. }
  34656. };
  34657. class BoxVolume extends Volume{
  34658. constructor(args = {}){
  34659. super(args);
  34660. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  34661. this.name = 'box_' + this.constructor.counter;
  34662. let boxGeometry = new BoxGeometry(1, 1, 1);
  34663. boxGeometry.computeBoundingBox();
  34664. let boxFrameGeometry = new Geometry();
  34665. {
  34666. let Vector3$1 = Vector3;
  34667. boxFrameGeometry.vertices.push(
  34668. // bottom
  34669. new Vector3$1(-0.5, -0.5, 0.5),
  34670. new Vector3$1(0.5, -0.5, 0.5),
  34671. new Vector3$1(0.5, -0.5, 0.5),
  34672. new Vector3$1(0.5, -0.5, -0.5),
  34673. new Vector3$1(0.5, -0.5, -0.5),
  34674. new Vector3$1(-0.5, -0.5, -0.5),
  34675. new Vector3$1(-0.5, -0.5, -0.5),
  34676. new Vector3$1(-0.5, -0.5, 0.5),
  34677. // top
  34678. new Vector3$1(-0.5, 0.5, 0.5),
  34679. new Vector3$1(0.5, 0.5, 0.5),
  34680. new Vector3$1(0.5, 0.5, 0.5),
  34681. new Vector3$1(0.5, 0.5, -0.5),
  34682. new Vector3$1(0.5, 0.5, -0.5),
  34683. new Vector3$1(-0.5, 0.5, -0.5),
  34684. new Vector3$1(-0.5, 0.5, -0.5),
  34685. new Vector3$1(-0.5, 0.5, 0.5),
  34686. // sides
  34687. new Vector3$1(-0.5, -0.5, 0.5),
  34688. new Vector3$1(-0.5, 0.5, 0.5),
  34689. new Vector3$1(0.5, -0.5, 0.5),
  34690. new Vector3$1(0.5, 0.5, 0.5),
  34691. new Vector3$1(0.5, -0.5, -0.5),
  34692. new Vector3$1(0.5, 0.5, -0.5),
  34693. new Vector3$1(-0.5, -0.5, -0.5),
  34694. new Vector3$1(-0.5, 0.5, -0.5),
  34695. );
  34696. }
  34697. this.material = new MeshBasicMaterial({
  34698. color: 0x00ff00,
  34699. transparent: true,
  34700. opacity: 0.3,
  34701. depthTest: true,
  34702. depthWrite: false});
  34703. this.box = new Mesh(boxGeometry, this.material);
  34704. this.box.geometry.computeBoundingBox();
  34705. this.boundingBox = this.box.geometry.boundingBox;
  34706. this.add(this.box);
  34707. this.frame = new LineSegments(boxFrameGeometry, new LineBasicMaterial({color: 0x000000}));
  34708. // this.frame.mode = THREE.Lines;
  34709. this.add(this.frame);
  34710. this.update();
  34711. }
  34712. update(){
  34713. this.boundingBox = this.box.geometry.boundingBox;
  34714. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  34715. if (this._clip) {
  34716. this.box.visible = false;
  34717. this.label.visible = false;
  34718. } else {
  34719. this.box.visible = true;
  34720. this.label.visible = this.showVolumeLabel;
  34721. }
  34722. }
  34723. raycast (raycaster, intersects) {
  34724. let is = [];
  34725. this.box.raycast(raycaster, is);
  34726. if (is.length > 0) {
  34727. let I = is[0];
  34728. intersects.push({
  34729. distance: I.distance,
  34730. object: this,
  34731. point: I.point.clone()
  34732. });
  34733. }
  34734. }
  34735. getVolume(){
  34736. return Math.abs(this.scale.x * this.scale.y * this.scale.z);
  34737. }
  34738. };
  34739. class SphereVolume$1 extends Volume{
  34740. constructor(args = {}){
  34741. super(args);
  34742. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  34743. this.name = 'sphere_' + this.constructor.counter;
  34744. let sphereGeometry = new SphereGeometry(1, 32, 32);
  34745. sphereGeometry.computeBoundingBox();
  34746. this.material = new MeshBasicMaterial({
  34747. color: 0x00ff00,
  34748. transparent: true,
  34749. opacity: 0.3,
  34750. depthTest: true,
  34751. depthWrite: false});
  34752. this.sphere = new Mesh(sphereGeometry, this.material);
  34753. this.sphere.visible = false;
  34754. this.sphere.geometry.computeBoundingBox();
  34755. this.boundingBox = this.sphere.geometry.boundingBox;
  34756. this.add(this.sphere);
  34757. this.label.visible = false;
  34758. let frameGeometry = new Geometry();
  34759. {
  34760. let steps = 64;
  34761. let uSegments = 8;
  34762. let vSegments = 5;
  34763. let r = 1;
  34764. for(let uSegment = 0; uSegment < uSegments; uSegment++){
  34765. let alpha = (uSegment / uSegments) * Math.PI * 2;
  34766. let dirx = Math.cos(alpha);
  34767. let diry = Math.sin(alpha);
  34768. for(let i = 0; i <= steps; i++){
  34769. let v = (i / steps) * Math.PI * 2;
  34770. let vNext = v + 2 * Math.PI / steps;
  34771. let height = Math.sin(v);
  34772. let xyAmount = Math.cos(v);
  34773. let heightNext = Math.sin(vNext);
  34774. let xyAmountNext = Math.cos(vNext);
  34775. let vertex = new Vector3(dirx * xyAmount, diry * xyAmount, height);
  34776. frameGeometry.vertices.push(vertex);
  34777. let vertexNext = new Vector3(dirx * xyAmountNext, diry * xyAmountNext, heightNext);
  34778. frameGeometry.vertices.push(vertexNext);
  34779. }
  34780. }
  34781. // creates rings at poles, just because it's easier to implement
  34782. for(let vSegment = 0; vSegment <= vSegments + 1; vSegment++){
  34783. //let height = (vSegment / (vSegments + 1)) * 2 - 1; // -1 to 1
  34784. let uh = (vSegment / (vSegments + 1)); // -1 to 1
  34785. uh = (1 - uh) * (-Math.PI / 2) + uh *(Math.PI / 2);
  34786. let height = Math.sin(uh);
  34787. console.log(uh, height);
  34788. for(let i = 0; i <= steps; i++){
  34789. let u = (i / steps) * Math.PI * 2;
  34790. let uNext = u + 2 * Math.PI / steps;
  34791. let dirx = Math.cos(u);
  34792. let diry = Math.sin(u);
  34793. let dirxNext = Math.cos(uNext);
  34794. let diryNext = Math.sin(uNext);
  34795. let xyAmount = Math.sqrt(1 - height * height);
  34796. let vertex = new Vector3(dirx * xyAmount, diry * xyAmount, height);
  34797. frameGeometry.vertices.push(vertex);
  34798. let vertexNext = new Vector3(dirxNext * xyAmount, diryNext * xyAmount, height);
  34799. frameGeometry.vertices.push(vertexNext);
  34800. }
  34801. }
  34802. }
  34803. this.frame = new LineSegments(frameGeometry, new LineBasicMaterial({color: 0x000000}));
  34804. this.add(this.frame);
  34805. let frameMaterial = new MeshBasicMaterial({wireframe: true, color: 0x000000});
  34806. this.frame = new Mesh(sphereGeometry, frameMaterial);
  34807. //this.add(this.frame);
  34808. //this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: 0x000000}));
  34809. // this.frame.mode = THREE.Lines;
  34810. //this.add(this.frame);
  34811. this.update();
  34812. }
  34813. update(){
  34814. this.boundingBox = this.sphere.geometry.boundingBox;
  34815. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  34816. //if (this._clip) {
  34817. // this.sphere.visible = false;
  34818. // this.label.visible = false;
  34819. //} else {
  34820. // this.sphere.visible = true;
  34821. // this.label.visible = this.showVolumeLabel;
  34822. //}
  34823. }
  34824. raycast (raycaster, intersects) {
  34825. let is = [];
  34826. this.sphere.raycast(raycaster, is);
  34827. if (is.length > 0) {
  34828. let I = is[0];
  34829. intersects.push({
  34830. distance: I.distance,
  34831. object: this,
  34832. point: I.point.clone()
  34833. });
  34834. }
  34835. }
  34836. // see https://en.wikipedia.org/wiki/Ellipsoid#Volume
  34837. getVolume(){
  34838. return (4 / 3) * Math.PI * this.scale.x * this.scale.y * this.scale.z;
  34839. }
  34840. };
  34841. class Profile extends Object3D{
  34842. constructor () {
  34843. super();
  34844. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  34845. this.name = 'Profile_' + this.constructor.counter;
  34846. this.points = [];
  34847. this.spheres = [];
  34848. this.edges = [];
  34849. this.boxes = [];
  34850. this.width = 1;
  34851. this.height = 20;
  34852. this._modifiable = true;
  34853. this.sphereGeometry = new SphereGeometry(0.4, 10, 10);
  34854. this.color = new Color(0xff0000);
  34855. this.lineColor = new Color(0xff0000);
  34856. }
  34857. createSphereMaterial () {
  34858. let sphereMaterial = new MeshLambertMaterial({
  34859. //shading: THREE.SmoothShading,
  34860. color: 0xff0000,
  34861. depthTest: false,
  34862. depthWrite: false}
  34863. );
  34864. return sphereMaterial;
  34865. };
  34866. getSegments () {
  34867. let segments = [];
  34868. for (let i = 0; i < this.points.length - 1; i++) {
  34869. let start = this.points[i].clone();
  34870. let end = this.points[i + 1].clone();
  34871. segments.push({start: start, end: end});
  34872. }
  34873. return segments;
  34874. }
  34875. getSegmentMatrices () {
  34876. let segments = this.getSegments();
  34877. let matrices = [];
  34878. for (let segment of segments) {
  34879. let {start, end} = segment;
  34880. let box = new Object3D();
  34881. let length = start.clone().setZ(0).distanceTo(end.clone().setZ(0));
  34882. box.scale.set(length, 10000, this.width);
  34883. box.up.set(0, 0, 1);
  34884. let center = new Vector3().addVectors(start, end).multiplyScalar(0.5);
  34885. let diff = new Vector3().subVectors(end, start);
  34886. let target = new Vector3(diff.y, -diff.x, 0);
  34887. box.position.set(0, 0, 0);
  34888. box.lookAt(target);
  34889. box.position.copy(center);
  34890. box.updateMatrixWorld();
  34891. matrices.push(box.matrixWorld);
  34892. }
  34893. return matrices;
  34894. }
  34895. addMarker (point) {
  34896. this.points.push(point);
  34897. let sphere = new Mesh(this.sphereGeometry, this.createSphereMaterial());
  34898. this.add(sphere);
  34899. this.spheres.push(sphere);
  34900. // edges & boxes
  34901. if (this.points.length > 1) {
  34902. let lineGeometry = new Geometry();
  34903. lineGeometry.vertices.push(new Vector3(), new Vector3());
  34904. lineGeometry.colors.push(this.lineColor, this.lineColor, this.lineColor);
  34905. let lineMaterial = new LineBasicMaterial({
  34906. vertexColors: VertexColors,
  34907. linewidth: 2,
  34908. transparent: true,
  34909. opacity: 0.4
  34910. });
  34911. lineMaterial.depthTest = false;
  34912. let edge = new Line(lineGeometry, lineMaterial);
  34913. edge.visible = false;
  34914. this.add(edge);
  34915. this.edges.push(edge);
  34916. let boxGeometry = new BoxGeometry(1, 1, 1);
  34917. let boxMaterial = new MeshBasicMaterial({color: 0xff0000, transparent: true, opacity: 0.2});
  34918. let box = new Mesh(boxGeometry, boxMaterial);
  34919. box.visible = false;
  34920. this.add(box);
  34921. this.boxes.push(box);
  34922. }
  34923. { // event listeners
  34924. let drag = (e) => {
  34925. let I = Utils.getMousePointCloudIntersection(
  34926. e.drag.end,
  34927. e.viewer.scene.getActiveCamera(),
  34928. e.viewer,
  34929. e.viewer.scene.pointclouds);
  34930. if (I) {
  34931. let i = this.spheres.indexOf(e.drag.object);
  34932. if (i !== -1) {
  34933. this.setPosition(i, I.location);
  34934. //this.dispatchEvent({
  34935. // 'type': 'marker_moved',
  34936. // 'profile': this,
  34937. // 'index': i
  34938. //});
  34939. }
  34940. }
  34941. };
  34942. let drop = e => {
  34943. let i = this.spheres.indexOf(e.drag.object);
  34944. if (i !== -1) {
  34945. this.dispatchEvent({
  34946. 'type': 'marker_dropped',
  34947. 'profile': this,
  34948. 'index': i
  34949. });
  34950. }
  34951. };
  34952. let mouseover = (e) => e.object.material.emissive.setHex(0x888888);
  34953. let mouseleave = (e) => e.object.material.emissive.setHex(0x000000);
  34954. sphere.addEventListener('drag', drag);
  34955. sphere.addEventListener('drop', drop);
  34956. sphere.addEventListener('mouseover', mouseover);
  34957. sphere.addEventListener('mouseleave', mouseleave);
  34958. }
  34959. let event = {
  34960. type: 'marker_added',
  34961. profile: this,
  34962. sphere: sphere
  34963. };
  34964. this.dispatchEvent(event);
  34965. this.setPosition(this.points.length - 1, point);
  34966. }
  34967. removeMarker (index) {
  34968. this.points.splice(index, 1);
  34969. this.remove(this.spheres[index]);
  34970. let edgeIndex = (index === 0) ? 0 : (index - 1);
  34971. this.remove(this.edges[edgeIndex]);
  34972. this.edges.splice(edgeIndex, 1);
  34973. this.remove(this.boxes[edgeIndex]);
  34974. this.boxes.splice(edgeIndex, 1);
  34975. this.spheres.splice(index, 1);
  34976. this.update();
  34977. this.dispatchEvent({
  34978. 'type': 'marker_removed',
  34979. 'profile': this
  34980. });
  34981. }
  34982. setPosition (index, position) {
  34983. let point = this.points[index];
  34984. point.copy(position);
  34985. let event = {
  34986. type: 'marker_moved',
  34987. profile: this,
  34988. index: index,
  34989. position: point.clone()
  34990. };
  34991. this.dispatchEvent(event);
  34992. this.update();
  34993. }
  34994. setWidth (width) {
  34995. this.width = width;
  34996. let event = {
  34997. type: 'width_changed',
  34998. profile: this,
  34999. width: width
  35000. };
  35001. this.dispatchEvent(event);
  35002. this.update();
  35003. }
  35004. getWidth () {
  35005. return this.width;
  35006. }
  35007. update () {
  35008. if (this.points.length === 0) {
  35009. return;
  35010. } else if (this.points.length === 1) {
  35011. let point = this.points[0];
  35012. this.spheres[0].position.copy(point);
  35013. return;
  35014. }
  35015. let min = this.points[0].clone();
  35016. let max = this.points[0].clone();
  35017. let centroid = new Vector3();
  35018. let lastIndex = this.points.length - 1;
  35019. for (let i = 0; i <= lastIndex; i++) {
  35020. let point = this.points[i];
  35021. let sphere = this.spheres[i];
  35022. let leftIndex = (i === 0) ? lastIndex : i - 1;
  35023. // let rightIndex = (i === lastIndex) ? 0 : i + 1;
  35024. let leftVertex = this.points[leftIndex];
  35025. // let rightVertex = this.points[rightIndex];
  35026. let leftEdge = this.edges[leftIndex];
  35027. let rightEdge = this.edges[i];
  35028. let leftBox = this.boxes[leftIndex];
  35029. // rightBox = this.boxes[i];
  35030. // let leftEdgeLength = point.distanceTo(leftVertex);
  35031. // let rightEdgeLength = point.distanceTo(rightVertex);
  35032. // let leftEdgeCenter = new THREE.Vector3().addVectors(leftVertex, point).multiplyScalar(0.5);
  35033. // let rightEdgeCenter = new THREE.Vector3().addVectors(point, rightVertex).multiplyScalar(0.5);
  35034. sphere.position.copy(point);
  35035. if (this._modifiable) {
  35036. sphere.visible = true;
  35037. } else {
  35038. sphere.visible = false;
  35039. }
  35040. if (leftEdge) {
  35041. leftEdge.geometry.vertices[1].copy(point);
  35042. leftEdge.geometry.verticesNeedUpdate = true;
  35043. leftEdge.geometry.computeBoundingSphere();
  35044. }
  35045. if (rightEdge) {
  35046. rightEdge.geometry.vertices[0].copy(point);
  35047. rightEdge.geometry.verticesNeedUpdate = true;
  35048. rightEdge.geometry.computeBoundingSphere();
  35049. }
  35050. if (leftBox) {
  35051. let start = leftVertex;
  35052. let end = point;
  35053. let length = start.clone().setZ(0).distanceTo(end.clone().setZ(0));
  35054. leftBox.scale.set(length, 1000000, this.width);
  35055. leftBox.up.set(0, 0, 1);
  35056. let center = new Vector3().addVectors(start, end).multiplyScalar(0.5);
  35057. let diff = new Vector3().subVectors(end, start);
  35058. let target = new Vector3(diff.y, -diff.x, 0);
  35059. leftBox.position.set(0, 0, 0);
  35060. leftBox.lookAt(target);
  35061. leftBox.position.copy(center);
  35062. }
  35063. centroid.add(point);
  35064. min.min(point);
  35065. max.max(point);
  35066. }
  35067. centroid.multiplyScalar(1 / this.points.length);
  35068. for (let i = 0; i < this.boxes.length; i++) {
  35069. let box = this.boxes[i];
  35070. box.position.z = min.z + (max.z - min.z) / 2;
  35071. }
  35072. }
  35073. raycast (raycaster, intersects) {
  35074. for (let i = 0; i < this.points.length; i++) {
  35075. let sphere = this.spheres[i];
  35076. sphere.raycast(raycaster, intersects);
  35077. }
  35078. // recalculate distances because they are not necessarely correct
  35079. // for scaled objects.
  35080. // see https://github.com/mrdoob/three.js/issues/5827
  35081. // TODO: remove this once the bug has been fixed
  35082. for (let i = 0; i < intersects.length; i++) {
  35083. let I = intersects[i];
  35084. I.distance = raycaster.ray.origin.distanceTo(I.point);
  35085. }
  35086. intersects.sort(function (a, b) { return a.distance - b.distance; });
  35087. };
  35088. get modifiable () {
  35089. return this._modifiable;
  35090. }
  35091. set modifiable (value) {
  35092. this._modifiable = value;
  35093. this.update();
  35094. }
  35095. }
  35096. const _box$4 = new Box3();
  35097. const _vector$d = new Vector3();
  35098. class LineSegmentsGeometry extends InstancedBufferGeometry {
  35099. constructor() {
  35100. super();
  35101. this.isLineSegmentsGeometry = true;
  35102. this.type = 'LineSegmentsGeometry';
  35103. const positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ];
  35104. const uvs = [ - 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2 ];
  35105. const index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ];
  35106. this.setIndex( index );
  35107. this.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
  35108. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  35109. }
  35110. applyMatrix4( matrix ) {
  35111. const start = this.attributes.instanceStart;
  35112. const end = this.attributes.instanceEnd;
  35113. if ( start !== undefined ) {
  35114. start.applyMatrix4( matrix );
  35115. end.applyMatrix4( matrix );
  35116. start.needsUpdate = true;
  35117. }
  35118. if ( this.boundingBox !== null ) {
  35119. this.computeBoundingBox();
  35120. }
  35121. if ( this.boundingSphere !== null ) {
  35122. this.computeBoundingSphere();
  35123. }
  35124. return this;
  35125. }
  35126. setPositions( array ) {
  35127. let lineSegments;
  35128. if ( array instanceof Float32Array ) {
  35129. lineSegments = array;
  35130. } else if ( Array.isArray( array ) ) {
  35131. lineSegments = new Float32Array( array );
  35132. }
  35133. const instanceBuffer = new InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz
  35134. this.setAttribute( 'instanceStart', new InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz
  35135. this.setAttribute( 'instanceEnd', new InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz
  35136. //
  35137. this.computeBoundingBox();
  35138. this.computeBoundingSphere();
  35139. return this;
  35140. }
  35141. setColors( array ) {
  35142. let colors;
  35143. if ( array instanceof Float32Array ) {
  35144. colors = array;
  35145. } else if ( Array.isArray( array ) ) {
  35146. colors = new Float32Array( array );
  35147. }
  35148. const instanceColorBuffer = new InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb
  35149. this.setAttribute( 'instanceColorStart', new InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb
  35150. this.setAttribute( 'instanceColorEnd', new InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb
  35151. return this;
  35152. }
  35153. fromWireframeGeometry( geometry ) {
  35154. this.setPositions( geometry.attributes.position.array );
  35155. return this;
  35156. }
  35157. fromEdgesGeometry( geometry ) {
  35158. this.setPositions( geometry.attributes.position.array );
  35159. return this;
  35160. }
  35161. fromMesh( mesh ) {
  35162. this.fromWireframeGeometry( new WireframeGeometry( mesh.geometry ) );
  35163. // set colors, maybe
  35164. return this;
  35165. }
  35166. fromLineSegments( lineSegments ) {
  35167. const geometry = lineSegments.geometry;
  35168. this.setPositions( geometry.attributes.position.array ); // assumes non-indexed
  35169. // set colors, maybe
  35170. return this;
  35171. }
  35172. computeBoundingBox() {
  35173. if ( this.boundingBox === null ) {
  35174. this.boundingBox = new Box3();
  35175. }
  35176. const start = this.attributes.instanceStart;
  35177. const end = this.attributes.instanceEnd;
  35178. if ( start !== undefined && end !== undefined ) {
  35179. this.boundingBox.setFromBufferAttribute( start );
  35180. _box$4.setFromBufferAttribute( end );
  35181. this.boundingBox.union( _box$4 );
  35182. }
  35183. }
  35184. computeBoundingSphere() {
  35185. if ( this.boundingSphere === null ) {
  35186. this.boundingSphere = new Sphere();
  35187. }
  35188. if ( this.boundingBox === null ) {
  35189. this.computeBoundingBox();
  35190. }
  35191. const start = this.attributes.instanceStart;
  35192. const end = this.attributes.instanceEnd;
  35193. if ( start !== undefined && end !== undefined ) {
  35194. const center = this.boundingSphere.center;
  35195. this.boundingBox.getCenter( center );
  35196. let maxRadiusSq = 0;
  35197. for ( let i = 0, il = start.count; i < il; i ++ ) {
  35198. _vector$d.fromBufferAttribute( start, i );
  35199. maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$d ) );
  35200. _vector$d.fromBufferAttribute( end, i );
  35201. maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$d ) );
  35202. }
  35203. this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
  35204. if ( isNaN( this.boundingSphere.radius ) ) {
  35205. console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this );
  35206. }
  35207. }
  35208. }
  35209. toJSON() {
  35210. // todo
  35211. }
  35212. applyMatrix( matrix ) {
  35213. console.warn( 'THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().' );
  35214. return this.applyMatrix4( matrix );
  35215. }
  35216. }
  35217. /**
  35218. * parameters = {
  35219. * color: <hex>,
  35220. * lineWidth: <float>,
  35221. * dashed: <boolean>,
  35222. * dashScale: <float>,
  35223. * dashSize: <float>,
  35224. * dashOffset: <float>,
  35225. * gapSize: <float>,
  35226. * resolution: <Vector2>, // to be set by renderer
  35227. * }
  35228. */
  35229. UniformsLib.line = {
  35230. /*
  35231. worldUnits: { value: 1 },
  35232. lineWidth: { value: 1 },
  35233. resolution: { value: new Vector2( 1, 1 ) },
  35234. dashOffset: { value: 0 },
  35235. dashScale: { value: 1 },
  35236. dashSize: { value: 1 },
  35237. gapSize: { value: 1 } // todo FIX - maybe change to totalSize
  35238. */
  35239. worldUnits: { value: 1 },
  35240. lineWidth: { value: 1 },
  35241. resolution: { value: new Vector2( 1, 1 ) },
  35242. viewportOffset: { value: new Vector2(0, 0 ) }, //left, top
  35243. devicePixelRatio:{ value:window.devicePixelRatio},
  35244. dashScale: { value: 1 },
  35245. dashSize: { value: 1 },
  35246. dashOffset: { value: 0 },
  35247. gapSize: { value: 1 },
  35248. opacity: { value: 1 },
  35249. backColor: {type:'v3', value: new Color("#ddd")},
  35250. clipDistance : { type: 'f', value: 4}, //消失距离
  35251. occlusionDistance : { type: 'f', value: 1 }, //变为backColor距离
  35252. maxClipFactor : { type: 'f', value: 1 }, //0-1
  35253. maxOcclusionFactor : { type: 'f', value: 1 }, //0-1
  35254. depthTexture:{ value: null },
  35255. nearPlane:{value: 0.1},
  35256. farPlane:{value: 100000},
  35257. uUseOrthographicCamera:{ type: "b", value: false },
  35258. };
  35259. ShaderLib[ 'line' ] = {
  35260. uniforms: UniformsUtils.merge( [
  35261. UniformsLib.common,
  35262. UniformsLib.fog,
  35263. UniformsLib.line
  35264. ] ),
  35265. vertexShader:
  35266. /* glsl */`
  35267. #include <common>
  35268. #include <color_pars_vertex>
  35269. #include <fog_pars_vertex>
  35270. #include <logdepthbuf_pars_vertex>
  35271. #include <clipping_planes_pars_vertex>
  35272. uniform float lineWidth;
  35273. uniform vec2 resolution;
  35274. uniform float devicePixelRatio; //add
  35275. attribute vec3 instanceStart;
  35276. attribute vec3 instanceEnd;
  35277. attribute vec3 instanceColorStart;
  35278. attribute vec3 instanceColorEnd;
  35279. #ifdef WORLD_UNITS
  35280. varying vec4 worldPos;
  35281. varying vec3 worldStart;
  35282. varying vec3 worldEnd;
  35283. #ifdef USE_DASH
  35284. varying vec2 vUv;
  35285. #endif
  35286. #else
  35287. varying vec2 vUv;
  35288. #endif
  35289. #ifdef USE_DASH
  35290. uniform float dashScale;
  35291. attribute float instanceDistanceStart;
  35292. attribute float instanceDistanceEnd;
  35293. varying float vLineDistance;
  35294. #endif
  35295. void trimSegment( const in vec4 start, inout vec4 end ) {
  35296. // trim end segment so it terminates between the camera plane and the near plane
  35297. // conservative estimate of the near plane
  35298. float a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column
  35299. float b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column
  35300. float nearEstimate = - 0.5 * b / a;
  35301. float alpha = ( nearEstimate - start.z ) / ( end.z - start.z );
  35302. end.xyz = mix( start.xyz, end.xyz, alpha );
  35303. }
  35304. void main() {
  35305. #ifdef USE_COLOR
  35306. vColor.xyz = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd;
  35307. #endif
  35308. #ifdef USE_DASH
  35309. vLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd;
  35310. vUv = uv;
  35311. #endif
  35312. float aspect = resolution.x / resolution.y;
  35313. // camera space
  35314. vec4 start = modelViewMatrix * vec4( instanceStart, 1.0 );
  35315. vec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 );
  35316. #ifdef WORLD_UNITS
  35317. worldStart = start.xyz;
  35318. worldEnd = end.xyz;
  35319. #else
  35320. vUv = uv;
  35321. #endif
  35322. // special case for perspective projection, and segments that terminate either in, or behind, the camera plane
  35323. // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
  35324. // but we need to perform ndc-space calculations in the shader, so we must address this issue directly
  35325. // perhaps there is a more elegant solution -- WestLangley
  35326. bool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column
  35327. if ( perspective ) {
  35328. if ( start.z < 0.0 && end.z >= 0.0 ) {
  35329. trimSegment( start, end );
  35330. } else if ( end.z < 0.0 && start.z >= 0.0 ) {
  35331. trimSegment( end, start );
  35332. }
  35333. }
  35334. // clip space
  35335. vec4 clipStart = projectionMatrix * start;
  35336. vec4 clipEnd = projectionMatrix * end;
  35337. // ndc space
  35338. vec3 ndcStart = clipStart.xyz / clipStart.w;
  35339. vec3 ndcEnd = clipEnd.xyz / clipEnd.w;
  35340. // direction
  35341. vec2 dir = ndcEnd.xy - ndcStart.xy;
  35342. // account for clip-space aspect ratio
  35343. dir.x *= aspect;
  35344. dir = normalize( dir );
  35345. #ifdef WORLD_UNITS
  35346. // get the offset direction as perpendicular to the view vector
  35347. vec3 worldDir = normalize( end.xyz - start.xyz );
  35348. vec3 offset;
  35349. if ( position.y < 0.5 ) {
  35350. offset = normalize( cross( start.xyz, worldDir ) );
  35351. } else {
  35352. offset = normalize( cross( end.xyz, worldDir ) );
  35353. }
  35354. // sign flip
  35355. if ( position.x < 0.0 ) offset *= - 1.0;
  35356. float forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) );
  35357. // don't extend the line if we're rendering dashes because we
  35358. // won't be rendering the endcaps
  35359. #ifndef USE_DASH
  35360. // extend the line bounds to encompass endcaps
  35361. start.xyz += - worldDir * lineWidth * 0.5;
  35362. end.xyz += worldDir * lineWidth * 0.5;
  35363. // shift the position of the quad so it hugs the forward edge of the line
  35364. offset.xy -= dir * forwardOffset;
  35365. offset.z += 0.5;
  35366. #endif
  35367. // endcaps
  35368. if ( position.y > 1.0 || position.y < 0.0 ) {
  35369. offset.xy += dir * 2.0 * forwardOffset;
  35370. }
  35371. // adjust for lineWidth
  35372. offset *= lineWidth * 0.5;
  35373. // set the world position
  35374. worldPos = ( position.y < 0.5 ) ? start : end;
  35375. worldPos.xyz += offset;
  35376. // project the worldpos
  35377. vec4 clip = projectionMatrix * worldPos;
  35378. // shift the depth of the projected points so the line
  35379. // segments overlap neatly
  35380. vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd;
  35381. clip.z = clipPose.z * clip.w;
  35382. #else
  35383. vec2 offset = vec2( dir.y, - dir.x );
  35384. // undo aspect ratio adjustment
  35385. dir.x /= aspect;
  35386. offset.x /= aspect;
  35387. // sign flip
  35388. if ( position.x < 0.0 ) offset *= - 1.0;
  35389. // endcaps
  35390. if ( position.y < 0.0 ) {
  35391. offset += - dir;
  35392. } else if ( position.y > 1.0 ) {
  35393. offset += dir;
  35394. }
  35395. // adjust for lineWidth
  35396. offset *= lineWidth;
  35397. // adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
  35398. offset /= resolution.y;// * devicePixelRatio;
  35399. // select end
  35400. vec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd;
  35401. // back to clip space
  35402. offset *= clip.w;
  35403. clip.xy += offset;
  35404. #endif
  35405. gl_Position = clip;
  35406. vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation
  35407. #include <logdepthbuf_vertex>
  35408. #include <clipping_planes_vertex>
  35409. #include <fog_vertex>
  35410. }
  35411. `,
  35412. fragmentShader:
  35413. /* glsl */`
  35414. uniform vec3 diffuse;
  35415. uniform float opacity;
  35416. uniform float lineWidth;
  35417. uniform bool uUseOrthographicCamera;
  35418. #ifdef USE_DASH
  35419. uniform float dashOffset;
  35420. uniform float dashSize;
  35421. uniform float gapSize;
  35422. #endif
  35423. //加
  35424. #if defined(GL_EXT_frag_depth) && defined(useDepth)
  35425. uniform sampler2D depthTexture;
  35426. uniform float nearPlane;
  35427. uniform float farPlane;
  35428. uniform vec2 resolution;
  35429. uniform vec2 viewportOffset;
  35430. uniform vec3 backColor;
  35431. uniform float occlusionDistance;
  35432. uniform float clipDistance;
  35433. uniform float maxClipFactor;
  35434. uniform float maxOcclusionFactor;
  35435. #endif
  35436. varying float vLineDistance;
  35437. #ifdef WORLD_UNITS
  35438. varying vec4 worldPos;
  35439. varying vec3 worldStart;
  35440. varying vec3 worldEnd;
  35441. #ifdef USE_DASH
  35442. varying vec2 vUv;
  35443. #endif
  35444. #else
  35445. varying vec2 vUv;
  35446. #endif
  35447. #include <common>
  35448. #include <color_pars_fragment>
  35449. #include <fog_pars_fragment>
  35450. #include <logdepthbuf_pars_fragment>
  35451. #include <clipping_planes_pars_fragment>
  35452. #if defined(GL_EXT_frag_depth) && defined(useDepth)
  35453. float convertToLinear(float zValue)
  35454. {
  35455. if(uUseOrthographicCamera){
  35456. return zValue*(farPlane-nearPlane)+nearPlane;
  35457. }else{
  35458. float z = zValue * 2.0 - 1.0;
  35459. return (2.0 * nearPlane * farPlane) / (farPlane + nearPlane - z * (farPlane - nearPlane));
  35460. }
  35461. }
  35462. #endif
  35463. vec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) {
  35464. float mua;
  35465. float mub;
  35466. vec3 p13 = p1 - p3;
  35467. vec3 p43 = p4 - p3;
  35468. vec3 p21 = p2 - p1;
  35469. float d1343 = dot( p13, p43 );
  35470. float d4321 = dot( p43, p21 );
  35471. float d1321 = dot( p13, p21 );
  35472. float d4343 = dot( p43, p43 );
  35473. float d2121 = dot( p21, p21 );
  35474. float denom = d2121 * d4343 - d4321 * d4321;
  35475. float numer = d1343 * d4321 - d1321 * d4343;
  35476. mua = numer / denom;
  35477. mua = clamp( mua, 0.0, 1.0 );
  35478. mub = ( d1343 + d4321 * ( mua ) ) / d4343;
  35479. mub = clamp( mub, 0.0, 1.0 );
  35480. return vec2( mua, mub );
  35481. }
  35482. void main() {
  35483. #include <clipping_planes_fragment>
  35484. /*#ifdef USE_DASH
  35485. if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps
  35486. if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX
  35487. #endif*/
  35488. #ifdef USE_DASH
  35489. if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps
  35490. bool unvisible = mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize;
  35491. //加
  35492. #ifdef DASH_with_depth
  35493. #else
  35494. if (unvisible) discard; // todo - FIX
  35495. #endif
  35496. #endif
  35497. float alpha = opacity;
  35498. #ifdef WORLD_UNITS
  35499. // Find the closest points on the view ray and the line segment
  35500. vec3 rayEnd = normalize( worldPos.xyz ) * 1e5;
  35501. vec3 lineDir = worldEnd - worldStart;
  35502. vec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd );
  35503. vec3 p1 = worldStart + lineDir * params.x;
  35504. vec3 p2 = rayEnd * params.y;
  35505. vec3 delta = p1 - p2;
  35506. float len = length( delta );
  35507. float norm = len / lineWidth;
  35508. #ifndef USE_DASH
  35509. #ifdef USE_ALPHA_TO_COVERAGE
  35510. float dnorm = fwidth( norm );
  35511. alpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm );
  35512. #else
  35513. if ( norm > 0.5 ) {
  35514. discard;
  35515. }
  35516. #endif
  35517. #endif
  35518. #else
  35519. #ifdef USE_ALPHA_TO_COVERAGE
  35520. // artifacts appear on some hardware if a derivative is taken within a conditional
  35521. float a = vUv.x;
  35522. float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;
  35523. float len2 = a * a + b * b;
  35524. float dlen = fwidth( len2 );
  35525. if ( abs( vUv.y ) > 1.0 ) {
  35526. alpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 );
  35527. }
  35528. #else
  35529. if ( abs( vUv.y ) > 1.0 ) {
  35530. float a = vUv.x;
  35531. float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;
  35532. float len2 = a * a + b * b;
  35533. if ( len2 > 1.0 ) discard;
  35534. }
  35535. #endif
  35536. #endif
  35537. vec4 diffuseColor = vec4( diffuse, alpha );
  35538. //加
  35539. #if defined(GL_EXT_frag_depth) && defined(useDepth)
  35540. float mixFactor = 0.0;
  35541. float clipFactor = 0.0;
  35542. float fragDepth = convertToLinear(gl_FragCoord.z);
  35543. //gl_FragCoord大小为 viewport client大小
  35544. vec2 depthTxtCoords = vec2(gl_FragCoord.x - viewportOffset.x, gl_FragCoord.y - viewportOffset.y) / resolution;
  35545. float textureDepth = convertToLinear(texture2D(depthTexture, depthTxtCoords).r);
  35546. float delta = fragDepth - textureDepth;
  35547. if (delta > 0.0)
  35548. {
  35549. mixFactor = clamp(delta / occlusionDistance, 0.0, maxOcclusionFactor);
  35550. clipFactor = clamp(delta / clipDistance, 0.0, maxClipFactor);
  35551. }
  35552. if (clipFactor == 1.0)
  35553. {
  35554. discard;
  35555. }
  35556. vec4 backColor_ = vec4(backColor, opacity); //vec4(0.8,0.8,0.8, 0.8*opacity);
  35557. #ifdef DASH_with_depth
  35558. // 只在被遮住的部分显示虚线, 所以若同时是虚线不可见部分和被遮住时, a为0
  35559. if(unvisible) backColor_.a = 0.0;
  35560. #endif
  35561. //vec4 diffuseColor = vec4(mix(diffuse, backColor_, mixFactor), opacity*(1.0 - clipFactor));
  35562. diffuseColor = mix(diffuseColor, backColor_ , mixFactor);
  35563. diffuseColor.a *= (1.0 - clipFactor);
  35564. #endif
  35565. #include <logdepthbuf_fragment>
  35566. #include <color_fragment>
  35567. //gl_FragColor = vec4( diffuseColor.rgb, alpha );
  35568. gl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a );
  35569. #include <tonemapping_fragment>
  35570. #include <encodings_fragment>
  35571. #include <fog_fragment>
  35572. #include <premultiplied_alpha_fragment>
  35573. }
  35574. `
  35575. };
  35576. class LineMaterial extends ShaderMaterial {
  35577. constructor( parameters ) {
  35578. super( {
  35579. type: 'LineMaterial',
  35580. uniforms: UniformsUtils.clone( ShaderLib[ 'line' ].uniforms ),
  35581. vertexShader: ShaderLib[ 'line' ].vertexShader,
  35582. fragmentShader: ShaderLib[ 'line' ].fragmentShader,
  35583. clipping: true // required for clipping support
  35584. } );
  35585. this.isLineMaterial = true;
  35586. this.lineWidth_ = 0;
  35587. this.supportExtDepth = parameters.supportExtDepth;
  35588. this.depthTestWhenPick = false; //pick时是否识别点云等
  35589. if(parameters.color){
  35590. this.color = new Color(parameters.color);
  35591. }
  35592. if(parameters.backColor){
  35593. this.uniforms.backColor.value = new Color(parameters.backColor);
  35594. }
  35595. if(parameters.clipDistance){
  35596. this.uniforms.clipDistance.value = parameters.clipDistance;
  35597. }
  35598. if(parameters.occlusionDistance){
  35599. this.uniforms.occlusionDistance.value = parameters.occlusionDistance;
  35600. }
  35601. if(parameters.maxClipFactor){
  35602. this.uniforms.maxClipFactor.value = parameters.maxClipFactor;
  35603. }
  35604. Object.defineProperties( this, {
  35605. color: {
  35606. enumerable: true,
  35607. get: function () {
  35608. return this.uniforms.diffuse.value;
  35609. },
  35610. set: function ( value ) {
  35611. this.uniforms.diffuse.value = value;
  35612. }
  35613. },
  35614. worldUnits: {
  35615. enumerable: true,
  35616. get: function () {
  35617. return 'WORLD_UNITS' in this.defines;
  35618. },
  35619. set: function ( value ) {
  35620. if ( value === true ) {
  35621. this.defines.WORLD_UNITS = '';
  35622. } else {
  35623. delete this.defines.WORLD_UNITS;
  35624. }
  35625. }
  35626. },
  35627. lineWidth: {
  35628. enumerable: true,
  35629. get: function () {
  35630. return this.lineWidth_;//this.uniforms.lineWidth.value;
  35631. },
  35632. set: function ( value ) {
  35633. this.uniforms.lineWidth.value = value * window.devicePixelRatio;
  35634. this.lineWidth_ = value;
  35635. }
  35636. },
  35637. dashed: {
  35638. enumerable: true,
  35639. get: function () {
  35640. return Boolean( 'USE_DASH' in this.defines );
  35641. },
  35642. set( value ) {
  35643. if ( Boolean( value ) !== Boolean( 'USE_DASH' in this.defines ) ) {
  35644. this.needsUpdate = true;
  35645. }
  35646. if ( value === true ) {
  35647. this.defines.USE_DASH = '';
  35648. } else {
  35649. delete this.defines.USE_DASH;
  35650. }
  35651. }
  35652. },
  35653. dashScale: {
  35654. enumerable: true,
  35655. get: function () {
  35656. return this.uniforms.dashScale.value;
  35657. },
  35658. set: function ( value ) {
  35659. this.uniforms.dashScale.value = value;
  35660. }
  35661. },
  35662. dashSize: {
  35663. enumerable: true,
  35664. get: function () {
  35665. return this.uniforms.dashSize.value;
  35666. },
  35667. set: function ( value ) {
  35668. this.uniforms.dashSize.value = value;
  35669. }
  35670. },
  35671. dashOffset: {
  35672. enumerable: true,
  35673. get: function () {
  35674. return this.uniforms.dashOffset.value;
  35675. },
  35676. set: function ( value ) {
  35677. this.uniforms.dashOffset.value = value;
  35678. }
  35679. },
  35680. gapSize: {
  35681. enumerable: true,
  35682. get: function () {
  35683. return this.uniforms.gapSize.value;
  35684. },
  35685. set: function ( value ) {
  35686. this.uniforms.gapSize.value = value;
  35687. }
  35688. },
  35689. opacity: {
  35690. enumerable: true,
  35691. get: function () {
  35692. return this.uniforms.opacity.value;
  35693. },
  35694. set: function ( value ) {
  35695. this.uniforms.opacity.value = value;
  35696. }
  35697. },
  35698. resolution: {
  35699. enumerable: true,
  35700. get: function () {
  35701. return this.uniforms.resolution.value;
  35702. },
  35703. set: function ( value ) {
  35704. this.uniforms.resolution.value.copy( value );
  35705. }
  35706. },
  35707. alphaToCoverage: {
  35708. enumerable: true,
  35709. get: function () {
  35710. return Boolean( 'USE_ALPHA_TO_COVERAGE' in this.defines );
  35711. },
  35712. set: function ( value ) {
  35713. if ( Boolean( value ) !== Boolean( 'USE_ALPHA_TO_COVERAGE' in this.defines ) ) {
  35714. this.needsUpdate = true;
  35715. }
  35716. if ( value === true ) {
  35717. this.defines.USE_ALPHA_TO_COVERAGE = '';
  35718. this.extensions.derivatives = true;
  35719. } else {
  35720. delete this.defines.USE_ALPHA_TO_COVERAGE;
  35721. this.extensions.derivatives = false;
  35722. }
  35723. }
  35724. },
  35725. dashWithDepth:{//add
  35726. enumerable: true,
  35727. get: function () {
  35728. return 'DASH_with_depth' in this.defines
  35729. },
  35730. set: function ( value ) {
  35731. value = value && !!this.supportExtDepth;
  35732. if(value != this.dashWithDepth){
  35733. if(value){
  35734. this.defines.DASH_with_depth = '';
  35735. }else {
  35736. delete this.defines.DASH_with_depth;
  35737. }
  35738. this.needsUpdate = true;
  35739. }
  35740. }
  35741. },
  35742. } );
  35743. this.events = {
  35744. setSize:(e)=>{//如果出现横条状的异常,往往是viewportOffset出错 //地图不需要
  35745. let viewport = e.viewport;
  35746. this.uniforms.resolution.value.copy(viewport.resolution2);
  35747. this.uniforms.devicePixelRatio.value = window.devicePixelRatio;
  35748. this.lineWidth = this.lineWidth_; //update
  35749. if(!this.useDepth /* || !e.viewport.camera.isPerspectiveCamera */|| !e.viewport)return
  35750. let viewportOffset = viewport.offset || new THREE.Vector2();
  35751. this.uniforms.viewportOffset.value.copy(viewportOffset);
  35752. },
  35753. render:(e)=>{//before render 如果有大于两个viewport的话,不同viewport用不同的depthTex
  35754. this.updateDepthParams(e);
  35755. }
  35756. };
  35757. let viewer = parameters.viewer || window.viewer;
  35758. this.setValues( parameters );
  35759. let viewport = viewer.viewports[0];
  35760. this.events.setSize({viewport});
  35761. viewer.addEventListener('resize', this.events.setSize);
  35762. }
  35763. get useDepth(){
  35764. return this.useDepth_
  35765. }
  35766. set useDepth(value){
  35767. value = value && this.supportExtDepth; //如果不支持 EXT_DEPTH 的话会失效
  35768. if(this.useDepth_ != value){
  35769. this.setRealDepth(value);
  35770. this.useDepth_ = value;
  35771. if(value){
  35772. viewer.addEventListener("render.begin", this.events.render);
  35773. this.events.setSize( {viewport:viewer.mainViewport} );
  35774. this.updateDepthParams();
  35775. }else {
  35776. viewer.removeEventListener("render.begin", this.events.render);
  35777. }
  35778. }
  35779. }
  35780. setRealDepth(useDepth){//确实使用到depthTex
  35781. if(this.realUseDepth != useDepth){
  35782. if(useDepth ){
  35783. this.defines.useDepth = '';
  35784. }else {
  35785. delete this.defines.useDepth;
  35786. }
  35787. this.realUseDepth = useDepth;
  35788. if(this.autoDepthTest)this.depthWrite = this.depthTest = !useDepth; //如果useDepth = false,使用原始的depthTest
  35789. this.needsUpdate = true;
  35790. }
  35791. }
  35792. updateDepthParams(e={}){
  35793. var viewport = e.viewport || viewer.mainViewport;
  35794. var camera = viewport.camera;
  35795. let hasDepth = this.useDepth/* && camera.isPerspectiveCamera */ &&
  35796. (Potree.settings.pointEnableRT || Potree.settings.displayMode == 'showPanos' || viewer.useEDL);
  35797. this.setRealDepth(hasDepth);
  35798. if(hasDepth){
  35799. this.uniforms.depthTexture.value = viewer.getPRenderer().getRtEDL(viewport).depthTexture; //其实只赋值一次就行
  35800. this.uniforms.nearPlane.value = camera.near;
  35801. this.uniforms.farPlane.value = camera.far;
  35802. }
  35803. this.uniforms.uUseOrthographicCamera.value = !camera.isPerspectiveCamera;
  35804. }
  35805. }
  35806. const _start$2 = new Vector3();
  35807. const _end$2 = new Vector3();
  35808. const _start4 = new Vector4();
  35809. const _end4 = new Vector4();
  35810. const _ssOrigin = new Vector4();
  35811. const _ssOrigin3 = new Vector3();
  35812. const _mvMatrix = new Matrix4();
  35813. const _line = new Line3();
  35814. const _closestPoint = new Vector3();
  35815. const _box$5 = new Box3();
  35816. const _sphere$4 = new Sphere();
  35817. const _clipToWorldVector = new Vector4();
  35818. let _ray$3, _instanceStart, _instanceEnd, _lineWidth;
  35819. // Returns the margin required to expand by in world space given the distance from the camera,
  35820. // line width, resolution, and camera projection
  35821. function getWorldSpaceHalfWidth( camera, distance, resolution ) {
  35822. // transform into clip space, adjust the x and y values by the pixel width offset, then
  35823. // transform back into world space to get world offset. Note clip space is [-1, 1] so full
  35824. // width does not need to be halved.
  35825. _clipToWorldVector.set( 0, 0, - distance, 1.0 ).applyMatrix4( camera.projectionMatrix );
  35826. _clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w );
  35827. _clipToWorldVector.x = _lineWidth / resolution.width;
  35828. _clipToWorldVector.y = _lineWidth / resolution.height;
  35829. _clipToWorldVector.applyMatrix4( camera.projectionMatrixInverse );
  35830. _clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w );
  35831. return Math.abs( Math.max( _clipToWorldVector.x, _clipToWorldVector.y ) );
  35832. }
  35833. function raycastWorldUnits( lineSegments, intersects ) {
  35834. for ( let i = 0, l = _instanceStart.count; i < l; i ++ ) {
  35835. _line.start.fromBufferAttribute( _instanceStart, i );
  35836. _line.end.fromBufferAttribute( _instanceEnd, i );
  35837. const pointOnLine = new Vector3();
  35838. const point = new Vector3();
  35839. _ray$3.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
  35840. const isInside = point.distanceTo( pointOnLine ) < _lineWidth * 0.5;
  35841. if ( isInside ) {
  35842. intersects.push( {
  35843. point,
  35844. pointOnLine,
  35845. distance: _ray$3.origin.distanceTo( point ),
  35846. object: lineSegments,
  35847. face: null,
  35848. faceIndex: i,
  35849. uv: null,
  35850. uv2: null,
  35851. } );
  35852. }
  35853. }
  35854. }
  35855. function raycastScreenSpace( lineSegments, camera, intersects ) {
  35856. const projectionMatrix = camera.projectionMatrix;
  35857. const material = lineSegments.material;
  35858. const resolution = material.resolution;
  35859. const matrixWorld = lineSegments.matrixWorld;
  35860. const geometry = lineSegments.geometry;
  35861. const instanceStart = geometry.attributes.instanceStart;
  35862. const instanceEnd = geometry.attributes.instanceEnd;
  35863. const near = - camera.near;
  35864. //
  35865. // pick a point 1 unit out along the ray to avoid the ray origin
  35866. // sitting at the camera origin which will cause "w" to be 0 when
  35867. // applying the projection matrix.
  35868. _ray$3.at( 1, _ssOrigin );
  35869. // ndc space [ - 1.0, 1.0 ]
  35870. _ssOrigin.w = 1;
  35871. _ssOrigin.applyMatrix4( camera.matrixWorldInverse );
  35872. _ssOrigin.applyMatrix4( projectionMatrix );
  35873. _ssOrigin.multiplyScalar( 1 / _ssOrigin.w );
  35874. // screen space
  35875. _ssOrigin.x *= resolution.x / 2;
  35876. _ssOrigin.y *= resolution.y / 2;
  35877. _ssOrigin.z = 0;
  35878. _ssOrigin3.copy( _ssOrigin );
  35879. _mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld );
  35880. for ( let i = 0, l = instanceStart.count; i < l; i ++ ) {
  35881. _start4.fromBufferAttribute( instanceStart, i );
  35882. _end4.fromBufferAttribute( instanceEnd, i );
  35883. _start4.w = 1;
  35884. _end4.w = 1;
  35885. // camera space
  35886. _start4.applyMatrix4( _mvMatrix );
  35887. _end4.applyMatrix4( _mvMatrix );
  35888. // skip the segment if it's entirely behind the camera
  35889. const isBehindCameraNear = _start4.z > near && _end4.z > near;
  35890. if ( isBehindCameraNear ) {
  35891. continue;
  35892. }
  35893. // trim the segment if it extends behind camera near
  35894. if ( _start4.z > near ) {
  35895. const deltaDist = _start4.z - _end4.z;
  35896. const t = ( _start4.z - near ) / deltaDist;
  35897. _start4.lerp( _end4, t );
  35898. } else if ( _end4.z > near ) {
  35899. const deltaDist = _end4.z - _start4.z;
  35900. const t = ( _end4.z - near ) / deltaDist;
  35901. _end4.lerp( _start4, t );
  35902. }
  35903. // clip space
  35904. _start4.applyMatrix4( projectionMatrix );
  35905. _end4.applyMatrix4( projectionMatrix );
  35906. // ndc space [ - 1.0, 1.0 ]
  35907. _start4.multiplyScalar( 1 / _start4.w );
  35908. _end4.multiplyScalar( 1 / _end4.w );
  35909. // screen space
  35910. _start4.x *= resolution.x / 2;
  35911. _start4.y *= resolution.y / 2;
  35912. _end4.x *= resolution.x / 2;
  35913. _end4.y *= resolution.y / 2;
  35914. // create 2d segment
  35915. _line.start.copy( _start4 );
  35916. _line.start.z = 0;
  35917. _line.end.copy( _end4 );
  35918. _line.end.z = 0;
  35919. // get closest point on ray to segment
  35920. const param = _line.closestPointToPointParameter( _ssOrigin3, true );
  35921. _line.at( param, _closestPoint );
  35922. // check if the intersection point is within clip space
  35923. const zPos = MathUtils$1.lerp( _start4.z, _end4.z, param );
  35924. const isInClipSpace = zPos >= - 1 && zPos <= 1;
  35925. const isInside = _ssOrigin3.distanceTo( _closestPoint ) < _lineWidth * 0.5;
  35926. if ( isInClipSpace && isInside ) {
  35927. _line.start.fromBufferAttribute( instanceStart, i );
  35928. _line.end.fromBufferAttribute( instanceEnd, i );
  35929. _line.start.applyMatrix4( matrixWorld );
  35930. _line.end.applyMatrix4( matrixWorld );
  35931. const pointOnLine = new Vector3();
  35932. const point = new Vector3();
  35933. _ray$3.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
  35934. intersects.push( {
  35935. point: point,
  35936. pointOnLine: pointOnLine,
  35937. distance: _ray$3.origin.distanceTo( point ),
  35938. object: lineSegments,
  35939. face: null,
  35940. faceIndex: i,
  35941. uv: null,
  35942. uv2: null,
  35943. } );
  35944. }
  35945. }
  35946. }
  35947. class LineSegments2 extends Mesh {
  35948. constructor( geometry = new LineSegmentsGeometry(), material = new LineMaterial( { color: Math.random() * 0xffffff } ) ) {
  35949. super( geometry, material );
  35950. this.isLineSegments2 = true;
  35951. this.type = 'LineSegments2';
  35952. }
  35953. // for backwards-compatibility, but could be a method of LineSegmentsGeometry...
  35954. computeLineDistances() {
  35955. const geometry = this.geometry;
  35956. const instanceStart = geometry.attributes.instanceStart;
  35957. const instanceEnd = geometry.attributes.instanceEnd;
  35958. const lineDistances = new Float32Array( 2 * instanceStart.count );
  35959. for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) {
  35960. _start$2.fromBufferAttribute( instanceStart, i );
  35961. _end$2.fromBufferAttribute( instanceEnd, i );
  35962. lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ];
  35963. lineDistances[ j + 1 ] = lineDistances[ j ] + _start$2.distanceTo( _end$2 );
  35964. }
  35965. const instanceDistanceBuffer = new InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1
  35966. geometry.setAttribute( 'instanceDistanceStart', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0
  35967. geometry.setAttribute( 'instanceDistanceEnd', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1
  35968. return this;
  35969. }
  35970. raycast( raycaster, intersects ) {
  35971. const worldUnits = this.material.worldUnits;
  35972. const camera = raycaster.camera;
  35973. if ( camera === null && ! worldUnits ) {
  35974. console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2 while worldUnits is set to false.' );
  35975. }
  35976. const threshold = ( raycaster.params.Line2 !== undefined ) ? raycaster.params.Line2.threshold || 0 : 0;
  35977. _ray$3 = raycaster.ray;
  35978. const matrixWorld = this.matrixWorld;
  35979. const geometry = this.geometry;
  35980. const material = this.material;
  35981. _lineWidth = material.lineWidth + threshold;
  35982. _instanceStart = geometry.attributes.instanceStart;
  35983. _instanceEnd = geometry.attributes.instanceEnd;
  35984. // check if we intersect the sphere bounds
  35985. if ( geometry.boundingSphere === null ) {
  35986. geometry.computeBoundingSphere();
  35987. }
  35988. _sphere$4.copy( geometry.boundingSphere ).applyMatrix4( matrixWorld );
  35989. // increase the sphere bounds by the worst case line screen space width
  35990. let sphereMargin;
  35991. if ( worldUnits ) {
  35992. sphereMargin = _lineWidth * 0.5;
  35993. } else {
  35994. const distanceToSphere = Math.max( camera.near, _sphere$4.distanceToPoint( _ray$3.origin ) );
  35995. sphereMargin = getWorldSpaceHalfWidth( camera, distanceToSphere, material.resolution );
  35996. }
  35997. _sphere$4.radius += sphereMargin;
  35998. if ( _ray$3.intersectsSphere( _sphere$4 ) === false ) {
  35999. return;
  36000. }
  36001. // check if we intersect the box bounds
  36002. if ( geometry.boundingBox === null ) {
  36003. geometry.computeBoundingBox();
  36004. }
  36005. _box$5.copy( geometry.boundingBox ).applyMatrix4( matrixWorld );
  36006. // increase the box bounds by the worst case line width
  36007. let boxMargin;
  36008. if ( worldUnits ) {
  36009. boxMargin = _lineWidth * 0.5;
  36010. } else {
  36011. const distanceToBox = Math.max( camera.near, _box$5.distanceToPoint( _ray$3.origin ) );
  36012. boxMargin = getWorldSpaceHalfWidth( camera, distanceToBox, material.resolution );
  36013. }
  36014. _box$5.expandByScalar( boxMargin );
  36015. if ( _ray$3.intersectsBox( _box$5 ) === false ) {
  36016. return;
  36017. }
  36018. if ( worldUnits ) {
  36019. raycastWorldUnits( this, intersects );
  36020. } else {
  36021. raycastScreenSpace( this, camera, intersects );
  36022. }
  36023. }
  36024. }
  36025. class LineGeometry extends LineSegmentsGeometry {
  36026. constructor() {
  36027. super();
  36028. this.isLineGeometry = true;
  36029. this.type = 'LineGeometry';
  36030. }
  36031. setPositions( array ) {//见potree.shim.js
  36032. // converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format
  36033. const length = array.length - 3;
  36034. const points = new Float32Array( 2 * length );
  36035. for ( let i = 0; i < length; i += 3 ) {
  36036. points[ 2 * i ] = array[ i ];
  36037. points[ 2 * i + 1 ] = array[ i + 1 ];
  36038. points[ 2 * i + 2 ] = array[ i + 2 ];
  36039. points[ 2 * i + 3 ] = array[ i + 3 ];
  36040. points[ 2 * i + 4 ] = array[ i + 4 ];
  36041. points[ 2 * i + 5 ] = array[ i + 5 ];
  36042. }
  36043. super.setPositions( points );
  36044. return this;
  36045. }
  36046. setColors( array ) {
  36047. // converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format
  36048. const length = array.length - 3;
  36049. const colors = new Float32Array( 2 * length );
  36050. for ( let i = 0; i < length; i += 3 ) {
  36051. colors[ 2 * i ] = array[ i ];
  36052. colors[ 2 * i + 1 ] = array[ i + 1 ];
  36053. colors[ 2 * i + 2 ] = array[ i + 2 ];
  36054. colors[ 2 * i + 3 ] = array[ i + 3 ];
  36055. colors[ 2 * i + 4 ] = array[ i + 4 ];
  36056. colors[ 2 * i + 5 ] = array[ i + 5 ];
  36057. }
  36058. super.setColors( colors );
  36059. return this;
  36060. }
  36061. fromLine( line ) {
  36062. const geometry = line.geometry;
  36063. this.setPositions( geometry.attributes.position.array ); // assumes non-indexed
  36064. // set colors, maybe
  36065. return this;
  36066. }
  36067. }
  36068. class Line2 extends LineSegments2 {
  36069. constructor( geometry = new LineGeometry(), material = new LineMaterial( { color: Math.random() * 0xffffff } ) ) {
  36070. super( geometry, material );
  36071. this.isLine2 = true;
  36072. this.type = 'Line2';
  36073. }
  36074. }
  36075. //old
  36076. function createHeightLine(){
  36077. let lineGeometry = new LineGeometry();
  36078. lineGeometry.setPositions([
  36079. 0, 0, 0,
  36080. 0, 0, 0,
  36081. ]);
  36082. let lineMaterial = new LineMaterial({
  36083. color: 0x00ff00,
  36084. dashSize: 5,
  36085. gapSize: 2,
  36086. linewidth: 2,
  36087. resolution: new Vector2(1000, 1000),
  36088. });
  36089. lineMaterial.depthTest = false;
  36090. const heightEdge = new Line2(lineGeometry, lineMaterial);
  36091. heightEdge.visible = false;
  36092. //this.add(this.heightEdge);
  36093. return heightEdge;
  36094. }
  36095. function createHeightLabel(){
  36096. const heightLabel = new TextSprite$1('');
  36097. heightLabel.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  36098. heightLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  36099. heightLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  36100. heightLabel.fontsize = 16;
  36101. heightLabel.material.depthTest = false;
  36102. heightLabel.material.opacity = 1;
  36103. heightLabel.visible = false;
  36104. return heightLabel;
  36105. }
  36106. function createAreaLabel(){
  36107. const areaLabel = new TextSprite$1('');
  36108. areaLabel.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  36109. areaLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  36110. areaLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  36111. areaLabel.fontsize = 16;
  36112. areaLabel.material.depthTest = false;
  36113. areaLabel.material.opacity = 1;
  36114. areaLabel.visible = false;
  36115. return areaLabel;
  36116. }
  36117. function createCircleRadiusLabel(){
  36118. const circleRadiusLabel = new TextSprite$1("");
  36119. circleRadiusLabel.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  36120. circleRadiusLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  36121. circleRadiusLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  36122. circleRadiusLabel.fontsize = 16;
  36123. circleRadiusLabel.material.depthTest = false;
  36124. circleRadiusLabel.material.opacity = 1;
  36125. circleRadiusLabel.visible = false;
  36126. return circleRadiusLabel;
  36127. }
  36128. function createCircleRadiusLine(){
  36129. const lineGeometry = new LineGeometry();
  36130. lineGeometry.setPositions([
  36131. 0, 0, 0,
  36132. 0, 0, 0,
  36133. ]);
  36134. const lineMaterial = new LineMaterial({
  36135. color: 0xff0000,
  36136. linewidth: 2,
  36137. resolution: new Vector2(1000, 1000),
  36138. gapSize: 1,
  36139. dashed: true,
  36140. });
  36141. lineMaterial.depthTest = false;
  36142. const circleRadiusLine = new Line2(lineGeometry, lineMaterial);
  36143. circleRadiusLine.visible = false;
  36144. return circleRadiusLine;
  36145. }
  36146. function createCircleLine(){
  36147. const coordinates = [];
  36148. let n = 128;
  36149. for(let i = 0; i <= n; i++){
  36150. let u0 = 2 * Math.PI * (i / n);
  36151. let u1 = 2 * Math.PI * (i + 1) / n;
  36152. let p0 = new Vector3(
  36153. Math.cos(u0),
  36154. Math.sin(u0),
  36155. 0
  36156. );
  36157. let p1 = new Vector3(
  36158. Math.cos(u1),
  36159. Math.sin(u1),
  36160. 0
  36161. );
  36162. coordinates.push(
  36163. ...p0.toArray(),
  36164. ...p1.toArray(),
  36165. );
  36166. }
  36167. const geometry = new LineGeometry();
  36168. geometry.setPositions(coordinates);
  36169. const material = new LineMaterial({
  36170. color: 0xff0000,
  36171. dashSize: 5,
  36172. gapSize: 2,
  36173. linewidth: 2,
  36174. resolution: new Vector2(1000, 1000),
  36175. });
  36176. material.depthTest = false;
  36177. const circleLine = new Line2(geometry, material);
  36178. circleLine.visible = false;
  36179. circleLine.computeLineDistances();
  36180. return circleLine;
  36181. }
  36182. function createCircleCenter(){
  36183. const sg = new SphereGeometry(1, 32, 32);
  36184. const sm = new MeshNormalMaterial();
  36185. const circleCenter = new Mesh(sg, sm);
  36186. circleCenter.visible = false;
  36187. return circleCenter;
  36188. }
  36189. function createLine(){
  36190. const geometry = new LineGeometry();
  36191. geometry.setPositions([
  36192. 0, 0, 0,
  36193. 0, 0, 0,
  36194. ]);
  36195. const material = new LineMaterial({
  36196. color: 0xff0000,
  36197. linewidth: 2,
  36198. resolution: new Vector2(1000, 1000),
  36199. gapSize: 1,
  36200. dashed: true,
  36201. });
  36202. material.depthTest = false;
  36203. const line = new Line2(geometry, material);
  36204. return line;
  36205. }
  36206. function createCircle(){
  36207. const coordinates = [];
  36208. let n = 128;
  36209. for(let i = 0; i <= n; i++){
  36210. let u0 = 2 * Math.PI * (i / n);
  36211. let u1 = 2 * Math.PI * (i + 1) / n;
  36212. let p0 = new Vector3(
  36213. Math.cos(u0),
  36214. Math.sin(u0),
  36215. 0
  36216. );
  36217. let p1 = new Vector3(
  36218. Math.cos(u1),
  36219. Math.sin(u1),
  36220. 0
  36221. );
  36222. coordinates.push(
  36223. ...p0.toArray(),
  36224. ...p1.toArray(),
  36225. );
  36226. }
  36227. const geometry = new LineGeometry();
  36228. geometry.setPositions(coordinates);
  36229. const material = new LineMaterial({
  36230. color: 0xff0000,
  36231. dashSize: 5,
  36232. gapSize: 2,
  36233. linewidth: 2,
  36234. resolution: new Vector2(1000, 1000),
  36235. });
  36236. material.depthTest = false;
  36237. const line = new Line2(geometry, material);
  36238. line.computeLineDistances();
  36239. return line;
  36240. }
  36241. function createAzimuth(){
  36242. const azimuth = {
  36243. label: null,
  36244. center: null,
  36245. target: null,
  36246. north: null,
  36247. centerToNorth: null,
  36248. centerToTarget: null,
  36249. centerToTargetground: null,
  36250. targetgroundToTarget: null,
  36251. circle: null,
  36252. node: null,
  36253. };
  36254. const sg = new SphereGeometry(1, 32, 32);
  36255. const sm = new MeshNormalMaterial();
  36256. {
  36257. const label = new TextSprite$1("");
  36258. label.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  36259. label.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  36260. label.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  36261. label.fontsize = 16;
  36262. label.material.depthTest = false;
  36263. label.material.opacity = 1;
  36264. azimuth.label = label;
  36265. }
  36266. azimuth.center = new Mesh(sg, sm);
  36267. azimuth.target = new Mesh(sg, sm);
  36268. azimuth.north = new Mesh(sg, sm);
  36269. azimuth.centerToNorth = createLine();
  36270. azimuth.centerToTarget = createLine();
  36271. azimuth.centerToTargetground = createLine();
  36272. azimuth.targetgroundToTarget = createLine();
  36273. azimuth.circle = createCircle();
  36274. azimuth.node = new Object3D();
  36275. azimuth.node.add(
  36276. azimuth.centerToNorth,
  36277. azimuth.centerToTarget,
  36278. azimuth.centerToTargetground,
  36279. azimuth.targetgroundToTarget,
  36280. azimuth.circle,
  36281. azimuth.label,
  36282. azimuth.center,
  36283. azimuth.target,
  36284. azimuth.north,
  36285. );
  36286. return azimuth;
  36287. }
  36288. class Measure extends Object3D {
  36289. constructor () {
  36290. super();
  36291. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  36292. this.name = 'Measure_' + this.constructor.counter;
  36293. this.points = [];
  36294. this._showDistances = true;
  36295. this._showCoordinates = false;
  36296. this._showArea = false;
  36297. this._closed = true;
  36298. this._showAngles = false;
  36299. this._showCircle = false;
  36300. this._showHeight = false;
  36301. this._showEdges = true;
  36302. this._showAzimuth = false;
  36303. this.maxMarkers = Number.MAX_SAFE_INTEGER;
  36304. this.sphereGeometry = new SphereGeometry(0.4, 10, 10);
  36305. this.color = new Color(0xff0000);
  36306. this.spheres = [];
  36307. this.edges = [];
  36308. this.sphereLabels = [];
  36309. this.edgeLabels = [];
  36310. this.angleLabels = [];
  36311. this.coordinateLabels = [];
  36312. this.heightEdge = createHeightLine();
  36313. this.heightLabel = createHeightLabel();
  36314. this.areaLabel = createAreaLabel();
  36315. this.circleRadiusLabel = createCircleRadiusLabel();
  36316. this.circleRadiusLine = createCircleRadiusLine();
  36317. this.circleLine = createCircleLine();
  36318. this.circleCenter = createCircleCenter();
  36319. this.azimuth = createAzimuth();
  36320. this.add(this.heightEdge);
  36321. this.add(this.heightLabel);
  36322. this.add(this.areaLabel);
  36323. this.add(this.circleRadiusLabel);
  36324. this.add(this.circleRadiusLine);
  36325. this.add(this.circleLine);
  36326. this.add(this.circleCenter);
  36327. this.add(this.azimuth.node);
  36328. }
  36329. createSphereMaterial () {
  36330. let sphereMaterial = new MeshLambertMaterial({
  36331. //shading: THREE.SmoothShading,
  36332. color: this.color,
  36333. depthTest: false,
  36334. depthWrite: false}
  36335. );
  36336. return sphereMaterial;
  36337. };
  36338. addMarker (point) {
  36339. if (point.x != null) {
  36340. point = {position: point};
  36341. }else if(point instanceof Array){
  36342. point = {position: new Vector3(...point)};
  36343. }
  36344. this.points.push(point);
  36345. // sphere
  36346. let sphere = new Mesh(this.sphereGeometry, this.createSphereMaterial());
  36347. this.add(sphere);
  36348. this.spheres.push(sphere);
  36349. { // edges
  36350. let lineGeometry = new LineGeometry();
  36351. lineGeometry.setPositions( [
  36352. 0, 0, 0,
  36353. 0, 0, 0,
  36354. ]);
  36355. let lineMaterial = new LineMaterial({
  36356. color: 0xff0000,
  36357. linewidth: 2,
  36358. resolution: new Vector2(1000, 1000),
  36359. });
  36360. lineMaterial.depthTest = false;
  36361. let edge = new Line2(lineGeometry, lineMaterial);
  36362. edge.visible = true;
  36363. this.add(edge);
  36364. this.edges.push(edge);
  36365. }
  36366. { // edge labels
  36367. let edgeLabel = new TextSprite$1();
  36368. edgeLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  36369. edgeLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  36370. edgeLabel.material.depthTest = false;
  36371. edgeLabel.visible = false;
  36372. edgeLabel.fontsize = 16;
  36373. this.edgeLabels.push(edgeLabel);
  36374. this.add(edgeLabel);
  36375. }
  36376. { // angle labels
  36377. let angleLabel = new TextSprite$1();
  36378. angleLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  36379. angleLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  36380. angleLabel.fontsize = 16;
  36381. angleLabel.material.depthTest = false;
  36382. angleLabel.material.opacity = 1;
  36383. angleLabel.visible = false;
  36384. this.angleLabels.push(angleLabel);
  36385. this.add(angleLabel);
  36386. }
  36387. { // coordinate labels
  36388. let coordinateLabel = new TextSprite$1();
  36389. coordinateLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  36390. coordinateLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  36391. coordinateLabel.fontsize = 16;
  36392. coordinateLabel.material.depthTest = false;
  36393. coordinateLabel.material.opacity = 1;
  36394. coordinateLabel.visible = false;
  36395. this.coordinateLabels.push(coordinateLabel);
  36396. this.add(coordinateLabel);
  36397. }
  36398. { // Event Listeners
  36399. let drag = (e) => {
  36400. let I = Utils.getMousePointCloudIntersection(
  36401. e.drag.end,
  36402. e.viewer.scene.getActiveCamera(),
  36403. e.viewer,
  36404. e.viewer.scene.pointclouds,
  36405. {pickClipped: true});
  36406. if (I) {
  36407. let i = this.spheres.indexOf(e.drag.object);
  36408. if (i !== -1) {
  36409. let point = this.points[i];
  36410. // loop through current keys and cleanup ones that will be orphaned
  36411. for (let key of Object.keys(point)) {
  36412. if (!I.point[key]) {
  36413. delete point[key];
  36414. }
  36415. }
  36416. for (let key of Object.keys(I.point).filter(e => e !== 'position')) {
  36417. point[key] = I.point[key];
  36418. }
  36419. this.setPosition(i, I.location);
  36420. }
  36421. }
  36422. };
  36423. let drop = e => {
  36424. let i = this.spheres.indexOf(e.drag.object);
  36425. if (i !== -1) {
  36426. this.dispatchEvent({
  36427. 'type': 'marker_dropped',
  36428. 'measurement': this,
  36429. 'index': i
  36430. });
  36431. }
  36432. };
  36433. let mouseover = (e) => e.object.material.emissive.setHex(0x888888);
  36434. let mouseleave = (e) => e.object.material.emissive.setHex(0x000000);
  36435. sphere.addEventListener('drag', drag);
  36436. sphere.addEventListener('drop', drop);
  36437. sphere.addEventListener('mouseover', mouseover);
  36438. sphere.addEventListener('mouseleave', mouseleave);
  36439. }
  36440. let event = {
  36441. type: 'marker_added',
  36442. measurement: this,
  36443. sphere: sphere
  36444. };
  36445. this.dispatchEvent(event);
  36446. this.setMarker(this.points.length - 1, point);
  36447. };
  36448. removeMarker (index) {
  36449. this.points.splice(index, 1);
  36450. this.remove(this.spheres[index]);
  36451. let edgeIndex = (index === 0) ? 0 : (index - 1);
  36452. this.remove(this.edges[edgeIndex]);
  36453. this.edges.splice(edgeIndex, 1);
  36454. this.remove(this.edgeLabels[edgeIndex]);
  36455. this.edgeLabels.splice(edgeIndex, 1);
  36456. this.coordinateLabels.splice(index, 1);
  36457. this.remove(this.angleLabels[index]);
  36458. this.angleLabels.splice(index, 1);
  36459. this.spheres.splice(index, 1);
  36460. this.update();
  36461. this.dispatchEvent({type: 'marker_removed', measurement: this});
  36462. };
  36463. setMarker (index, point) {
  36464. this.points[index] = point;
  36465. let event = {
  36466. type: 'marker_moved',
  36467. measure: this,
  36468. index: index,
  36469. position: point.position.clone()
  36470. };
  36471. this.dispatchEvent(event);
  36472. this.update();
  36473. }
  36474. setPosition (index, position) {
  36475. let point = this.points[index];
  36476. point.position.copy(position);
  36477. let event = {
  36478. type: 'marker_moved',
  36479. measure: this,
  36480. index: index,
  36481. position: position.clone()
  36482. };
  36483. this.dispatchEvent(event);
  36484. this.update();
  36485. };
  36486. getArea () {
  36487. let area = 0;
  36488. let j = this.points.length - 1;
  36489. for (let i = 0; i < this.points.length; i++) {
  36490. let p1 = this.points[i].position;
  36491. let p2 = this.points[j].position;
  36492. area += (p2.x + p1.x) * (p1.y - p2.y);
  36493. j = i;
  36494. }
  36495. return Math.abs(area / 2);
  36496. };
  36497. getTotalDistance () {
  36498. if (this.points.length === 0) {
  36499. return 0;
  36500. }
  36501. let distance = 0;
  36502. for (let i = 1; i < this.points.length; i++) {
  36503. let prev = this.points[i - 1].position;
  36504. let curr = this.points[i].position;
  36505. let d = prev.distanceTo(curr);
  36506. distance += d;
  36507. }
  36508. if (this.closed && this.points.length > 1) {
  36509. let first = this.points[0].position;
  36510. let last = this.points[this.points.length - 1].position;
  36511. let d = last.distanceTo(first);
  36512. distance += d;
  36513. }
  36514. return distance;
  36515. }
  36516. getAngleBetweenLines (cornerPoint, point1, point2) {
  36517. let v1 = new Vector3().subVectors(point1.position, cornerPoint.position);
  36518. let v2 = new Vector3().subVectors(point2.position, cornerPoint.position);
  36519. // avoid the error printed by threejs if denominator is 0
  36520. const denominator = Math.sqrt( v1.lengthSq() * v2.lengthSq() );
  36521. if(denominator === 0){
  36522. return 0;
  36523. }else {
  36524. return v1.angleTo(v2);
  36525. }
  36526. };
  36527. getAngle (index) {
  36528. if (this.points.length < 3 || index >= this.points.length) {
  36529. return 0;
  36530. }
  36531. let previous = (index === 0) ? this.points[this.points.length - 1] : this.points[index - 1];
  36532. let point = this.points[index];
  36533. let next = this.points[(index + 1) % (this.points.length)];
  36534. return this.getAngleBetweenLines(point, previous, next);
  36535. }
  36536. // updateAzimuth(){
  36537. // // if(this.points.length !== 2){
  36538. // // return;
  36539. // // }
  36540. // // const azimuth = this.azimuth;
  36541. // // const [p0, p1] = this.points;
  36542. // // const r = p0.position.distanceTo(p1.position);
  36543. // }
  36544. update () {
  36545. if (this.points.length === 0) {
  36546. return;
  36547. } else if (this.points.length === 1) {
  36548. let point = this.points[0];
  36549. let position = point.position;
  36550. this.spheres[0].position.copy(position);
  36551. { // coordinate labels
  36552. let coordinateLabel = this.coordinateLabels[0];
  36553. let msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
  36554. coordinateLabel.setText(msg);
  36555. coordinateLabel.visible = this.showCoordinates;
  36556. }
  36557. return;
  36558. }
  36559. let lastIndex = this.points.length - 1;
  36560. let centroid = new Vector3();
  36561. for (let i = 0; i <= lastIndex; i++) {
  36562. let point = this.points[i];
  36563. centroid.add(point.position);
  36564. }
  36565. centroid.divideScalar(this.points.length);
  36566. for (let i = 0; i <= lastIndex; i++) {
  36567. let index = i;
  36568. let nextIndex = (i + 1 > lastIndex) ? 0 : i + 1;
  36569. let previousIndex = (i === 0) ? lastIndex : i - 1;
  36570. let point = this.points[index];
  36571. let nextPoint = this.points[nextIndex];
  36572. let previousPoint = this.points[previousIndex];
  36573. let sphere = this.spheres[index];
  36574. // spheres
  36575. sphere.position.copy(point.position);
  36576. sphere.material.color = this.color;
  36577. { // edges
  36578. let edge = this.edges[index];
  36579. edge.material.color = this.color;
  36580. edge.position.copy(point.position);
  36581. edge.geometry.setPositions([
  36582. 0, 0, 0,
  36583. ...nextPoint.position.clone().sub(point.position).toArray(),
  36584. ]);
  36585. edge.geometry.verticesNeedUpdate = true;
  36586. edge.geometry.computeBoundingSphere();
  36587. edge.computeLineDistances();
  36588. edge.visible = index < lastIndex || this.closed;
  36589. if(!this.showEdges){
  36590. edge.visible = false;
  36591. }
  36592. }
  36593. { // edge labels
  36594. let edgeLabel = this.edgeLabels[i];
  36595. let center = new Vector3().add(point.position);
  36596. center.add(nextPoint.position);
  36597. center = center.multiplyScalar(0.5);
  36598. let distance = point.position.distanceTo(nextPoint.position);
  36599. edgeLabel.position.copy(center);
  36600. let suffix = "";
  36601. if(this.lengthUnit != null && this.lengthUnitDisplay != null){
  36602. distance = distance / this.lengthUnit.unitspermeter * this.lengthUnitDisplay.unitspermeter; //convert to meters then to the display unit
  36603. suffix = this.lengthUnitDisplay.code;
  36604. }
  36605. let txtLength = Utils.addCommas(distance.toFixed(2));
  36606. edgeLabel.setText(`${txtLength} ${suffix}`);
  36607. edgeLabel.visible = this.showDistances && (index < lastIndex || this.closed) && this.points.length >= 2 && distance > 0;
  36608. }
  36609. { // angle labels
  36610. let angleLabel = this.angleLabels[i];
  36611. let angle = this.getAngleBetweenLines(point, previousPoint, nextPoint);
  36612. let dir = nextPoint.position.clone().sub(previousPoint.position);
  36613. dir.multiplyScalar(0.5);
  36614. dir = previousPoint.position.clone().add(dir).sub(point.position).normalize();
  36615. let dist = Math.min(point.position.distanceTo(previousPoint.position), point.position.distanceTo(nextPoint.position));
  36616. dist = dist / 9;
  36617. let labelPos = point.position.clone().add(dir.multiplyScalar(dist));
  36618. angleLabel.position.copy(labelPos);
  36619. let msg = Utils.addCommas((angle * (180.0 / Math.PI)).toFixed(1)) + '\u00B0';
  36620. angleLabel.setText(msg);
  36621. angleLabel.visible = this.showAngles && (index < lastIndex || this.closed) && this.points.length >= 3 && angle > 0;
  36622. }
  36623. }
  36624. { // update height stuff
  36625. let heightEdge = this.heightEdge;
  36626. heightEdge.visible = this.showHeight;
  36627. this.heightLabel.visible = this.showHeight;
  36628. if (this.showHeight) {
  36629. let sorted = this.points.slice().sort((a, b) => a.position.z - b.position.z);
  36630. let lowPoint = sorted[0].position.clone();
  36631. let highPoint = sorted[sorted.length - 1].position.clone();
  36632. let min = lowPoint.z;
  36633. let max = highPoint.z;
  36634. let height = max - min;
  36635. let start = new Vector3(highPoint.x, highPoint.y, min);
  36636. let end = new Vector3(highPoint.x, highPoint.y, max);
  36637. heightEdge.position.copy(lowPoint);
  36638. heightEdge.geometry.setPositions([
  36639. 0, 0, 0,
  36640. ...start.clone().sub(lowPoint).toArray(),
  36641. ...start.clone().sub(lowPoint).toArray(),
  36642. ...end.clone().sub(lowPoint).toArray(),
  36643. ]);
  36644. heightEdge.geometry.verticesNeedUpdate = true;
  36645. // heightEdge.geometry.computeLineDistances();
  36646. // heightEdge.geometry.lineDistancesNeedUpdate = true;
  36647. heightEdge.geometry.computeBoundingSphere();
  36648. heightEdge.computeLineDistances();
  36649. // heightEdge.material.dashSize = height / 40;
  36650. // heightEdge.material.gapSize = height / 40;
  36651. let heightLabelPosition = start.clone().add(end).multiplyScalar(0.5);
  36652. this.heightLabel.position.copy(heightLabelPosition);
  36653. let suffix = "";
  36654. if(this.lengthUnit != null && this.lengthUnitDisplay != null){
  36655. height = height / this.lengthUnit.unitspermeter * this.lengthUnitDisplay.unitspermeter; //convert to meters then to the display unit
  36656. suffix = this.lengthUnitDisplay.code;
  36657. }
  36658. let txtHeight = Utils.addCommas(height.toFixed(2));
  36659. let msg = `${txtHeight} ${suffix}`;
  36660. this.heightLabel.setText(msg);
  36661. }
  36662. }
  36663. { // update circle stuff
  36664. const circleRadiusLabel = this.circleRadiusLabel;
  36665. const circleRadiusLine = this.circleRadiusLine;
  36666. const circleLine = this.circleLine;
  36667. const circleCenter = this.circleCenter;
  36668. const circleOkay = this.points.length === 3;
  36669. circleRadiusLabel.visible = this.showCircle && circleOkay;
  36670. circleRadiusLine.visible = this.showCircle && circleOkay;
  36671. circleLine.visible = this.showCircle && circleOkay;
  36672. circleCenter.visible = this.showCircle && circleOkay;
  36673. if(this.showCircle && circleOkay){
  36674. const A = this.points[0].position;
  36675. const B = this.points[1].position;
  36676. const C = this.points[2].position;
  36677. const AB = B.clone().sub(A);
  36678. const AC = C.clone().sub(A);
  36679. const N = AC.clone().cross(AB).normalize();
  36680. const center = Potree.Utils.computeCircleCenter(A, B, C);
  36681. const radius = center.distanceTo(A);
  36682. const scale = radius / 20;
  36683. circleCenter.position.copy(center);
  36684. circleCenter.scale.set(scale, scale, scale);
  36685. //circleRadiusLine.geometry.vertices[0].set(0, 0, 0);
  36686. //circleRadiusLine.geometry.vertices[1].copy(B.clone().sub(center));
  36687. circleRadiusLine.geometry.setPositions( [
  36688. 0, 0, 0,
  36689. ...B.clone().sub(center).toArray()
  36690. ] );
  36691. circleRadiusLine.geometry.verticesNeedUpdate = true;
  36692. circleRadiusLine.geometry.computeBoundingSphere();
  36693. circleRadiusLine.position.copy(center);
  36694. circleRadiusLine.computeLineDistances();
  36695. const target = center.clone().add(N);
  36696. circleLine.position.copy(center);
  36697. circleLine.scale.set(radius, radius, radius);
  36698. circleLine.lookAt(target);
  36699. circleRadiusLabel.visible = true;
  36700. circleRadiusLabel.position.copy(center.clone().add(B).multiplyScalar(0.5));
  36701. circleRadiusLabel.setText(`${radius.toFixed(3)}`);
  36702. }
  36703. }
  36704. { // update area label
  36705. this.areaLabel.position.copy(centroid);
  36706. this.areaLabel.visible = this.showArea && this.points.length >= 3;
  36707. let area = this.getArea();
  36708. let suffix = "";
  36709. if(this.lengthUnit != null && this.lengthUnitDisplay != null){
  36710. area = area / Math.pow(this.lengthUnit.unitspermeter, 2) * Math.pow(this.lengthUnitDisplay.unitspermeter, 2); //convert to square meters then to the square display unit
  36711. suffix = this.lengthUnitDisplay.code;
  36712. }
  36713. let txtArea = Utils.addCommas(area.toFixed(1));
  36714. let msg = `${txtArea} ${suffix}\u00B2`;
  36715. this.areaLabel.setText(msg);
  36716. }
  36717. // this.updateAzimuth();
  36718. };
  36719. raycast (raycaster, intersects) {
  36720. for (let i = 0; i < this.points.length; i++) {
  36721. let sphere = this.spheres[i];
  36722. sphere.raycast(raycaster, intersects);
  36723. }
  36724. // recalculate distances because they are not necessarely correct
  36725. // for scaled objects.
  36726. // see https://github.com/mrdoob/three.js/issues/5827
  36727. // TODO: remove this once the bug has been fixed
  36728. for (let i = 0; i < intersects.length; i++) {
  36729. let I = intersects[i];
  36730. I.distance = raycaster.ray.origin.distanceTo(I.point);
  36731. }
  36732. intersects.sort(function (a, b) { return a.distance - b.distance; });
  36733. };
  36734. get showCoordinates () {
  36735. return this._showCoordinates;
  36736. }
  36737. set showCoordinates (value) {
  36738. this._showCoordinates = value;
  36739. this.update();
  36740. }
  36741. get showAngles () {
  36742. return this._showAngles;
  36743. }
  36744. set showAngles (value) {
  36745. this._showAngles = value;
  36746. this.update();
  36747. }
  36748. get showCircle () {
  36749. return this._showCircle;
  36750. }
  36751. set showCircle (value) {
  36752. this._showCircle = value;
  36753. this.update();
  36754. }
  36755. get showAzimuth(){
  36756. return this._showAzimuth;
  36757. }
  36758. set showAzimuth(value){
  36759. this._showAzimuth = value;
  36760. this.update();
  36761. }
  36762. get showEdges () {
  36763. return this._showEdges;
  36764. }
  36765. set showEdges (value) {
  36766. this._showEdges = value;
  36767. this.update();
  36768. }
  36769. get showHeight () {
  36770. return this._showHeight;
  36771. }
  36772. set showHeight (value) {
  36773. this._showHeight = value;
  36774. this.update();
  36775. }
  36776. get showArea () {
  36777. return this._showArea;
  36778. }
  36779. set showArea (value) {
  36780. this._showArea = value;
  36781. this.update();
  36782. }
  36783. get closed () {
  36784. return this._closed;
  36785. }
  36786. set closed (value) {
  36787. this._closed = value;
  36788. this.update();
  36789. }
  36790. get showDistances () {
  36791. return this._showDistances;
  36792. }
  36793. set showDistances (value) {
  36794. this._showDistances = value;
  36795. this.update();
  36796. }
  36797. }
  36798. class PolygonClipVolume extends Object3D{
  36799. constructor(camera){
  36800. super();
  36801. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  36802. this.name = "polygon_clip_volume_" + this.constructor.counter;
  36803. this.camera = camera.clone();
  36804. this.camera.rotation.set(...camera.rotation.toArray()); // [r85] workaround because camera.clone() doesn't work on rotation
  36805. this.camera.rotation.order = camera.rotation.order;
  36806. this.camera.updateMatrixWorld();
  36807. this.camera.updateProjectionMatrix();
  36808. this.camera.matrixWorldInverse.copy(this.camera.matrixWorld).invert();
  36809. this.viewMatrix = this.camera.matrixWorldInverse.clone();
  36810. this.projMatrix = this.camera.projectionMatrix.clone();
  36811. // projected markers
  36812. this.markers = [];
  36813. this.initialized = false;
  36814. }
  36815. addMarker() {
  36816. let marker = new Mesh();
  36817. let cancel;
  36818. let drag = e => {
  36819. let size = e.viewer.renderer.getSize(new Vector2());
  36820. let projectedPos = new Vector3(
  36821. 2.0 * (e.drag.end.x / size.width) - 1.0,
  36822. -2.0 * (e.drag.end.y / size.height) + 1.0,
  36823. 0
  36824. );
  36825. marker.position.copy(projectedPos);
  36826. };
  36827. let drop = e => {
  36828. cancel();
  36829. };
  36830. cancel = e => {
  36831. marker.removeEventListener("drag", drag);
  36832. marker.removeEventListener("drop", drop);
  36833. };
  36834. marker.addEventListener("drag", drag);
  36835. marker.addEventListener("drop", drop);
  36836. this.markers.push(marker);
  36837. }
  36838. removeLastMarker() {
  36839. if(this.markers.length > 0) {
  36840. this.markers.splice(this.markers.length - 1, 1);
  36841. }
  36842. }
  36843. };
  36844. class Utils {
  36845. static async loadShapefileFeatures (file, callback) {
  36846. let features = [];
  36847. let handleFinish = () => {
  36848. callback(features);
  36849. };
  36850. let source = await shapefile.open(file);
  36851. while(true){
  36852. let result = await source.read();
  36853. if (result.done) {
  36854. handleFinish();
  36855. break;
  36856. }
  36857. if (result.value && result.value.type === 'Feature' && result.value.geometry !== undefined) {
  36858. features.push(result.value);
  36859. }
  36860. }
  36861. }
  36862. static toString (value) {
  36863. if (value.x != null) {
  36864. return value.x.toFixed(2) + ', ' + value.y.toFixed(2) + ', ' + value.z.toFixed(2);
  36865. } else {
  36866. return '' + value + '';
  36867. }
  36868. }
  36869. static normalizeURL (url) {
  36870. let u = new URL(url);
  36871. return u.protocol + '//' + u.hostname + u.pathname.replace(/\/+/g, '/');
  36872. };
  36873. static pathExists (url) {
  36874. let req = XHRFactory.createXMLHttpRequest();
  36875. req.open('GET', url, false);
  36876. req.send(null);
  36877. if (req.status !== 200) {
  36878. return false;
  36879. }
  36880. return true;
  36881. };
  36882. static debugSphere(parent, position, scale, color){
  36883. let geometry = new SphereGeometry(1, 8, 8);
  36884. let material;
  36885. if(color !== undefined){
  36886. material = new MeshBasicMaterial({color: color});
  36887. }else {
  36888. material = new MeshNormalMaterial();
  36889. }
  36890. let sphere = new Mesh(geometry, material);
  36891. sphere.position.copy(position);
  36892. sphere.scale.set(scale, scale, scale);
  36893. parent.add(sphere);
  36894. return sphere;
  36895. }
  36896. static debugLine(parent, start, end, color){
  36897. let material = new LineBasicMaterial({ color: color });
  36898. let geometry = new Geometry();
  36899. const p1 = new Vector3(0, 0, 0);
  36900. const p2 = end.clone().sub(start);
  36901. geometry.vertices.push(p1, p2);
  36902. let tl = new Line( geometry, material );
  36903. tl.position.copy(start);
  36904. parent.add(tl);
  36905. let line = {
  36906. node: tl,
  36907. set: (start, end) => {
  36908. geometry.vertices[0].copy(start);
  36909. geometry.vertices[1].copy(end);
  36910. geometry.verticesNeedUpdate = true;
  36911. },
  36912. };
  36913. return line;
  36914. }
  36915. static debugCircle(parent, center, radius, normal, color){
  36916. let material = new LineBasicMaterial({ color: color });
  36917. let geometry = new Geometry();
  36918. let n = 32;
  36919. for(let i = 0; i <= n; i++){
  36920. let u0 = 2 * Math.PI * (i / n);
  36921. let u1 = 2 * Math.PI * (i + 1) / n;
  36922. let p0 = new Vector3(
  36923. Math.cos(u0),
  36924. Math.sin(u0),
  36925. 0
  36926. );
  36927. let p1 = new Vector3(
  36928. Math.cos(u1),
  36929. Math.sin(u1),
  36930. 0
  36931. );
  36932. geometry.vertices.push(p0, p1);
  36933. }
  36934. let tl = new Line( geometry, material );
  36935. tl.position.copy(center);
  36936. tl.scale.set(radius, radius, radius);
  36937. parent.add(tl);
  36938. }
  36939. static debugBox(parent, box, transform = new Matrix4(), color = 0xFFFF00){
  36940. let vertices = [
  36941. [box.min.x, box.min.y, box.min.z],
  36942. [box.min.x, box.min.y, box.max.z],
  36943. [box.min.x, box.max.y, box.min.z],
  36944. [box.min.x, box.max.y, box.max.z],
  36945. [box.max.x, box.min.y, box.min.z],
  36946. [box.max.x, box.min.y, box.max.z],
  36947. [box.max.x, box.max.y, box.min.z],
  36948. [box.max.x, box.max.y, box.max.z],
  36949. ].map(v => new Vector3(...v));
  36950. let edges = [
  36951. [0, 4], [4, 5], [5, 1], [1, 0],
  36952. [2, 6], [6, 7], [7, 3], [3, 2],
  36953. [0, 2], [4, 6], [5, 7], [1, 3]
  36954. ];
  36955. let center = box.getCenter(new Vector3());
  36956. let centroids = [
  36957. {position: [box.min.x, center.y, center.z], color: 0xFF0000},
  36958. {position: [box.max.x, center.y, center.z], color: 0x880000},
  36959. {position: [center.x, box.min.y, center.z], color: 0x00FF00},
  36960. {position: [center.x, box.max.y, center.z], color: 0x008800},
  36961. {position: [center.x, center.y, box.min.z], color: 0x0000FF},
  36962. {position: [center.x, center.y, box.max.z], color: 0x000088},
  36963. ];
  36964. for(let vertex of vertices){
  36965. let pos = vertex.clone().applyMatrix4(transform);
  36966. Utils.debugSphere(parent, pos, 0.1, 0xFF0000);
  36967. }
  36968. for(let edge of edges){
  36969. let start = vertices[edge[0]].clone().applyMatrix4(transform);
  36970. let end = vertices[edge[1]].clone().applyMatrix4(transform);
  36971. Utils.debugLine(parent, start, end, color);
  36972. }
  36973. for(let centroid of centroids){
  36974. let pos = new Vector3(...centroid.position).applyMatrix4(transform);
  36975. Utils.debugSphere(parent, pos, 0.1, centroid.color);
  36976. }
  36977. }
  36978. static debugPlane(parent, plane, size = 1, color = 0x0000FF){
  36979. let planehelper = new PlaneHelper(plane, size, color);
  36980. parent.add(planehelper);
  36981. }
  36982. /**
  36983. * adapted from mhluska at https://github.com/mrdoob/three.js/issues/1561
  36984. */
  36985. static computeTransformedBoundingBox (box, transform) {
  36986. let vertices = [
  36987. new Vector3(box.min.x, box.min.y, box.min.z).applyMatrix4(transform),
  36988. new Vector3(box.min.x, box.min.y, box.min.z).applyMatrix4(transform),
  36989. new Vector3(box.max.x, box.min.y, box.min.z).applyMatrix4(transform),
  36990. new Vector3(box.min.x, box.max.y, box.min.z).applyMatrix4(transform),
  36991. new Vector3(box.min.x, box.min.y, box.max.z).applyMatrix4(transform),
  36992. new Vector3(box.min.x, box.max.y, box.max.z).applyMatrix4(transform),
  36993. new Vector3(box.max.x, box.max.y, box.min.z).applyMatrix4(transform),
  36994. new Vector3(box.max.x, box.min.y, box.max.z).applyMatrix4(transform),
  36995. new Vector3(box.max.x, box.max.y, box.max.z).applyMatrix4(transform)
  36996. ];
  36997. let boundingBox = new Box3();
  36998. boundingBox.setFromPoints(vertices);
  36999. return boundingBox;
  37000. };//感觉就是bound.applyMatrix4(transform)
  37001. /**
  37002. * add separators to large numbers
  37003. *
  37004. * @param nStr
  37005. * @returns
  37006. */
  37007. static addCommas (nStr) {
  37008. nStr += '';
  37009. let x = nStr.split('.');
  37010. let x1 = x[0];
  37011. let x2 = x.length > 1 ? '.' + x[1] : '';
  37012. let rgx = /(\d+)(\d{3})/;
  37013. while (rgx.test(x1)) {
  37014. x1 = x1.replace(rgx, '$1' + ',' + '$2');
  37015. }
  37016. return x1 + x2;
  37017. };
  37018. static removeCommas (str) {
  37019. return str.replace(/,/g, '');
  37020. }
  37021. /**
  37022. * create worker from a string
  37023. *
  37024. * code from http://stackoverflow.com/questions/10343913/how-to-create-a-web-worker-from-a-string
  37025. */
  37026. static createWorker (code) {
  37027. let blob = new Blob([code], {type: 'application/javascript'});
  37028. let worker = new Worker(URL.createObjectURL(blob));
  37029. return worker;
  37030. };
  37031. static moveTo(scene, endPosition, endTarget){
  37032. let view = scene.view;
  37033. let camera = scene.getActiveCamera();
  37034. let animationDuration = 500;
  37035. let easing = TWEEN.Easing.Quartic.Out;
  37036. { // animate camera position
  37037. let tween = new TWEEN.Tween(view.position).to(endPosition, animationDuration);
  37038. tween.easing(easing);
  37039. tween.start();
  37040. }
  37041. { // animate camera target
  37042. let camTargetDistance = camera.position.distanceTo(endTarget);
  37043. let target = new Vector3().addVectors(
  37044. camera.position,
  37045. camera.getWorldDirection(new Vector3()).clone().multiplyScalar(camTargetDistance)
  37046. );
  37047. let tween = new TWEEN.Tween(target).to(endTarget, animationDuration);
  37048. tween.easing(easing);
  37049. tween.onUpdate(() => {
  37050. view.lookAt(target);
  37051. });
  37052. tween.onComplete(() => {
  37053. view.lookAt(target);
  37054. });
  37055. tween.start();
  37056. }
  37057. }
  37058. static loadSkybox (path) {
  37059. let parent = new Object3D("skybox_root");
  37060. let camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 100000);
  37061. camera.up.set(0, 0, 1);
  37062. let scene = new Scene();
  37063. let format = '.jpg';
  37064. let urls = [
  37065. path + 'px' + format, path + 'nx' + format,
  37066. path + 'py' + format, path + 'ny' + format,
  37067. path + 'pz' + format, path + 'nz' + format
  37068. ];
  37069. let materialArray = [];
  37070. {
  37071. for (let i = 0; i < 6; i++) {
  37072. let material = new MeshBasicMaterial({
  37073. map: null,
  37074. side: BackSide,
  37075. depthTest: false,
  37076. depthWrite: false,
  37077. color: 0x424556
  37078. });
  37079. materialArray.push(material);
  37080. let loader = new TextureLoader();
  37081. loader.load(urls[i],
  37082. function loaded (texture) {
  37083. material.map = texture;
  37084. material.needsUpdate = true;
  37085. material.color.setHex(0xffffff);
  37086. }, function progress (xhr) {
  37087. // console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
  37088. }, function error (xhr) {
  37089. console.log('An error happened', xhr);
  37090. }
  37091. );
  37092. }
  37093. }
  37094. let skyGeometry = new BoxGeometry(700, 700, 700);
  37095. let skybox = new Mesh(skyGeometry, materialArray);
  37096. scene.add(skybox);
  37097. scene.traverse(n => n.frustumCulled = false);
  37098. // z up
  37099. scene.rotation.x = Math.PI / 2;
  37100. parent.children.push(camera);
  37101. camera.parent = parent;
  37102. return {camera, scene, parent};
  37103. };
  37104. static createGrid (width, length, spacing, color) {
  37105. let material = new LineBasicMaterial({
  37106. color: color || 0x888888
  37107. });
  37108. let geometry = new Geometry();
  37109. for (let i = 0; i <= length; i++) {
  37110. geometry.vertices.push(new Vector3(-(spacing * width) / 2, i * spacing - (spacing * length) / 2, 0));
  37111. geometry.vertices.push(new Vector3(+(spacing * width) / 2, i * spacing - (spacing * length) / 2, 0));
  37112. }
  37113. for (let i = 0; i <= width; i++) {
  37114. geometry.vertices.push(new Vector3(i * spacing - (spacing * width) / 2, -(spacing * length) / 2, 0));
  37115. geometry.vertices.push(new Vector3(i * spacing - (spacing * width) / 2, +(spacing * length) / 2, 0));
  37116. }
  37117. let line = new LineSegments(geometry, material, LinePieces);
  37118. line.receiveShadow = true;
  37119. return line;
  37120. }
  37121. static createBackgroundTexture (width, height) {
  37122. function gauss (x, y) {
  37123. return (1 / (2 * Math.PI)) * Math.exp(-(x * x + y * y) / 2);
  37124. };
  37125. // map.magFilter = THREE.NearestFilter;
  37126. let size = width * height;
  37127. let data = new Uint8Array(3 * size);
  37128. let chroma = [1, 1.5, 1.7];
  37129. let max = gauss(0, 0);
  37130. for (let x = 0; x < width; x++) {
  37131. for (let y = 0; y < height; y++) {
  37132. let u = 2 * (x / width) - 1;
  37133. let v = 2 * (y / height) - 1;
  37134. let i = x + width * y;
  37135. let d = gauss(2 * u, 2 * v) / max;
  37136. let r = (Math.random() + Math.random() + Math.random()) / 3;
  37137. r = (d * 0.5 + 0.5) * r * 0.03;
  37138. r = r * 0.4;
  37139. // d = Math.pow(d, 0.6);
  37140. data[3 * i + 0] = 255 * (d / 15 + 0.05 + r) * chroma[0];
  37141. data[3 * i + 1] = 255 * (d / 15 + 0.05 + r) * chroma[1];
  37142. data[3 * i + 2] = 255 * (d / 15 + 0.05 + r) * chroma[2];
  37143. }
  37144. }
  37145. let texture = new DataTexture(data, width, height, RGBFormat);
  37146. texture.needsUpdate = true;
  37147. return texture;
  37148. }
  37149. static getMousePointCloudIntersection (mouse, camera, viewer, pointclouds, params = {}) {
  37150. let renderer = viewer.renderer;
  37151. let nmouse = {
  37152. x: (mouse.x / renderer.domElement.clientWidth) * 2 - 1,
  37153. y: -(mouse.y / renderer.domElement.clientHeight) * 2 + 1
  37154. };
  37155. let pickParams = {};
  37156. if(params.pickClipped){
  37157. pickParams.pickClipped = params.pickClipped;
  37158. }
  37159. pickParams.x = mouse.x;
  37160. pickParams.y = renderer.domElement.clientHeight - mouse.y;
  37161. let raycaster = new Raycaster();
  37162. raycaster.setFromCamera(nmouse, camera);
  37163. let ray = raycaster.ray;
  37164. let selectedPointcloud = null;
  37165. let closestDistance = Infinity;
  37166. let closestIntersection = null;
  37167. let closestPoint = null;
  37168. for(let pointcloud of pointclouds){
  37169. let point = pointcloud.pick(viewer, camera, ray, pickParams);
  37170. if(!point){
  37171. continue;
  37172. }
  37173. let distance = camera.position.distanceTo(point.position);
  37174. if (distance < closestDistance) {
  37175. closestDistance = distance;
  37176. selectedPointcloud = pointcloud;
  37177. closestIntersection = point.position;
  37178. closestPoint = point;
  37179. }
  37180. }
  37181. if (selectedPointcloud) {
  37182. return {
  37183. location: closestIntersection,
  37184. distance: closestDistance,
  37185. pointcloud: selectedPointcloud,
  37186. point: closestPoint
  37187. };
  37188. } else {
  37189. return null;
  37190. }
  37191. }
  37192. static pixelsArrayToImage (pixels, width, height) {
  37193. let canvas = document.createElement('canvas');
  37194. canvas.width = width;
  37195. canvas.height = height;
  37196. let context = canvas.getContext('2d');
  37197. pixels = new pixels.constructor(pixels);
  37198. for (let i = 0; i < pixels.length; i++) {
  37199. pixels[i * 4 + 3] = 255;
  37200. }
  37201. let imageData = context.createImageData(width, height);
  37202. imageData.data.set(pixels);
  37203. context.putImageData(imageData, 0, 0);
  37204. let img = new Image();
  37205. img.src = canvas.toDataURL();
  37206. // img.style.transform = "scaleY(-1)";
  37207. return img;
  37208. }
  37209. static pixelsArrayToDataUrl(pixels, width, height) {
  37210. let canvas = document.createElement('canvas');
  37211. canvas.width = width;
  37212. canvas.height = height;
  37213. let context = canvas.getContext('2d');
  37214. pixels = new pixels.constructor(pixels);
  37215. for (let i = 0; i < pixels.length; i++) {
  37216. pixels[i * 4 + 3] = 255;
  37217. }
  37218. let imageData = context.createImageData(width, height);
  37219. imageData.data.set(pixels);
  37220. context.putImageData(imageData, 0, 0);
  37221. let dataURL = canvas.toDataURL();
  37222. return dataURL;
  37223. }
  37224. static pixelsArrayToCanvas(pixels, width, height){
  37225. let canvas = document.createElement('canvas');
  37226. canvas.width = width;
  37227. canvas.height = height;
  37228. let context = canvas.getContext('2d');
  37229. pixels = new pixels.constructor(pixels);
  37230. //for (let i = 0; i < pixels.length; i++) {
  37231. // pixels[i * 4 + 3] = 255;
  37232. //}
  37233. // flip vertically
  37234. let bytesPerLine = width * 4;
  37235. for(let i = 0; i < parseInt(height / 2); i++){
  37236. let j = height - i - 1;
  37237. let lineI = pixels.slice(i * bytesPerLine, i * bytesPerLine + bytesPerLine);
  37238. let lineJ = pixels.slice(j * bytesPerLine, j * bytesPerLine + bytesPerLine);
  37239. pixels.set(lineJ, i * bytesPerLine);
  37240. pixels.set(lineI, j * bytesPerLine);
  37241. }
  37242. let imageData = context.createImageData(width, height);
  37243. imageData.data.set(pixels);
  37244. context.putImageData(imageData, 0, 0);
  37245. return canvas;
  37246. }
  37247. static removeListeners(dispatcher, type){
  37248. if (dispatcher._listeners === undefined) {
  37249. return;
  37250. }
  37251. if (dispatcher._listeners[ type ]) {
  37252. delete dispatcher._listeners[ type ];
  37253. }
  37254. }
  37255. static mouseToRay(mouse, camera, width, height){
  37256. let normalizedMouse = {
  37257. x: (mouse.x / width) * 2 - 1,
  37258. y: -(mouse.y / height) * 2 + 1
  37259. };
  37260. let vector = new Vector3(normalizedMouse.x, normalizedMouse.y, 0.5);
  37261. let origin = camera.position.clone();
  37262. vector.unproject(camera);
  37263. let direction = new Vector3().subVectors(vector, origin).normalize();
  37264. let ray = new Ray(origin, direction);
  37265. return ray;
  37266. }
  37267. static projectedRadius(radius, camera, distance, screenWidth, screenHeight){
  37268. if(camera instanceof OrthographicCamera){
  37269. return Utils.projectedRadiusOrtho(radius, camera.projectionMatrix, screenWidth, screenHeight);
  37270. }else if(camera instanceof PerspectiveCamera){
  37271. return Utils.projectedRadiusPerspective(radius, camera.fov * Math.PI / 180, distance, screenHeight);
  37272. }else {
  37273. throw new Error("invalid parameters");
  37274. }
  37275. }
  37276. static projectedRadiusPerspective(radius, fov, distance, screenHeight) {
  37277. let projFactor = (1 / Math.tan(fov / 2)) / distance;
  37278. projFactor = projFactor * screenHeight / 2;
  37279. return radius * projFactor;
  37280. }
  37281. static projectedRadiusOrtho(radius, proj, screenWidth, screenHeight) {
  37282. let p1 = new Vector4(0);
  37283. let p2 = new Vector4(radius);
  37284. p1.applyMatrix4(proj);
  37285. p2.applyMatrix4(proj);
  37286. p1 = new Vector3(p1.x, p1.y, p1.z);
  37287. p2 = new Vector3(p2.x, p2.y, p2.z);
  37288. p1.x = (p1.x + 1.0) * 0.5 * screenWidth;
  37289. p1.y = (p1.y + 1.0) * 0.5 * screenHeight;
  37290. p2.x = (p2.x + 1.0) * 0.5 * screenWidth;
  37291. p2.y = (p2.y + 1.0) * 0.5 * screenHeight;
  37292. return p1.distanceTo(p2);
  37293. }
  37294. static topView(camera, node){
  37295. camera.position.set(0, 1, 0);
  37296. camera.rotation.set(-Math.PI / 2, 0, 0);
  37297. camera.zoomTo(node, 1);
  37298. }
  37299. static frontView (camera, node) {
  37300. camera.position.set(0, 0, 1);
  37301. camera.rotation.set(0, 0, 0);
  37302. camera.zoomTo(node, 1);
  37303. }
  37304. static leftView (camera, node) {
  37305. camera.position.set(-1, 0, 0);
  37306. camera.rotation.set(0, -Math.PI / 2, 0);
  37307. camera.zoomTo(node, 1);
  37308. }
  37309. static rightView (camera, node) {
  37310. camera.position.set(1, 0, 0);
  37311. camera.rotation.set(0, Math.PI / 2, 0);
  37312. camera.zoomTo(node, 1);
  37313. }
  37314. static findClosestGpsTime(target, viewer){
  37315. const start = performance.now();
  37316. const nodes = [];
  37317. for(const pc of viewer.scene.pointclouds){
  37318. nodes.push(pc.root);
  37319. for(const child of pc.root.children){
  37320. if(child){
  37321. nodes.push(child);
  37322. }
  37323. }
  37324. }
  37325. let closestNode = null;
  37326. let closestIndex = Infinity;
  37327. let closestDistance = Infinity;
  37328. let closestValue = 0;
  37329. for(const node of nodes){
  37330. const isOkay = node.geometryNode != null
  37331. && node.geometryNode.geometry != null
  37332. && node.sceneNode != null;
  37333. if(!isOkay){
  37334. continue;
  37335. }
  37336. let geometry = node.geometryNode.geometry;
  37337. let gpsTime = geometry.attributes["gps-time"];
  37338. let range = gpsTime.potree.range;
  37339. for(let i = 0; i < gpsTime.array.length; i++){
  37340. let value = gpsTime.array[i];
  37341. value = value * (range[1] - range[0]) + range[0];
  37342. const distance = Math.abs(target - value);
  37343. if(distance < closestDistance){
  37344. closestIndex = i;
  37345. closestDistance = distance;
  37346. closestValue = value;
  37347. closestNode = node;
  37348. //console.log("found a closer one: " + value);
  37349. }
  37350. }
  37351. }
  37352. const geometry = closestNode.geometryNode.geometry;
  37353. const position = new Vector3(
  37354. geometry.attributes.position.array[3 * closestIndex + 0],
  37355. geometry.attributes.position.array[3 * closestIndex + 1],
  37356. geometry.attributes.position.array[3 * closestIndex + 2],
  37357. );
  37358. position.applyMatrix4(closestNode.sceneNode.matrixWorld);
  37359. const end = performance.now();
  37360. const duration = (end - start);
  37361. console.log(`duration: ${duration.toFixed(3)}ms`);
  37362. return {
  37363. node: closestNode,
  37364. index: closestIndex,
  37365. position: position,
  37366. };
  37367. }
  37368. /**
  37369. *
  37370. * 0: no intersection
  37371. * 1: intersection
  37372. * 2: fully inside
  37373. */
  37374. static frustumSphereIntersection (frustum, sphere) {
  37375. let planes = frustum.planes;
  37376. let center = sphere.center;
  37377. let negRadius = -sphere.radius;
  37378. let minDistance = Number.MAX_VALUE;
  37379. for (let i = 0; i < 6; i++) {
  37380. let distance = planes[ i ].distanceToPoint(center);
  37381. if (distance < negRadius) {
  37382. return 0;
  37383. }
  37384. minDistance = Math.min(minDistance, distance);
  37385. }
  37386. return (minDistance >= sphere.radius) ? 2 : 1;
  37387. }
  37388. // code taken from three.js
  37389. // ImageUtils - generateDataTexture()
  37390. static generateDataTexture (width, height, color) {
  37391. let size = width * height;
  37392. let data = new Uint8Array(4 * width * height);
  37393. let r = Math.floor(color.r * 255);
  37394. let g = Math.floor(color.g * 255);
  37395. let b = Math.floor(color.b * 255);
  37396. for (let i = 0; i < size; i++) {
  37397. data[ i * 3 ] = r;
  37398. data[ i * 3 + 1 ] = g;
  37399. data[ i * 3 + 2 ] = b;
  37400. }
  37401. let texture = new DataTexture(data, width, height, RGBAFormat);
  37402. texture.needsUpdate = true;
  37403. texture.magFilter = NearestFilter;
  37404. return texture;
  37405. }
  37406. // from http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
  37407. static getParameterByName (name) {
  37408. name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
  37409. let regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
  37410. let results = regex.exec(document.location.search);
  37411. return results === null ? null : decodeURIComponent(results[1].replace(/\+/g, ' '));
  37412. }
  37413. static setParameter (name, value) {
  37414. // value = encodeURIComponent(value);
  37415. name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
  37416. let regex = new RegExp('([\\?&])(' + name + '=([^&#]*))');
  37417. let results = regex.exec(document.location.search);
  37418. let url = window.location.href;
  37419. if (results === null) {
  37420. if (window.location.search.length === 0) {
  37421. url = url + '?';
  37422. } else {
  37423. url = url + '&';
  37424. }
  37425. url = url + name + '=' + value;
  37426. } else {
  37427. let newValue = name + '=' + value;
  37428. url = url.replace(results[2], newValue);
  37429. }
  37430. window.history.replaceState({}, '', url);
  37431. }
  37432. static createChildAABB(aabb, index){
  37433. let min = aabb.min.clone();
  37434. let max = aabb.max.clone();
  37435. let size = new Vector3().subVectors(max, min);
  37436. if ((index & 0b0001) > 0) {
  37437. min.z += size.z / 2;
  37438. } else {
  37439. max.z -= size.z / 2;
  37440. }
  37441. if ((index & 0b0010) > 0) {
  37442. min.y += size.y / 2;
  37443. } else {
  37444. max.y -= size.y / 2;
  37445. }
  37446. if ((index & 0b0100) > 0) {
  37447. min.x += size.x / 2;
  37448. } else {
  37449. max.x -= size.x / 2;
  37450. }
  37451. return new Box3(min, max);
  37452. }
  37453. // see https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
  37454. static clipboardCopy(text){
  37455. let textArea = document.createElement("textarea");
  37456. textArea.style.position = 'fixed';
  37457. textArea.style.top = 0;
  37458. textArea.style.left = 0;
  37459. textArea.style.width = '2em';
  37460. textArea.style.height = '2em';
  37461. textArea.style.padding = 0;
  37462. textArea.style.border = 'none';
  37463. textArea.style.outline = 'none';
  37464. textArea.style.boxShadow = 'none';
  37465. textArea.style.background = 'transparent';
  37466. textArea.value = text;
  37467. document.body.appendChild(textArea);
  37468. textArea.select();
  37469. try {
  37470. let success = document.execCommand('copy');
  37471. if(success){
  37472. console.log("copied text to clipboard");
  37473. }else {
  37474. console.log("copy to clipboard failed");
  37475. }
  37476. } catch (err) {
  37477. console.log("error while trying to copy to clipboard");
  37478. }
  37479. document.body.removeChild(textArea);
  37480. }
  37481. static getMeasurementIcon(measurement){
  37482. if (measurement instanceof Measure) {
  37483. if (measurement.showDistances && !measurement.showArea && !measurement.showAngles) {
  37484. return `${Potree.resourcePath}/icons/distance.svg`;
  37485. } else if (measurement.showDistances && measurement.showArea && !measurement.showAngles) {
  37486. return `${Potree.resourcePath}/icons/area.svg`;
  37487. } else if (measurement.maxMarkers === 1) {
  37488. return `${Potree.resourcePath}/icons/point.svg`;
  37489. } else if (!measurement.showDistances && !measurement.showArea && measurement.showAngles) {
  37490. return `${Potree.resourcePath}/icons/angle.png`;
  37491. } else if (measurement.showHeight) {
  37492. return `${Potree.resourcePath}/icons/height.svg`;
  37493. } else {
  37494. return `${Potree.resourcePath}/icons/distance.svg`;
  37495. }
  37496. } else if (measurement instanceof Profile) {
  37497. return `${Potree.resourcePath}/icons/profile.svg`;
  37498. } else if (measurement instanceof Volume) {
  37499. return `${Potree.resourcePath}/icons/volume.svg`;
  37500. } else if (measurement instanceof PolygonClipVolume) {
  37501. return `${Potree.resourcePath}/icons/clip-polygon.svg`;
  37502. }
  37503. }
  37504. static lineToLineIntersection(P0, P1, P2, P3){
  37505. const P = [P0, P1, P2, P3];
  37506. const d = (m, n, o, p) => {
  37507. let result =
  37508. (P[m].x - P[n].x) * (P[o].x - P[p].x)
  37509. + (P[m].y - P[n].y) * (P[o].y - P[p].y)
  37510. + (P[m].z - P[n].z) * (P[o].z - P[p].z);
  37511. return result;
  37512. };
  37513. const mua = (d(0, 2, 3, 2) * d(3, 2, 1, 0) - d(0, 2, 1, 0) * d(3, 2, 3, 2))
  37514. /**-----------------------------------------------------------------**/ /
  37515. (d(1, 0, 1, 0) * d(3, 2, 3, 2) - d(3, 2, 1, 0) * d(3, 2, 1, 0));
  37516. const mub = (d(0, 2, 3, 2) + mua * d(3, 2, 1, 0))
  37517. /**--------------------------------------**/ /
  37518. d(3, 2, 3, 2);
  37519. const P01 = P1.clone().sub(P0);
  37520. const P23 = P3.clone().sub(P2);
  37521. const Pa = P0.clone().add(P01.multiplyScalar(mua));
  37522. const Pb = P2.clone().add(P23.multiplyScalar(mub));
  37523. const center = Pa.clone().add(Pb).multiplyScalar(0.5);
  37524. return center;
  37525. }
  37526. static computeCircleCenter(A, B, C){
  37527. const AB = B.clone().sub(A);
  37528. const AC = C.clone().sub(A);
  37529. const N = AC.clone().cross(AB).normalize();
  37530. const ab_dir = AB.clone().cross(N).normalize();
  37531. const ac_dir = AC.clone().cross(N).normalize();
  37532. const ab_origin = A.clone().add(B).multiplyScalar(0.5);
  37533. const ac_origin = A.clone().add(C).multiplyScalar(0.5);
  37534. const P0 = ab_origin;
  37535. const P1 = ab_origin.clone().add(ab_dir);
  37536. const P2 = ac_origin;
  37537. const P3 = ac_origin.clone().add(ac_dir);
  37538. const center = Utils.lineToLineIntersection(P0, P1, P2, P3);
  37539. return center;
  37540. // Potree.Utils.debugLine(viewer.scene.scene, P0, P1, 0x00ff00);
  37541. // Potree.Utils.debugLine(viewer.scene.scene, P2, P3, 0x0000ff);
  37542. // Potree.Utils.debugSphere(viewer.scene.scene, center, 0.03, 0xff00ff);
  37543. // const radius = center.distanceTo(A);
  37544. // Potree.Utils.debugCircle(viewer.scene.scene, center, radius, new THREE.Vector3(0, 0, 1), 0xff00ff);
  37545. }
  37546. static getNorthVec(p1, distance, projection){
  37547. if(projection){
  37548. // if there is a projection, transform coordinates to WGS84
  37549. // and compute angle to north there
  37550. proj4.defs("pointcloud", projection);
  37551. const transform = proj4("pointcloud", "WGS84");
  37552. const llP1 = transform.forward(p1.toArray());
  37553. let llP2 = transform.forward([p1.x, p1.y + distance]);
  37554. const polarRadius = Math.sqrt((llP2[0] - llP1[0]) ** 2 + (llP2[1] - llP1[1]) ** 2);
  37555. llP2 = [llP1[0], llP1[1] + polarRadius];
  37556. const northVec = transform.inverse(llP2);
  37557. return new Vector3(...northVec, p1.z).sub(p1);
  37558. }else {
  37559. // if there is no projection, assume [0, 1, 0] as north direction
  37560. const vec = new Vector3(0, 1, 0).multiplyScalar(distance);
  37561. return vec;
  37562. }
  37563. }
  37564. static computeAzimuth(p1, p2, projection){
  37565. let azimuth = 0;
  37566. if(projection){
  37567. // if there is a projection, transform coordinates to WGS84
  37568. // and compute angle to north there
  37569. let transform;
  37570. if (projection.includes('EPSG')) {
  37571. transform = proj4(projection, "WGS84");
  37572. } else {
  37573. proj4.defs("pointcloud", projection);
  37574. transform = proj4("pointcloud", "WGS84");
  37575. }
  37576. const llP1 = transform.forward(p1.toArray());
  37577. const llP2 = transform.forward(p2.toArray());
  37578. const dir = [
  37579. llP2[0] - llP1[0],
  37580. llP2[1] - llP1[1],
  37581. ];
  37582. azimuth = Math.atan2(dir[1], dir[0]) - Math.PI / 2;
  37583. }else {
  37584. // if there is no projection, assume [0, 1, 0] as north direction
  37585. const dir = [p2.x - p1.x, p2.y - p1.y];
  37586. azimuth = Math.atan2(dir[1], dir[0]) - Math.PI / 2;
  37587. }
  37588. // make clockwise
  37589. azimuth = -azimuth;
  37590. return azimuth;
  37591. }
  37592. static async loadScript(url){
  37593. return new Promise( resolve => {
  37594. const element = document.getElementById(url);
  37595. if(element){
  37596. resolve();
  37597. }else {
  37598. const script = document.createElement("script");
  37599. script.id = url;
  37600. script.onload = () => {
  37601. resolve();
  37602. };
  37603. script.src = url;
  37604. document.body.appendChild(script);
  37605. }
  37606. });
  37607. }
  37608. static createSvgGradient(scheme){
  37609. // this is what we are creating:
  37610. //
  37611. //<svg width="1em" height="3em" xmlns="http://www.w3.org/2000/svg">
  37612. // <defs>
  37613. // <linearGradient id="gradientID" gradientTransform="rotate(90)">
  37614. // <stop offset="0%" stop-color="rgb(93, 78, 162)" />
  37615. // ...
  37616. // <stop offset="100%" stop-color="rgb(157, 0, 65)" />
  37617. // </linearGradient>
  37618. // </defs>
  37619. //
  37620. // <rect width="100%" height="100%" fill="url('#myGradient')" stroke="black" stroke-width="0.1em"/>
  37621. //</svg>
  37622. const gradientId = `${Math.random()}_${Date.now()}`;
  37623. const svgn = "http://www.w3.org/2000/svg";
  37624. const svg = document.createElementNS(svgn, "svg");
  37625. svg.setAttributeNS(null, "width", "2em");
  37626. svg.setAttributeNS(null, "height", "3em");
  37627. { // <defs>
  37628. const defs = document.createElementNS(svgn, "defs");
  37629. const linearGradient = document.createElementNS(svgn, "linearGradient");
  37630. linearGradient.setAttributeNS(null, "id", gradientId);
  37631. linearGradient.setAttributeNS(null, "gradientTransform", "rotate(90)");
  37632. for(let i = scheme.length - 1; i >= 0; i--){
  37633. const stopVal = scheme[i];
  37634. const percent = parseInt(100 - stopVal[0] * 100);
  37635. const [r, g, b] = stopVal[1].toArray().map(v => parseInt(v * 255));
  37636. const stop = document.createElementNS(svgn, "stop");
  37637. stop.setAttributeNS(null, "offset", `${percent}%`);
  37638. stop.setAttributeNS(null, "stop-color", `rgb(${r}, ${g}, ${b})`);
  37639. linearGradient.appendChild(stop);
  37640. }
  37641. defs.appendChild(linearGradient);
  37642. svg.appendChild(defs);
  37643. }
  37644. const rect = document.createElementNS(svgn, "rect");
  37645. rect.setAttributeNS(null, "width", `100%`);
  37646. rect.setAttributeNS(null, "height", `100%`);
  37647. rect.setAttributeNS(null, "fill", `url("#${gradientId}")`);
  37648. rect.setAttributeNS(null, "stroke", `black`);
  37649. rect.setAttributeNS(null, "stroke-width", `0.1em`);
  37650. svg.appendChild(rect);
  37651. return svg;
  37652. }
  37653. static async waitAny(promises){
  37654. return new Promise( (resolve) => {
  37655. promises.map( promise => {
  37656. promise.then( () => {
  37657. resolve();
  37658. });
  37659. });
  37660. });
  37661. }
  37662. }
  37663. Utils.screenPass = new function () {
  37664. this.screenScene = new Scene();
  37665. this.screenQuad = new Mesh(new PlaneBufferGeometry(2, 2, 1));
  37666. this.screenQuad.material.depthTest = true;
  37667. this.screenQuad.material.depthWrite = true;
  37668. this.screenQuad.material.transparent = true;
  37669. this.screenScene.add(this.screenQuad);
  37670. this.camera = new Camera();
  37671. this.render = function (renderer, material, target) {
  37672. this.screenQuad.material = material;
  37673. if (typeof target === 'undefined') {
  37674. renderer.render(this.screenScene, this.camera);
  37675. } else {
  37676. renderer.render(this.screenScene, this.camera, target);
  37677. }
  37678. };
  37679. }();
  37680. class Version{
  37681. constructor(version){
  37682. this.version = version;
  37683. let vmLength = (version.indexOf('.') === -1) ? version.length : version.indexOf('.');
  37684. this.versionMajor = parseInt(version.substr(0, vmLength));
  37685. this.versionMinor = parseInt(version.substr(vmLength + 1));
  37686. if (this.versionMinor.length === 0) {
  37687. this.versionMinor = 0;
  37688. }
  37689. }
  37690. newerThan(version){
  37691. let v = new Version(version);
  37692. if (this.versionMajor > v.versionMajor) {
  37693. return true;
  37694. } else if (this.versionMajor === v.versionMajor && this.versionMinor > v.versionMinor) {
  37695. return true;
  37696. } else {
  37697. return false;
  37698. }
  37699. }
  37700. equalOrHigher(version){
  37701. let v = new Version(version);
  37702. if (this.versionMajor > v.versionMajor) {
  37703. return true;
  37704. } else if (this.versionMajor === v.versionMajor && this.versionMinor >= v.versionMinor) {
  37705. return true;
  37706. } else {
  37707. return false;
  37708. }
  37709. }
  37710. upTo(version){
  37711. return !this.newerThan(version);
  37712. }
  37713. }
  37714. //加载 解析点云
  37715. class BinaryLoader{
  37716. constructor(version, boundingBox, scale){
  37717. if (typeof (version) === 'string') {
  37718. this.version = new Version(version);
  37719. } else {
  37720. this.version = version;
  37721. }
  37722. this.boundingBox = boundingBox;
  37723. this.scale = scale;
  37724. }
  37725. load(node){
  37726. if (node.loaded) {
  37727. return;
  37728. }
  37729. let url = node.getURL();
  37730. if (this.version.equalOrHigher('1.4')) {
  37731. url += '.bin';
  37732. }
  37733. let xhr = XHRFactory.createXMLHttpRequest();
  37734. xhr.open('GET', url, true);
  37735. xhr.responseType = 'arraybuffer';
  37736. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  37737. xhr.onreadystatechange = () => {
  37738. if (xhr.readyState === 4) {
  37739. if((xhr.status === 200 || xhr.status === 0) && xhr.response !== null){
  37740. let buffer = xhr.response;
  37741. this.parse(node, buffer);
  37742. } else {
  37743. //console.error(`Failed to load file! HTTP status: ${xhr.status}, file: ${url}`);
  37744. throw new Error(`Failed to load file! HTTP status: ${xhr.status}, file: ${url}`);
  37745. }
  37746. }
  37747. };
  37748. try {
  37749. xhr.send(null);
  37750. } catch (e) {
  37751. console.log('fehler beim laden der punktwolke: ' + e);
  37752. }
  37753. };
  37754. parse(node, buffer, callback){
  37755. let pointAttributes = node.pcoGeometry.pointAttributes;
  37756. let numPoints = buffer.byteLength / node.pcoGeometry.pointAttributes.byteSize;
  37757. if (this.version.upTo('1.5')) {
  37758. node.numPoints = numPoints;
  37759. }
  37760. let workerPath = Potree.scriptPath + '/workers/BinaryDecoderWorker.js';
  37761. let worker = Potree.workerPool.getWorker(workerPath);
  37762. worker.onmessage = function (e) {
  37763. let data = e.data;
  37764. let buffers = data.attributeBuffers;
  37765. let tightBoundingBox = new Box3(
  37766. new Vector3().fromArray(data.tightBoundingBox.min),
  37767. new Vector3().fromArray(data.tightBoundingBox.max)
  37768. );
  37769. Potree.workerPool.returnWorker(workerPath, worker);
  37770. let geometry = new BufferGeometry();
  37771. for(let property in buffers){
  37772. let buffer = buffers[property].buffer;
  37773. let batchAttribute = buffers[property].attribute;
  37774. if (property === "POSITION_CARTESIAN") {
  37775. geometry.setAttribute('position', new BufferAttribute(new Float32Array(buffer), 3));
  37776. } else if (property === "rgba") {
  37777. geometry.setAttribute("rgba", new BufferAttribute(new Uint8Array(buffer), 4, true));
  37778. } else if (property === "NORMAL_SPHEREMAPPED") {
  37779. geometry.setAttribute('normal', new BufferAttribute(new Float32Array(buffer), 3));
  37780. } else if (property === "NORMAL_OCT16") {
  37781. geometry.setAttribute('normal', new BufferAttribute(new Float32Array(buffer), 3));
  37782. } else if (property === "NORMAL") {
  37783. geometry.setAttribute('normal', new BufferAttribute(new Float32Array(buffer), 3));
  37784. } else if (property === "INDICES") {
  37785. let bufferAttribute = new BufferAttribute(new Uint8Array(buffer), 4);
  37786. bufferAttribute.normalized = true;
  37787. geometry.setAttribute('indices', bufferAttribute);
  37788. } else if (property === "SPACING") {
  37789. let bufferAttribute = new BufferAttribute(new Float32Array(buffer), 1);
  37790. geometry.setAttribute('spacing', bufferAttribute);
  37791. } else {
  37792. const bufferAttribute = new BufferAttribute(new Float32Array(buffer), 1);
  37793. bufferAttribute.potree = {
  37794. offset: buffers[property].offset,
  37795. scale: buffers[property].scale,
  37796. preciseBuffer: buffers[property].preciseBuffer,
  37797. range: batchAttribute.range,
  37798. };
  37799. geometry.setAttribute(property, bufferAttribute);
  37800. const attribute = pointAttributes.attributes.find(a => a.name === batchAttribute.name);
  37801. attribute.range[0] = Math.min(attribute.range[0], batchAttribute.range[0]);
  37802. attribute.range[1] = Math.max(attribute.range[1], batchAttribute.range[1]);
  37803. if(node.getLevel() === 0){
  37804. attribute.initialRange = batchAttribute.range;
  37805. }
  37806. }
  37807. }
  37808. tightBoundingBox.max.sub(tightBoundingBox.min);
  37809. tightBoundingBox.min.set(0, 0, 0);
  37810. let numPoints = e.data.buffer.byteLength / pointAttributes.byteSize;
  37811. node.numPoints = numPoints;
  37812. node.geometry = geometry;
  37813. node.mean = new Vector3(...data.mean);
  37814. node.tightBoundingBox = tightBoundingBox;
  37815. node.loaded = true;
  37816. node.loading = false;
  37817. node.estimatedSpacing = data.estimatedSpacing;
  37818. Potree.numNodesLoading--;
  37819. callback();//add
  37820. };
  37821. let message = {
  37822. buffer: buffer,
  37823. pointAttributes: pointAttributes,
  37824. version: this.version.version,
  37825. min: [ node.boundingBox.min.x, node.boundingBox.min.y, node.boundingBox.min.z ],
  37826. offset: [node.pcoGeometry.offset.x, node.pcoGeometry.offset.y, node.pcoGeometry.offset.z],
  37827. scale: this.scale,
  37828. spacing: node.spacing,
  37829. hasChildren: node.hasChildren,
  37830. name: node.name
  37831. };
  37832. worker.postMessage(message, [message.buffer]);
  37833. };
  37834. }
  37835. let ftCanvas = document.createElement('canvas');
  37836. const Features = (function () {
  37837. let gl = ftCanvas.getContext('webgl') || ftCanvas.getContext('experimental-webgl');
  37838. if (gl === null){
  37839. return null;
  37840. }
  37841. // -- code taken from THREE.WebGLRenderer --
  37842. let _vertexShaderPrecisionHighpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT);
  37843. let _vertexShaderPrecisionMediumpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT);
  37844. // Unused: let _vertexShaderPrecisionLowpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT);
  37845. let _fragmentShaderPrecisionHighpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
  37846. let _fragmentShaderPrecisionMediumpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT);
  37847. // Unused: let _fragmentShaderPrecisionLowpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT);
  37848. let highpAvailable = _vertexShaderPrecisionHighpFloat.precision > 0 && _fragmentShaderPrecisionHighpFloat.precision > 0;
  37849. let mediumpAvailable = _vertexShaderPrecisionMediumpFloat.precision > 0 && _fragmentShaderPrecisionMediumpFloat.precision > 0;
  37850. // -----------------------------------------
  37851. let precision;
  37852. if (highpAvailable) {
  37853. precision = 'highp';
  37854. } else if (mediumpAvailable) {
  37855. precision = 'mediump';
  37856. } else {
  37857. precision = 'lowp';
  37858. }
  37859. return {
  37860. SHADER_INTERPOLATION: {
  37861. isSupported: function () {
  37862. let supported = true;
  37863. supported = supported && gl.getExtension('EXT_frag_depth');
  37864. supported = supported && gl.getParameter(gl.MAX_VARYING_VECTORS) >= 8;
  37865. return supported;
  37866. }
  37867. },
  37868. SHADER_SPLATS: {
  37869. isSupported: function () {
  37870. let supported = true;
  37871. supported = supported && gl.getExtension('EXT_frag_depth');
  37872. supported = supported && gl.getExtension('OES_texture_float');
  37873. supported = supported && gl.getParameter(gl.MAX_VARYING_VECTORS) >= 8;
  37874. return supported;
  37875. }
  37876. },
  37877. SHADER_EDL: {
  37878. isSupported: function () {
  37879. let supported = true;
  37880. supported = supported && gl.getExtension('EXT_frag_depth');
  37881. supported = supported && gl.getExtension('OES_texture_float');
  37882. supported = supported && gl.getParameter(gl.MAX_VARYING_VECTORS) >= 8;
  37883. //supported = supported || (gl instanceof WebGL2RenderingContext);
  37884. return supported;
  37885. }
  37886. },
  37887. //WEBGL2: {
  37888. // isSupported: function(){
  37889. // return typeof WebGL2RenderingContext != 'undefined' && gl instanceof WebGL2RenderingContext;
  37890. // }
  37891. //},
  37892. precision: precision
  37893. };
  37894. }());
  37895. /**
  37896. * Some types of possible point attribute data formats
  37897. *
  37898. * @class
  37899. */
  37900. const PointAttributeTypes = {
  37901. DATA_TYPE_DOUBLE: {ordinal: 0, name: "double", size: 8},
  37902. DATA_TYPE_FLOAT: {ordinal: 1, name: "float", size: 4},
  37903. DATA_TYPE_INT8: {ordinal: 2, name: "int8", size: 1},
  37904. DATA_TYPE_UINT8: {ordinal: 3, name: "uint8", size: 1},
  37905. DATA_TYPE_INT16: {ordinal: 4, name: "int16", size: 2},
  37906. DATA_TYPE_UINT16: {ordinal: 5, name: "uint16", size: 2},
  37907. DATA_TYPE_INT32: {ordinal: 6, name: "int32", size: 4},
  37908. DATA_TYPE_UINT32: {ordinal: 7, name: "uint32", size: 4},
  37909. DATA_TYPE_INT64: {ordinal: 8, name: "int64", size: 8},
  37910. DATA_TYPE_UINT64: {ordinal: 9, name: "uint64", size: 8}
  37911. };
  37912. let i = 0;
  37913. for (let obj in PointAttributeTypes) {
  37914. PointAttributeTypes[i] = PointAttributeTypes[obj];
  37915. i++;
  37916. }
  37917. class PointAttribute{
  37918. constructor(name, type, numElements){
  37919. this.name = name;
  37920. this.type = type;
  37921. this.numElements = numElements;
  37922. this.byteSize = this.numElements * this.type.size;
  37923. this.description = "";
  37924. this.range = [Infinity, -Infinity];
  37925. }
  37926. };
  37927. PointAttribute.POSITION_CARTESIAN = new PointAttribute(
  37928. "POSITION_CARTESIAN", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  37929. PointAttribute.RGBA_PACKED = new PointAttribute(
  37930. "COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 4);
  37931. PointAttribute.COLOR_PACKED = PointAttribute.RGBA_PACKED;
  37932. PointAttribute.RGB_PACKED = new PointAttribute(
  37933. "COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 3);
  37934. PointAttribute.NORMAL_FLOATS = new PointAttribute(
  37935. "NORMAL_FLOATS", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  37936. PointAttribute.INTENSITY = new PointAttribute(
  37937. "INTENSITY", PointAttributeTypes.DATA_TYPE_UINT16, 1);
  37938. PointAttribute.CLASSIFICATION = new PointAttribute(
  37939. "CLASSIFICATION", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  37940. PointAttribute.NORMAL_SPHEREMAPPED = new PointAttribute(
  37941. "NORMAL_SPHEREMAPPED", PointAttributeTypes.DATA_TYPE_UINT8, 2);
  37942. PointAttribute.NORMAL_OCT16 = new PointAttribute(
  37943. "NORMAL_OCT16", PointAttributeTypes.DATA_TYPE_UINT8, 2);
  37944. PointAttribute.NORMAL = new PointAttribute(
  37945. "NORMAL", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  37946. PointAttribute.RETURN_NUMBER = new PointAttribute(
  37947. "RETURN_NUMBER", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  37948. PointAttribute.NUMBER_OF_RETURNS = new PointAttribute(
  37949. "NUMBER_OF_RETURNS", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  37950. PointAttribute.SOURCE_ID = new PointAttribute(
  37951. "SOURCE_ID", PointAttributeTypes.DATA_TYPE_UINT16, 1);
  37952. PointAttribute.INDICES = new PointAttribute(
  37953. "INDICES", PointAttributeTypes.DATA_TYPE_UINT32, 1);
  37954. PointAttribute.SPACING = new PointAttribute(
  37955. "SPACING", PointAttributeTypes.DATA_TYPE_FLOAT, 1);
  37956. PointAttribute.GPS_TIME = new PointAttribute(
  37957. "GPS_TIME", PointAttributeTypes.DATA_TYPE_DOUBLE, 1);
  37958. class PointAttributes{
  37959. constructor(pointAttributes){
  37960. this.attributes = [];
  37961. this.byteSize = 0;
  37962. this.size = 0;
  37963. this.vectors = [];
  37964. if (pointAttributes != null) {
  37965. for (let i = 0; i < pointAttributes.length; i++) {
  37966. let pointAttributeName = pointAttributes[i];
  37967. let pointAttribute = PointAttribute[pointAttributeName];
  37968. this.attributes.push(pointAttribute);
  37969. this.byteSize += pointAttribute.byteSize;
  37970. this.size++;
  37971. }
  37972. }
  37973. }
  37974. add(pointAttribute){
  37975. this.attributes.push(pointAttribute);
  37976. this.byteSize += pointAttribute.byteSize;
  37977. this.size++;
  37978. };
  37979. addVector(vector){
  37980. this.vectors.push(vector);
  37981. }
  37982. hasNormals(){
  37983. for (let name in this.attributes) {
  37984. let pointAttribute = this.attributes[name];
  37985. if (
  37986. pointAttribute === PointAttribute.NORMAL_SPHEREMAPPED ||
  37987. pointAttribute === PointAttribute.NORMAL_FLOATS ||
  37988. pointAttribute === PointAttribute.NORMAL ||
  37989. pointAttribute === PointAttribute.NORMAL_OCT16) {
  37990. return true;
  37991. }
  37992. }
  37993. return false;
  37994. };
  37995. }
  37996. class Points$1 {
  37997. constructor () {
  37998. this.boundingBox = new Box3();
  37999. this.numPoints = 0;
  38000. this.data = {};
  38001. }
  38002. add (points) {
  38003. let currentSize = this.numPoints;
  38004. let additionalSize = points.numPoints;
  38005. let newSize = currentSize + additionalSize;
  38006. let thisAttributes = Object.keys(this.data);
  38007. let otherAttributes = Object.keys(points.data);
  38008. let attributes = new Set([...thisAttributes, ...otherAttributes]);
  38009. for (let attribute of attributes) {
  38010. if (thisAttributes.includes(attribute) && otherAttributes.includes(attribute)) {
  38011. // attribute in both, merge
  38012. let Type = this.data[attribute].constructor;
  38013. let merged = new Type(this.data[attribute].length + points.data[attribute].length);
  38014. merged.set(this.data[attribute], 0);
  38015. merged.set(points.data[attribute], this.data[attribute].length);
  38016. this.data[attribute] = merged;
  38017. } else if (thisAttributes.includes(attribute) && !otherAttributes.includes(attribute)) {
  38018. // attribute only in this; take over this and expand to new size
  38019. let elementsPerPoint = this.data[attribute].length / this.numPoints;
  38020. let Type = this.data[attribute].constructor;
  38021. let expanded = new Type(elementsPerPoint * newSize);
  38022. expanded.set(this.data[attribute], 0);
  38023. this.data[attribute] = expanded;
  38024. } else if (!thisAttributes.includes(attribute) && otherAttributes.includes(attribute)) {
  38025. // attribute only in points to be added; take over new points and expand to new size
  38026. let elementsPerPoint = points.data[attribute].length / points.numPoints;
  38027. let Type = points.data[attribute].constructor;
  38028. let expanded = new Type(elementsPerPoint * newSize);
  38029. expanded.set(points.data[attribute], elementsPerPoint * currentSize);
  38030. this.data[attribute] = expanded;
  38031. }
  38032. }
  38033. this.numPoints = newSize;
  38034. this.boundingBox.union(points.boundingBox);
  38035. }
  38036. }
  38037. class CSVExporter {
  38038. static toString (points) {
  38039. let string = '';
  38040. let attributes = Object.keys(points.data)
  38041. .filter(a => a !== 'normal')
  38042. .sort((a, b) => {
  38043. if (a === 'position') return -1;
  38044. if (b === 'position') return 1;
  38045. if (a === 'rgba') return -1;
  38046. if (b === 'rgba') return 1;
  38047. });
  38048. let headerValues = [];
  38049. for (let attribute of attributes) {
  38050. let itemSize = points.data[attribute].length / points.numPoints;
  38051. if (attribute === 'position') {
  38052. headerValues = headerValues.concat(['x', 'y', 'z']);
  38053. } else if (attribute === 'rgba') {
  38054. headerValues = headerValues.concat(['r', 'g', 'b', 'a']);
  38055. } else if (itemSize > 1) {
  38056. for (let i = 0; i < itemSize; i++) {
  38057. headerValues.push(`${attribute}_${i}`);
  38058. }
  38059. } else {
  38060. headerValues.push(attribute);
  38061. }
  38062. }
  38063. string = headerValues.join(', ') + '\n';
  38064. for (let i = 0; i < points.numPoints; i++) {
  38065. let values = [];
  38066. for (let attribute of attributes) {
  38067. let itemSize = points.data[attribute].length / points.numPoints;
  38068. let value = points.data[attribute]
  38069. .subarray(itemSize * i, itemSize * i + itemSize)
  38070. .join(', ');
  38071. values.push(value);
  38072. }
  38073. string += values.join(', ') + '\n';
  38074. }
  38075. return string;
  38076. }
  38077. };
  38078. class LASExporter {
  38079. static toLAS (points) {
  38080. // TODO Unused: let string = '';
  38081. let boundingBox = points.boundingBox;
  38082. let offset = boundingBox.min.clone();
  38083. let diagonal = boundingBox.min.distanceTo(boundingBox.max);
  38084. let scale = new Vector3(0.001, 0.001, 0.001);
  38085. if (diagonal > 1000 * 1000) {
  38086. scale = new Vector3(0.01, 0.01, 0.01);
  38087. } else {
  38088. scale = new Vector3(0.001, 0.001, 0.001);
  38089. }
  38090. let setString = function (string, offset, buffer) {
  38091. let view = new Uint8Array(buffer);
  38092. for (let i = 0; i < string.length; i++) {
  38093. let charCode = string.charCodeAt(i);
  38094. view[offset + i] = charCode;
  38095. }
  38096. };
  38097. let buffer = new ArrayBuffer(227 + 28 * points.numPoints);
  38098. let view = new DataView(buffer);
  38099. let u8View = new Uint8Array(buffer);
  38100. // let u16View = new Uint16Array(buffer);
  38101. setString('LASF', 0, buffer);
  38102. u8View[24] = 1;
  38103. u8View[25] = 2;
  38104. // system identifier o:26 l:32
  38105. // generating software o:58 l:32
  38106. setString('Potree 1.7', 58, buffer);
  38107. // file creation day of year o:90 l:2
  38108. // file creation year o:92 l:2
  38109. // header size o:94 l:2
  38110. view.setUint16(94, 227, true);
  38111. // offset to point data o:96 l:4
  38112. view.setUint32(96, 227, true);
  38113. // number of letiable length records o:100 l:4
  38114. // point data record format 104 1
  38115. u8View[104] = 2;
  38116. // point data record length 105 2
  38117. view.setUint16(105, 28, true);
  38118. // number of point records 107 4
  38119. view.setUint32(107, points.numPoints, true);
  38120. // number of points by return 111 20
  38121. // x scale factor 131 8
  38122. view.setFloat64(131, scale.x, true);
  38123. // y scale factor 139 8
  38124. view.setFloat64(139, scale.y, true);
  38125. // z scale factor 147 8
  38126. view.setFloat64(147, scale.z, true);
  38127. // x offset 155 8
  38128. view.setFloat64(155, offset.x, true);
  38129. // y offset 163 8
  38130. view.setFloat64(163, offset.y, true);
  38131. // z offset 171 8
  38132. view.setFloat64(171, offset.z, true);
  38133. // max x 179 8
  38134. view.setFloat64(179, boundingBox.max.x, true);
  38135. // min x 187 8
  38136. view.setFloat64(187, boundingBox.min.x, true);
  38137. // max y 195 8
  38138. view.setFloat64(195, boundingBox.max.y, true);
  38139. // min y 203 8
  38140. view.setFloat64(203, boundingBox.min.y, true);
  38141. // max z 211 8
  38142. view.setFloat64(211, boundingBox.max.z, true);
  38143. // min z 219 8
  38144. view.setFloat64(219, boundingBox.min.z, true);
  38145. let boffset = 227;
  38146. for (let i = 0; i < points.numPoints; i++) {
  38147. let px = points.data.position[3 * i + 0];
  38148. let py = points.data.position[3 * i + 1];
  38149. let pz = points.data.position[3 * i + 2];
  38150. let ux = parseInt((px - offset.x) / scale.x);
  38151. let uy = parseInt((py - offset.y) / scale.y);
  38152. let uz = parseInt((pz - offset.z) / scale.z);
  38153. view.setUint32(boffset + 0, ux, true);
  38154. view.setUint32(boffset + 4, uy, true);
  38155. view.setUint32(boffset + 8, uz, true);
  38156. if (points.data.intensity) {
  38157. view.setUint16(boffset + 12, (points.data.intensity[i]), true);
  38158. }
  38159. let rt = 0;
  38160. if (points.data.returnNumber) {
  38161. rt += points.data.returnNumber[i];
  38162. }
  38163. if (points.data.numberOfReturns) {
  38164. rt += (points.data.numberOfReturns[i] << 3);
  38165. }
  38166. view.setUint8(boffset + 14, rt);
  38167. if (points.data.classification) {
  38168. view.setUint8(boffset + 15, points.data.classification[i]);
  38169. }
  38170. // scan angle rank
  38171. // user data
  38172. // point source id
  38173. if (points.data.pointSourceID) {
  38174. view.setUint16(boffset + 18, points.data.pointSourceID[i]);
  38175. }
  38176. if (points.data.rgba) {
  38177. let rgba = points.data.rgba;
  38178. view.setUint16(boffset + 20, (rgba[4 * i + 0] * 255), true);
  38179. view.setUint16(boffset + 22, (rgba[4 * i + 1] * 255), true);
  38180. view.setUint16(boffset + 24, (rgba[4 * i + 2] * 255), true);
  38181. }
  38182. boffset += 28;
  38183. }
  38184. return buffer;
  38185. }
  38186. }
  38187. /**
  38188. * @author mrdoob / http://mrdoob.com/ https://github.com/mrdoob/eventdispatcher.js
  38189. *
  38190. * with slight modifications by mschuetz, http://potree.org
  38191. *
  38192. */
  38193. // The MIT License
  38194. //
  38195. // Copyright (c) 2011 Mr.doob
  38196. //
  38197. // Permission is hereby granted, free of charge, to any person obtaining a copy
  38198. // of this software and associated documentation files (the "Software"), to deal
  38199. // in the Software without restriction, including without limitation the rights
  38200. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  38201. // copies of the Software, and to permit persons to whom the Software is
  38202. // furnished to do so, subject to the following conditions:
  38203. //
  38204. // The above copyright notice and this permission notice shall be included in
  38205. // all copies or substantial portions of the Software.
  38206. //
  38207. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  38208. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  38209. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  38210. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  38211. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  38212. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  38213. // THE SOFTWARE.
  38214. class EventDispatcher$1{
  38215. constructor(){
  38216. this._listeners = {};
  38217. }
  38218. addEventListener(type, listener){
  38219. const listeners = this._listeners;
  38220. if(listeners[type] === undefined){
  38221. listeners[type] = [];
  38222. }
  38223. if(listeners[type].indexOf(listener) === - 1){
  38224. listeners[type].push( listener );
  38225. }
  38226. }
  38227. hasEventListener(type, listener){
  38228. const listeners = this._listeners;
  38229. return listeners[type] !== undefined && listeners[type].indexOf(listener) !== - 1;
  38230. }
  38231. removeEventListener(type, listener){
  38232. let listeners = this._listeners;
  38233. let listenerArray = listeners[type];
  38234. if (listenerArray !== undefined){
  38235. let index = listenerArray.indexOf(listener);
  38236. if(index !== - 1){
  38237. listenerArray.splice(index, 1);
  38238. }
  38239. }
  38240. }
  38241. removeEventListeners(type){
  38242. if(this._listeners[type] !== undefined){
  38243. delete this._listeners[type];
  38244. }
  38245. };
  38246. dispatchEvent(event){
  38247. let listeners = this._listeners;
  38248. let listenerArray = listeners[event.type];
  38249. if ( listenerArray !== undefined ) {
  38250. event.target = this;
  38251. for(let listener of listenerArray.slice(0)){
  38252. listener.call(this, event);
  38253. }
  38254. }
  38255. }
  38256. }
  38257. class PointCloudTreeNode extends EventDispatcher$1{
  38258. constructor(){
  38259. super();
  38260. this.needsTransformUpdate = true;
  38261. }
  38262. getChildren () {
  38263. throw new Error('override function');
  38264. }
  38265. getBoundingBox () {
  38266. throw new Error('override function');
  38267. }
  38268. isLoaded () {
  38269. throw new Error('override function');
  38270. }
  38271. isGeometryNode () {
  38272. throw new Error('override function');
  38273. }
  38274. isTreeNode () {
  38275. throw new Error('override function');
  38276. }
  38277. getLevel () {
  38278. throw new Error('override function');
  38279. }
  38280. getBoundingSphere () {
  38281. throw new Error('override function');
  38282. }
  38283. };
  38284. class PointCloudTree extends Object3D {
  38285. constructor () {
  38286. super();
  38287. //this.spriteGroup = new THREE.Object3D //add
  38288. }
  38289. initialized () {
  38290. return this.root !== null;
  38291. }
  38292. };
  38293. class PointCloudOctreeGeometry{
  38294. constructor(){
  38295. this.url = null;
  38296. this.octreeDir = null;
  38297. this.spacing = 0;
  38298. this.boundingBox = null;
  38299. this.root = null;
  38300. this.nodes = null;
  38301. this.pointAttributes = null;
  38302. this.hierarchyStepSize = -1;
  38303. this.loader = null;
  38304. }
  38305. }
  38306. class PointCloudOctreeGeometryNode extends PointCloudTreeNode{
  38307. constructor(name, pcoGeometry, boundingBox){
  38308. super();
  38309. this.id = PointCloudOctreeGeometryNode.IDCount++;
  38310. this.name = name;
  38311. this.index = parseInt(name.charAt(name.length - 1));
  38312. this.pcoGeometry = pcoGeometry;
  38313. this.geometry = null;
  38314. this.boundingBox = boundingBox;
  38315. this.boundingSphere = boundingBox.getBoundingSphere(new Sphere());
  38316. this.children = {};
  38317. this.numPoints = 0;
  38318. this.level = null;
  38319. this.loaded = false;
  38320. this.oneTimeDisposeHandlers = [];
  38321. }
  38322. isGeometryNode(){
  38323. return true;
  38324. }
  38325. getLevel(){
  38326. return this.level;
  38327. }
  38328. isTreeNode(){
  38329. return false;
  38330. }
  38331. isLoaded(){
  38332. return this.loaded;
  38333. }
  38334. getBoundingSphere(){
  38335. return this.boundingSphere;
  38336. }
  38337. getBoundingBox(){
  38338. return this.boundingBox;
  38339. }
  38340. getChildren(){
  38341. let children = [];
  38342. for (let i = 0; i < 8; i++) {
  38343. if (this.children[i]) {
  38344. children.push(this.children[i]);
  38345. }
  38346. }
  38347. return children;
  38348. }
  38349. getBoundingBox(){
  38350. return this.boundingBox;
  38351. }
  38352. getURL(){
  38353. let url = '';
  38354. let version = this.pcoGeometry.loader.version;
  38355. if (version.equalOrHigher('1.5')) {
  38356. url = this.pcoGeometry.octreeDir + '/' + this.getHierarchyPath() + '/' + this.name;
  38357. } else if (version.equalOrHigher('1.4')) {
  38358. url = this.pcoGeometry.octreeDir + '/' + this.name;
  38359. } else if (version.upTo('1.3')) {
  38360. url = this.pcoGeometry.octreeDir + '/' + this.name;
  38361. }
  38362. return url;
  38363. }
  38364. getHierarchyPath(){
  38365. let path = 'r/';
  38366. let hierarchyStepSize = this.pcoGeometry.hierarchyStepSize;
  38367. let indices = this.name.substr(1);
  38368. let numParts = Math.floor(indices.length / hierarchyStepSize);
  38369. for (let i = 0; i < numParts; i++) {
  38370. path += indices.substr(i * hierarchyStepSize, hierarchyStepSize) + '/';
  38371. }
  38372. path = path.slice(0, -1);
  38373. return path;
  38374. }
  38375. addChild(child) {
  38376. this.children[child.index] = child;
  38377. child.parent = this;
  38378. }
  38379. load(){
  38380. if (this.loading === true || this.loaded === true || Potree.numNodesLoading >= Potree.maxNodesLoading) {
  38381. return;
  38382. }
  38383. this.loading = true;
  38384. Potree.numNodesLoading++;
  38385. if (this.pcoGeometry.loader.version.equalOrHigher('1.5')) {
  38386. if ((this.level % this.pcoGeometry.hierarchyStepSize) === 0 && this.hasChildren) {
  38387. this.loadHierachyThenPoints();
  38388. } else {
  38389. this.loadPoints();
  38390. }
  38391. } else {
  38392. this.loadPoints();
  38393. }
  38394. }
  38395. loadPoints(){
  38396. this.pcoGeometry.loader.load(this);
  38397. }
  38398. loadHierachyThenPoints(){//旧的 新的见shim
  38399. let node = this;
  38400. // load hierarchy
  38401. let callback = function (node, hbuffer) {
  38402. let tStart = performance.now();
  38403. let view = new DataView(hbuffer);
  38404. let stack = [];
  38405. let children = view.getUint8(0);
  38406. let numPoints = view.getUint32(1, true);
  38407. node.numPoints = numPoints;
  38408. stack.push({children: children, numPoints: numPoints, name: node.name});
  38409. let decoded = [];
  38410. let offset = 5;
  38411. while (stack.length > 0) {
  38412. let snode = stack.shift();
  38413. let mask = 1;
  38414. for (let i = 0; i < 8; i++) {
  38415. if ((snode.children & mask) !== 0) {
  38416. let childName = snode.name + i;
  38417. let childChildren = view.getUint8(offset);
  38418. let childNumPoints = view.getUint32(offset + 1, true);
  38419. stack.push({children: childChildren, numPoints: childNumPoints, name: childName});
  38420. decoded.push({children: childChildren, numPoints: childNumPoints, name: childName});
  38421. offset += 5;
  38422. }
  38423. mask = mask * 2;
  38424. }
  38425. if (offset === hbuffer.byteLength) {
  38426. break;
  38427. }
  38428. }
  38429. // console.log(decoded);
  38430. let nodes = {};
  38431. nodes[node.name] = node;
  38432. let pco = node.pcoGeometry;
  38433. for (let i = 0; i < decoded.length; i++) {
  38434. let name = decoded[i].name;
  38435. let decodedNumPoints = decoded[i].numPoints;
  38436. let index = parseInt(name.charAt(name.length - 1));
  38437. let parentName = name.substring(0, name.length - 1);
  38438. let parentNode = nodes[parentName];
  38439. let level = name.length - 1;
  38440. let boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
  38441. let currentNode = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
  38442. currentNode.level = level;
  38443. currentNode.numPoints = decodedNumPoints;
  38444. currentNode.hasChildren = decoded[i].children > 0;
  38445. currentNode.spacing = pco.spacing / Math.pow(2, level);
  38446. parentNode.addChild(currentNode);
  38447. nodes[name] = currentNode;
  38448. }
  38449. let duration = performance.now() - tStart;
  38450. if(duration > 5){
  38451. let msg = `duration: ${duration}ms, numNodes: ${decoded.length}`;
  38452. console.log(msg);
  38453. }
  38454. node.loadPoints();
  38455. };
  38456. if ((node.level % node.pcoGeometry.hierarchyStepSize) === 0) {
  38457. // let hurl = node.pcoGeometry.octreeDir + "/../hierarchy/" + node.name + ".hrc";
  38458. let hurl = node.pcoGeometry.octreeDir + '/' + node.getHierarchyPath() + '/' + node.name + '.hrc';
  38459. let xhr = XHRFactory.createXMLHttpRequest();
  38460. xhr.open('GET', hurl, true);
  38461. xhr.responseType = 'arraybuffer';
  38462. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  38463. xhr.onreadystatechange = () => {
  38464. if (xhr.readyState === 4) {
  38465. if (xhr.status === 200 || xhr.status === 0) {
  38466. let hbuffer = xhr.response;
  38467. callback(node, hbuffer);
  38468. } else {
  38469. console.log('Failed to load file! HTTP status: ' + xhr.status + ', file: ' + hurl);
  38470. Potree.numNodesLoading--;
  38471. }
  38472. }
  38473. };
  38474. try {
  38475. xhr.send(null);
  38476. } catch (e) {
  38477. console.log('fehler beim laden der punktwolke: ' + e);
  38478. }
  38479. }
  38480. }
  38481. getNumPoints(){
  38482. return this.numPoints;
  38483. }
  38484. dispose(){
  38485. if (this.geometry && this.parent != null) {
  38486. this.geometry.dispose();
  38487. this.geometry = null;
  38488. this.loaded = false;
  38489. this.dispatchEvent( { type: 'dispose' } );
  38490. for (let i = 0; i < this.oneTimeDisposeHandlers.length; i++) {
  38491. let handler = this.oneTimeDisposeHandlers[i];
  38492. handler();
  38493. }
  38494. this.oneTimeDisposeHandlers = [];
  38495. }
  38496. }
  38497. }
  38498. PointCloudOctreeGeometryNode.IDCount = 0;
  38499. // -------------------------------------------
  38500. // to get a ready to use gradient array from a chroma.js gradient:
  38501. // http://gka.github.io/chroma.js/
  38502. // -------------------------------------------
  38503. //
  38504. // let stops = [];
  38505. // for(let i = 0; i <= 10; i++){
  38506. // let range = chroma.scale(['yellow', 'navy']).mode('lch').domain([10,0])(i)._rgb
  38507. // .slice(0, 3)
  38508. // .map(v => (v / 255).toFixed(4))
  38509. // .join(", ");
  38510. //
  38511. // let line = `[${i / 10}, new THREE.Color(${range})],`;
  38512. //
  38513. // stops.push(line);
  38514. // }
  38515. // stops.join("\n");
  38516. //
  38517. //
  38518. //
  38519. // -------------------------------------------
  38520. // to get a ready to use gradient array from matplotlib:
  38521. // -------------------------------------------
  38522. // import matplotlib.pyplot as plt
  38523. // import matplotlib.colors as colors
  38524. //
  38525. // norm = colors.Normalize(vmin=0,vmax=1)
  38526. // cmap = plt.cm.viridis
  38527. //
  38528. // for i in range(0,11):
  38529. // u = i / 10
  38530. // rgb = cmap(norm(u))[0:3]
  38531. // rgb = ["{0:.3f}".format(v) for v in rgb]
  38532. // rgb = "[" + str(u) + ", new THREE.Color(" + ", ".join(rgb) + ")],"
  38533. // print(rgb)
  38534. let Gradients = {
  38535. // From chroma spectral http://gka.github.io/chroma.js/
  38536. SPECTRAL: [
  38537. [0, new Color(0.3686, 0.3098, 0.6353)],
  38538. [0.1, new Color(0.1961, 0.5333, 0.7412)],
  38539. [0.2, new Color(0.4000, 0.7608, 0.6471)],
  38540. [0.3, new Color(0.6706, 0.8667, 0.6431)],
  38541. [0.4, new Color(0.9020, 0.9608, 0.5961)],
  38542. [0.5, new Color(1.0000, 1.0000, 0.7490)],
  38543. [0.6, new Color(0.9961, 0.8784, 0.5451)],
  38544. [0.7, new Color(0.9922, 0.6824, 0.3804)],
  38545. [0.8, new Color(0.9569, 0.4275, 0.2627)],
  38546. [0.9, new Color(0.8353, 0.2431, 0.3098)],
  38547. [1, new Color(0.6196, 0.0039, 0.2588)]
  38548. ],
  38549. PLASMA: [
  38550. [0.0, new Color(0.241, 0.015, 0.610)],
  38551. [0.1, new Color(0.387, 0.001, 0.654)],
  38552. [0.2, new Color(0.524, 0.025, 0.653)],
  38553. [0.3, new Color(0.651, 0.125, 0.596)],
  38554. [0.4, new Color(0.752, 0.227, 0.513)],
  38555. [0.5, new Color(0.837, 0.329, 0.431)],
  38556. [0.6, new Color(0.907, 0.435, 0.353)],
  38557. [0.7, new Color(0.963, 0.554, 0.272)],
  38558. [0.8, new Color(0.992, 0.681, 0.195)],
  38559. [0.9, new Color(0.987, 0.822, 0.144)],
  38560. [1.0, new Color(0.940, 0.975, 0.131)]
  38561. ],
  38562. YELLOW_GREEN: [
  38563. [0, new Color(0.1647, 0.2824, 0.3451)],
  38564. [0.1, new Color(0.1338, 0.3555, 0.4227)],
  38565. [0.2, new Color(0.0610, 0.4319, 0.4864)],
  38566. [0.3, new Color(0.0000, 0.5099, 0.5319)],
  38567. [0.4, new Color(0.0000, 0.5881, 0.5569)],
  38568. [0.5, new Color(0.1370, 0.6650, 0.5614)],
  38569. [0.6, new Color(0.2906, 0.7395, 0.5477)],
  38570. [0.7, new Color(0.4453, 0.8099, 0.5201)],
  38571. [0.8, new Color(0.6102, 0.8748, 0.4850)],
  38572. [0.9, new Color(0.7883, 0.9323, 0.4514)],
  38573. [1, new Color(0.9804, 0.9804, 0.4314)]
  38574. ],
  38575. VIRIDIS: [
  38576. [0.0, new Color(0.267, 0.005, 0.329)],
  38577. [0.1, new Color(0.283, 0.141, 0.458)],
  38578. [0.2, new Color(0.254, 0.265, 0.530)],
  38579. [0.3, new Color(0.207, 0.372, 0.553)],
  38580. [0.4, new Color(0.164, 0.471, 0.558)],
  38581. [0.5, new Color(0.128, 0.567, 0.551)],
  38582. [0.6, new Color(0.135, 0.659, 0.518)],
  38583. [0.7, new Color(0.267, 0.749, 0.441)],
  38584. [0.8, new Color(0.478, 0.821, 0.318)],
  38585. [0.9, new Color(0.741, 0.873, 0.150)],
  38586. [1.0, new Color(0.993, 0.906, 0.144)]
  38587. ],
  38588. INFERNO: [
  38589. [0.0, new Color(0.077, 0.042, 0.206)],
  38590. [0.1, new Color(0.225, 0.036, 0.388)],
  38591. [0.2, new Color(0.373, 0.074, 0.432)],
  38592. [0.3, new Color(0.522, 0.128, 0.420)],
  38593. [0.4, new Color(0.665, 0.182, 0.370)],
  38594. [0.5, new Color(0.797, 0.255, 0.287)],
  38595. [0.6, new Color(0.902, 0.364, 0.184)],
  38596. [0.7, new Color(0.969, 0.516, 0.063)],
  38597. [0.8, new Color(0.988, 0.683, 0.072)],
  38598. [0.9, new Color(0.961, 0.859, 0.298)],
  38599. [1.0, new Color(0.988, 0.998, 0.645)]
  38600. ],
  38601. GRAYSCALE: [
  38602. [0, new Color(0, 0, 0)],
  38603. [1, new Color(1, 1, 1)]
  38604. ],
  38605. // 16 samples of the TURBU color scheme
  38606. // values taken from: https://gist.github.com/mikhailov-work/ee72ba4191942acecc03fe6da94fc73f
  38607. // original file licensed under Apache-2.0
  38608. TURBO: [
  38609. [0.00, new Color(0.18995, 0.07176, 0.23217)],
  38610. [0.07, new Color(0.25107, 0.25237, 0.63374)],
  38611. [0.13, new Color(0.27628, 0.42118, 0.89123)],
  38612. [0.20, new Color(0.25862, 0.57958, 0.99876)],
  38613. [0.27, new Color(0.15844, 0.73551, 0.92305)],
  38614. [0.33, new Color(0.09267, 0.86554, 0.7623)],
  38615. [0.40, new Color(0.19659, 0.94901, 0.59466)],
  38616. [0.47, new Color(0.42778, 0.99419, 0.38575)],
  38617. [0.53, new Color(0.64362, 0.98999, 0.23356)],
  38618. [0.60, new Color(0.80473, 0.92452, 0.20459)],
  38619. [0.67, new Color(0.93301, 0.81236, 0.22667)],
  38620. [0.73, new Color(0.99314, 0.67408, 0.20348)],
  38621. [0.80, new Color(0.9836, 0.49291, 0.12849)],
  38622. [0.87, new Color(0.92105, 0.31489, 0.05475)],
  38623. [0.93, new Color(0.81608, 0.18462, 0.01809)],
  38624. [1.00, new Color(0.66449, 0.08436, 0.00424)],
  38625. ],
  38626. RAINBOW: [
  38627. [0, new Color(0.278, 0, 0.714)],
  38628. [1 / 6, new Color(0, 0, 1)],
  38629. [2 / 6, new Color(0, 1, 1)],
  38630. [3 / 6, new Color(0, 1, 0)],
  38631. [4 / 6, new Color(1, 1, 0)],
  38632. [5 / 6, new Color(1, 0.64, 0)],
  38633. [1, new Color(1, 0, 0)]
  38634. ],
  38635. CONTOUR: [
  38636. [0.00, new Color(0, 0, 0)],
  38637. [0.03, new Color(0, 0, 0)],
  38638. [0.04, new Color(1, 1, 1)],
  38639. [1.00, new Color(1, 1, 1)]
  38640. ],
  38641. };
  38642. let Shaders = {};
  38643. Shaders["pointcloud_new.vs"] = `
  38644. precision highp float;
  38645. precision highp int;
  38646. #define max_clip_polygons 8
  38647. #define PI 3.141592653589793
  38648. #if defined(usePanoMap)
  38649. uniform samplerCube pano0Map; //随便设置一个samplerCube去使用都会让点云消失
  38650. uniform samplerCube pano1Map;
  38651. uniform float progress;
  38652. uniform float easeInOutRatio;
  38653. uniform vec3 pano0Position;
  38654. uniform mat4 pano0Matrix;
  38655. uniform vec3 pano1Position;
  38656. uniform mat4 pano1Matrix;
  38657. /*
  38658. varying vec3 vWorldPosition0;
  38659. varying vec3 vWorldPosition1;
  38660. */
  38661. #endif
  38662. //--------------
  38663. attribute vec3 position;
  38664. attribute vec3 color;
  38665. attribute float intensity;
  38666. attribute float classification;
  38667. attribute float returnNumber;
  38668. attribute float numberOfReturns;
  38669. attribute float pointSourceID;
  38670. attribute vec4 indices; //每个点的index
  38671. attribute float spacing;
  38672. attribute float gpsTime;
  38673. attribute vec3 normal;
  38674. attribute float aExtra;
  38675. uniform mat4 modelMatrix;
  38676. uniform mat4 modelViewMatrix;
  38677. uniform mat4 projectionMatrix;
  38678. uniform mat4 viewMatrix;
  38679. uniform mat4 uViewInv;
  38680. //uniform float uScreenWidth;
  38681. //uniform float uScreenHeight;
  38682. uniform vec2 resolution;
  38683. uniform float fov;
  38684. uniform float near;
  38685. uniform float far;
  38686. uniform bool uDebug;
  38687. uniform bool uUseOrthographicCamera;
  38688. uniform float uOrthoWidth;
  38689. uniform float uOrthoHeight;
  38690. #define CLIPTASK_NONE 0
  38691. #define CLIPTASK_HIGHLIGHT 1
  38692. #define CLIPTASK_SHOW_INSIDE 2
  38693. #define CLIPTASK_SHOW_OUTSIDE 3
  38694. #define CLIPMETHOD_INSIDE_ANY 0
  38695. #define CLIPMETHOD_INSIDE_ALL 1
  38696. //最外层裁剪(下载)
  38697. #if defined(bigClipInBox)
  38698. uniform mat4 clipBoxBig_in;
  38699. #endif
  38700. //内层裁剪
  38701. #if defined(num_in_clipboxes) && num_in_clipboxes > 0
  38702. uniform mat4 clipBoxes_in[num_in_clipboxes];
  38703. #endif
  38704. #if defined(num_out_clipboxes) && num_out_clipboxes > 0
  38705. uniform mat4 clipBoxes_out[num_out_clipboxes];
  38706. #endif
  38707. #if defined(num_clipspheres) && num_clipspheres > 0
  38708. uniform mat4 uClipSpheres[num_clipspheres];
  38709. #endif
  38710. #if defined(num_highlightBox) && num_highlightBox > 0
  38711. uniform mat4 boxes_highlight[num_highlightBox];
  38712. #endif
  38713. uniform float size;
  38714. uniform float minSize;
  38715. uniform float maxSize;
  38716. uniform float uPCIndex;
  38717. uniform float uOctreeSpacing;
  38718. uniform float uNodeSpacing;
  38719. uniform float uOctreeSize;
  38720. uniform vec3 uBBSize;
  38721. uniform float uLevel;
  38722. uniform float uVNStart;
  38723. uniform bool uIsLeafNode;
  38724. uniform vec3 uColor;
  38725. uniform float uOpacity;
  38726. varying float vOpacity; //add
  38727. uniform vec2 elevationRange;
  38728. uniform vec2 intensityRange;
  38729. uniform vec2 uFilterReturnNumberRange;
  38730. uniform vec2 uFilterNumberOfReturnsRange;
  38731. uniform vec2 uFilterPointSourceIDClipRange;
  38732. uniform vec2 uFilterGPSTimeClipRange;
  38733. //uniform float ufilterByNormalThreshold;
  38734. uniform float uGpsScale;
  38735. uniform float uGpsOffset;
  38736. uniform vec2 uNormalizedGpsBufferRange;
  38737. uniform vec3 uIntensity_gbc;
  38738. uniform vec3 uRGB_gbc;
  38739. uniform vec3 uExtra_gbc;
  38740. uniform float uTransition;
  38741. uniform float wRGB;
  38742. uniform float wIntensity;
  38743. uniform float wElevation;
  38744. uniform float wClassification;
  38745. uniform float wReturnNumber;
  38746. uniform float wSourceID;
  38747. uniform vec2 uExtraNormalizedRange;
  38748. uniform vec2 uExtraRange;
  38749. uniform float uExtraScale;
  38750. uniform float uExtraOffset;
  38751. uniform vec3 uShadowColor;
  38752. uniform sampler2D visibleNodes;
  38753. uniform sampler2D gradient;
  38754. uniform sampler2D classificationLUT;
  38755. #if defined(color_type_matcap)
  38756. uniform sampler2D matcapTextureUniform;
  38757. #endif
  38758. uniform bool backfaceCulling;
  38759. #if defined(num_shadowmaps) && num_shadowmaps > 0
  38760. uniform sampler2D uShadowMap[num_shadowmaps];
  38761. uniform mat4 uShadowWorldView[num_shadowmaps];
  38762. uniform mat4 uShadowProj[num_shadowmaps];
  38763. #endif
  38764. varying vec3 vColor;
  38765. varying float vLogDepth;
  38766. varying vec3 vViewPosition;
  38767. varying float vRadius;
  38768. varying float vPointSize;
  38769. float round(float number){
  38770. return floor(number + 0.5);
  38771. }
  38772. //
  38773. // ### ######## ### ######## ######## #### ## ## ######## ###### #### ######## ######## ######
  38774. // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  38775. // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  38776. // ## ## ## ## ## ## ######## ## ## ## ## ###### ###### ## ## ###### ######
  38777. // ######### ## ## ######### ## ## ## ## ## ## ## ## ## ## ##
  38778. // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  38779. // ## ## ######## ## ## ## ## #### ### ######## ###### #### ######## ######## ######
  38780. //
  38781. // ---------------------
  38782. // OCTREE
  38783. // ---------------------
  38784. #if (defined(adaptive_point_size) || defined(color_type_level_of_detail)) && defined(tree_type_octree)
  38785. /**
  38786. * number of 1-bits up to inclusive index position
  38787. * number is treated as if it were an integer in the range 0-255
  38788. *
  38789. */
  38790. int numberOfOnes(int number, int index){
  38791. int numOnes = 0;
  38792. int tmp = 128;
  38793. for(int i = 7; i >= 0; i--){
  38794. if(number >= tmp){
  38795. number = number - tmp;
  38796. if(i <= index){
  38797. numOnes++;
  38798. }
  38799. }
  38800. tmp = tmp / 2;
  38801. }
  38802. return numOnes;
  38803. }
  38804. /**
  38805. * checks whether the bit at index is 1
  38806. * number is treated as if it were an integer in the range 0-255
  38807. *
  38808. */
  38809. bool isBitSet(int number, int index){
  38810. // weird multi else if due to lack of proper array, int and bitwise support in WebGL 1.0
  38811. int powi = 1;
  38812. if(index == 0){
  38813. powi = 1;
  38814. }else if(index == 1){
  38815. powi = 2;
  38816. }else if(index == 2){
  38817. powi = 4;
  38818. }else if(index == 3){
  38819. powi = 8;
  38820. }else if(index == 4){
  38821. powi = 16;
  38822. }else if(index == 5){
  38823. powi = 32;
  38824. }else if(index == 6){
  38825. powi = 64;
  38826. }else if(index == 7){
  38827. powi = 128;
  38828. }else{
  38829. return false;
  38830. }
  38831. int ndp = number / powi;
  38832. return mod(float(ndp), 2.0) != 0.0;
  38833. }
  38834. /**
  38835. * find the LOD at the point position
  38836. */
  38837. float getLOD(){//////
  38838. vec3 offset = vec3(0.0, 0.0, 0.0);
  38839. int iOffset = int(uVNStart);
  38840. float depth = uLevel;
  38841. for(float i = 0.0; i <= 30.0; i++){
  38842. float nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);
  38843. vec3 index3d = (position-offset) / nodeSizeAtLevel;
  38844. index3d = floor(index3d + 0.5);
  38845. int index = int(round(4.0 * index3d.x + 2.0 * index3d.y + index3d.z));
  38846. vec4 value = texture2D(visibleNodes, vec2(float(iOffset) / 2048.0, 0.0));
  38847. int mask = int(round(value.r * 255.0));
  38848. if(isBitSet(mask, index)){
  38849. // there are more visible child nodes at this position
  38850. int advanceG = int(round(value.g * 255.0)) * 256;
  38851. int advanceB = int(round(value.b * 255.0));
  38852. int advanceChild = numberOfOnes(mask, index - 1);
  38853. int advance = advanceG + advanceB + advanceChild;
  38854. iOffset = iOffset + advance;
  38855. depth++;
  38856. }else{
  38857. // no more visible child nodes at this position
  38858. //return value.a * 255.0;
  38859. float lodOffset = (255.0 * value.a) / 10.0 - 10.0;
  38860. return depth + lodOffset;
  38861. }
  38862. offset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;
  38863. }
  38864. return depth;
  38865. }
  38866. float getSpacing(){
  38867. vec3 offset = vec3(0.0, 0.0, 0.0);
  38868. int iOffset = int(uVNStart);
  38869. float depth = uLevel;
  38870. float spacing = uNodeSpacing;
  38871. for(float i = 0.0; i <= 30.0; i++){
  38872. float nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);
  38873. vec3 index3d = (position-offset) / nodeSizeAtLevel;
  38874. index3d = floor(index3d + 0.5);
  38875. int index = int(round(4.0 * index3d.x + 2.0 * index3d.y + index3d.z));
  38876. vec4 value = texture2D(visibleNodes, vec2(float(iOffset) / 2048.0, 0.0));
  38877. int mask = int(round(value.r * 255.0));
  38878. float spacingFactor = value.a;
  38879. if(i > 0.0){
  38880. spacing = spacing / (255.0 * spacingFactor);
  38881. }
  38882. if(isBitSet(mask, index)){
  38883. // there are more visible child nodes at this position
  38884. int advanceG = int(round(value.g * 255.0)) * 256;
  38885. int advanceB = int(round(value.b * 255.0));
  38886. int advanceChild = numberOfOnes(mask, index - 1);
  38887. int advance = advanceG + advanceB + advanceChild;
  38888. iOffset = iOffset + advance;
  38889. //spacing = spacing / (255.0 * spacingFactor);
  38890. //spacing = spacing / 3.0;
  38891. depth++;
  38892. }else{
  38893. // no more visible child nodes at this position
  38894. return spacing;
  38895. }
  38896. offset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;
  38897. }
  38898. return spacing;
  38899. }
  38900. float getPointSizeAttenuation(){
  38901. return pow(2.0, getLOD());
  38902. }
  38903. #endif
  38904. // ---------------------
  38905. // KD-TREE
  38906. // ---------------------
  38907. #if (defined(adaptive_point_size) || defined(color_type_level_of_detail)) && defined(tree_type_kdtree)
  38908. float getLOD(){
  38909. vec3 offset = vec3(0.0, 0.0, 0.0);
  38910. float iOffset = 0.0;
  38911. float depth = 0.0;
  38912. vec3 size = uBBSize;
  38913. vec3 pos = position;
  38914. for(float i = 0.0; i <= 1000.0; i++){
  38915. vec4 value = texture2D(visibleNodes, vec2(iOffset / 2048.0, 0.0));
  38916. int children = int(value.r * 255.0);
  38917. float next = value.g * 255.0;
  38918. int split = int(value.b * 255.0);
  38919. if(next == 0.0){
  38920. return depth;
  38921. }
  38922. vec3 splitv = vec3(0.0, 0.0, 0.0);
  38923. if(split == 1){
  38924. splitv.x = 1.0;
  38925. }else if(split == 2){
  38926. splitv.y = 1.0;
  38927. }else if(split == 4){
  38928. splitv.z = 1.0;
  38929. }
  38930. iOffset = iOffset + next;
  38931. float factor = length(pos * splitv / size);
  38932. if(factor < 0.5){
  38933. // left
  38934. if(children == 0 || children == 2){
  38935. return depth;
  38936. }
  38937. }else{
  38938. // right
  38939. pos = pos - size * splitv * 0.5;
  38940. if(children == 0 || children == 1){
  38941. return depth;
  38942. }
  38943. if(children == 3){
  38944. iOffset = iOffset + 1.0;
  38945. }
  38946. }
  38947. size = size * ((1.0 - (splitv + 1.0) / 2.0) + 0.5);
  38948. depth++;
  38949. }
  38950. return depth;
  38951. }
  38952. float getPointSizeAttenuation(){
  38953. return 0.5 * pow(1.3, getLOD());
  38954. }
  38955. #endif
  38956. //
  38957. // ### ######## ######## ######## #### ######## ## ## ######## ######## ######
  38958. // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  38959. // ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  38960. // ## ## ## ## ######## ## ######## ## ## ## ###### ######
  38961. // ######### ## ## ## ## ## ## ## ## ## ## ## ##
  38962. // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  38963. // ## ## ## ## ## ## #### ######## ####### ## ######## ######
  38964. //
  38965. // formula adapted from: http://www.dfstudios.co.uk/articles/programming/image-programming-algorithms/image-processing-algorithms-part-5-contrast-adjustment/
  38966. float getContrastFactor(float contrast){
  38967. return (1.0158730158730156 * (contrast + 1.0)) / (1.0158730158730156 - contrast);
  38968. }
  38969. vec3 getRGB(){
  38970. vec3 rgb = color;
  38971. rgb = pow(rgb, vec3(uRGB_gbc.x));
  38972. rgb = rgb + uRGB_gbc.y;
  38973. rgb = (rgb - 0.5) * getContrastFactor(uRGB_gbc.z) + 0.5;
  38974. rgb = clamp(rgb, 0.0, 1.0);
  38975. return rgb;
  38976. }
  38977. float getIntensity(){
  38978. float w = (intensity - intensityRange.x) / (intensityRange.y - intensityRange.x);
  38979. w = pow(w, uIntensity_gbc.x);
  38980. w = w + uIntensity_gbc.y;
  38981. w = (w - 0.5) * getContrastFactor(uIntensity_gbc.z) + 0.5;
  38982. w = clamp(w, 0.0, 1.0);
  38983. return w;
  38984. }
  38985. vec3 getGpsTime(){
  38986. float w = (gpsTime + uGpsOffset) * uGpsScale;
  38987. vec3 c = texture2D(gradient, vec2(w, 1.0 - w)).rgb;
  38988. // vec2 r = uNormalizedGpsBufferRange;
  38989. // float w = gpsTime * (r.y - r.x) + r.x;
  38990. // w = clamp(w, 0.0, 1.0);
  38991. // vec3 c = texture2D(gradient, vec2(w,1.0-w)).rgb;
  38992. return c;
  38993. }
  38994. vec3 getElevation(){
  38995. vec4 world = modelMatrix * vec4( position, 1.0 );
  38996. float w = (world.z - elevationRange.x) / (elevationRange.y - elevationRange.x);
  38997. vec3 cElevation = texture2D(gradient, vec2(w,1.0-w)).rgb;
  38998. return cElevation;
  38999. }
  39000. vec4 getClassification(){
  39001. vec2 uv = vec2(classification / 255.0, 0.5);
  39002. vec4 classColor = texture2D(classificationLUT, uv);
  39003. return classColor;
  39004. }
  39005. vec3 getReturns(){
  39006. // 0b 00_000_111
  39007. float rn = mod(returnNumber, 8.0);
  39008. // 0b 00_111_000
  39009. float nr = mod(returnNumber / 8.0, 8.0);
  39010. if(nr <= 1.0){
  39011. return vec3(1.0, 0.0, 0.0);
  39012. }else{
  39013. return vec3(0.0, 1.0, 0.0);
  39014. }
  39015. // return vec3(nr / 4.0, 0.0, 0.0);
  39016. // if(nr == 1.0){
  39017. // return vec3(1.0, 1.0, 0.0);
  39018. // }else{
  39019. // if(rn == 1.0){
  39020. // return vec3(1.0, 0.0, 0.0);
  39021. // }else if(rn == nr){
  39022. // return vec3(0.0, 0.0, 1.0);
  39023. // }else{
  39024. // return vec3(0.0, 1.0, 0.0);
  39025. // }
  39026. // }
  39027. // if(numberOfReturns == 1.0){
  39028. // return vec3(1.0, 1.0, 0.0);
  39029. // }else{
  39030. // if(returnNumber == 1.0){
  39031. // return vec3(1.0, 0.0, 0.0);
  39032. // }else if(returnNumber == numberOfReturns){
  39033. // return vec3(0.0, 0.0, 1.0);
  39034. // }else{
  39035. // return vec3(0.0, 1.0, 0.0);
  39036. // }
  39037. // }
  39038. }
  39039. vec3 getReturnNumber(){
  39040. if(numberOfReturns == 1.0){
  39041. return vec3(1.0, 1.0, 0.0);
  39042. }else{
  39043. if(returnNumber == 1.0){
  39044. return vec3(1.0, 0.0, 0.0);
  39045. }else if(returnNumber == numberOfReturns){
  39046. return vec3(0.0, 0.0, 1.0);
  39047. }else{
  39048. return vec3(0.0, 1.0, 0.0);
  39049. }
  39050. }
  39051. }
  39052. vec3 getNumberOfReturns(){
  39053. float value = numberOfReturns;
  39054. float w = value / 6.0;
  39055. vec3 color = texture2D(gradient, vec2(w, 1.0 - w)).rgb;
  39056. return color;
  39057. }
  39058. vec3 getSourceID(){
  39059. float w = mod(pointSourceID, 10.0) / 10.0;
  39060. return texture2D(gradient, vec2(w,1.0 - w)).rgb;
  39061. }
  39062. vec3 getCompositeColor(){
  39063. vec3 c;
  39064. float w;
  39065. c += wRGB * getRGB();
  39066. w += wRGB;
  39067. c += wIntensity * getIntensity() * vec3(1.0, 1.0, 1.0);
  39068. w += wIntensity;
  39069. c += wElevation * getElevation();
  39070. w += wElevation;
  39071. c += wReturnNumber * getReturnNumber();
  39072. w += wReturnNumber;
  39073. c += wSourceID * getSourceID();
  39074. w += wSourceID;
  39075. vec4 cl = wClassification * getClassification();
  39076. c += cl.a * cl.rgb;
  39077. w += wClassification * cl.a;
  39078. c = c / w;
  39079. if(w == 0.0){
  39080. //c = color;
  39081. gl_Position = vec4(100.0, 100.0, 100.0, 0.0);
  39082. }
  39083. return c;
  39084. }
  39085. vec3 getNormal(){
  39086. //vec3 n_hsv = vec3( modelMatrix * vec4( normal, 0.0 )) * 0.5 + 0.5; // (n_world.xyz + vec3(1.,1.,1.)) / 2.;
  39087. vec3 n_view = normalize( vec3(modelViewMatrix * vec4( normal, 0.0 )) );
  39088. return n_view;
  39089. }
  39090. bool applyBackfaceCulling() {
  39091. // Black not facing vertices / Backface culling
  39092. vec3 e = normalize(vec3(modelViewMatrix * vec4( position, 1. )));
  39093. vec3 n = getNormal(); // normalize( vec3(modelViewMatrix * vec4( normal, 0.0 )) );
  39094. if((uUseOrthographicCamera && n.z <= 0.) || (!uUseOrthographicCamera && dot( n, e ) >= 0.)) {
  39095. return true;
  39096. } else {
  39097. return false;
  39098. }
  39099. }
  39100. #if defined(color_type_matcap)
  39101. // Matcap Material
  39102. vec3 getMatcap(){
  39103. vec3 eye = normalize( vec3( modelViewMatrix * vec4( position, 1. ) ) );
  39104. if(uUseOrthographicCamera) {
  39105. eye = vec3(0., 0., -1.);
  39106. }
  39107. vec3 r_en = reflect( eye, getNormal() ); // or r_en = e - 2. * dot( n, e ) * n;
  39108. float m = 2. * sqrt(pow( r_en.x, 2. ) + pow( r_en.y, 2. ) + pow( r_en.z + 1., 2. ));
  39109. vec2 vN = r_en.xy / m + .5;
  39110. return texture2D(matcapTextureUniform, vN).rgb;
  39111. }
  39112. #endif
  39113. vec3 getExtra(){
  39114. float w = (aExtra + uExtraOffset) * uExtraScale;
  39115. w = clamp(w, 0.0, 1.0);
  39116. vec3 color = texture2D(gradient, vec2(w,1.0-w)).rgb;
  39117. // vec2 r = uExtraNormalizedRange;
  39118. // float w = aExtra * (r.y - r.x) + r.x;
  39119. // w = (w - uExtraRange.x) / (uExtraRange.y - uExtraRange.x);
  39120. // w = clamp(w, 0.0, 1.0);
  39121. // vec3 color = texture2D(gradient, vec2(w,1.0-w)).rgb;
  39122. return color;
  39123. }
  39124. vec3 getColor(){
  39125. vec3 color;
  39126. #ifdef color_type_rgba
  39127. color = getRGB();
  39128. #elif defined color_type_height || defined color_type_elevation
  39129. color = getElevation();
  39130. #elif defined color_type_rgb_height
  39131. vec3 cHeight = getElevation();
  39132. color = (1.0 - uTransition) * getRGB() + uTransition * cHeight;
  39133. #elif defined color_type_depth
  39134. float linearDepth = gl_Position.w;
  39135. float expDepth = (gl_Position.z / gl_Position.w) * 0.5 + 0.5;
  39136. color = vec3(linearDepth, expDepth, 0.0);
  39137. //color = vec3(1.0, 0.5, 0.3);
  39138. #elif defined color_type_intensity
  39139. float w = getIntensity();
  39140. color = vec3(w, w, w);
  39141. #elif defined color_type_gps_time
  39142. color = getGpsTime();
  39143. #elif defined color_type_intensity_gradient
  39144. float w = getIntensity();
  39145. color = texture2D(gradient, vec2(w,1.0-w)).rgb;
  39146. #elif defined color_type_color
  39147. color = uColor;
  39148. #elif defined color_type_level_of_detail
  39149. float depth = getLOD();
  39150. float w = depth / 10.0;
  39151. color = texture2D(gradient, vec2(w,1.0-w)).rgb;
  39152. #elif defined color_type_indices
  39153. color = indices.rgb;
  39154. #elif defined color_type_classification
  39155. vec4 cl = getClassification();
  39156. color = cl.rgb;
  39157. #elif defined color_type_return_number
  39158. color = getReturnNumber();
  39159. #elif defined color_type_returns
  39160. color = getReturns();
  39161. #elif defined color_type_number_of_returns
  39162. color = getNumberOfReturns();
  39163. #elif defined color_type_source_id
  39164. color = getSourceID();
  39165. #elif defined color_type_point_source_id
  39166. color = getSourceID();
  39167. #elif defined color_type_normal
  39168. color = (modelMatrix * vec4(normal, 0.0)).xyz;
  39169. #elif defined color_type_phong
  39170. color = color;
  39171. #elif defined color_type_composite
  39172. color = getCompositeColor();
  39173. #elif defined color_type_matcap
  39174. color = getMatcap();
  39175. #else
  39176. color = getExtra();
  39177. #endif
  39178. if (backfaceCulling && applyBackfaceCulling()){
  39179. //color = vec3(0.);
  39180. }
  39181. //applyBackfaceCulling直接返回false或者注释color = vec3(0.);都没问题
  39182. return color;
  39183. }
  39184. float getPointSize(){
  39185. float pointSize = 1.0;
  39186. float maxSize_ = maxSize;
  39187. float slope = tan(fov / 2.0);
  39188. float projFactor = -0.5 * resolution.y / (slope * vViewPosition.z);
  39189. /*
  39190. float scale = length(
  39191. modelViewMatrix * vec4(0, 0, 0, 1) -
  39192. modelViewMatrix * vec4(uOctreeSpacing, 0, 0, 1)
  39193. ) / uOctreeSpacing;
  39194. projFactor = projFactor * scale;
  39195. */
  39196. float r = uOctreeSpacing * 1.7;
  39197. //vRadius = r;
  39198. #if defined fixed_point_size
  39199. pointSize = size;
  39200. #elif defined attenuated_point_size
  39201. if(uUseOrthographicCamera){
  39202. //pointSize = size * 100.0; //加个乘数
  39203. pointSize = size / uOrthoWidth * resolution.x; //改成近似adaptive_point_size根据窗口缩放
  39204. maxSize_ = 6.0; //for panoEditor, when zoom in, need more details, rather than always same size
  39205. }else{ //近大远小,模拟真实mesh,边缘放大
  39206. //pointSize = size * spacing * projFactor; //spacing是attribute 为空 如果有这个值就能更自适应填补
  39207. //pointSize = size * uOctreeSpacing * projFactor / 18.0; //直接用cloud的spacing里,不过因为都一样所以可能没有什么意义
  39208. //pointSize = pointSize * projFactor;
  39209. pointSize = size * projFactor ;
  39210. }
  39211. #elif defined adaptive_point_size
  39212. if(uUseOrthographicCamera) {
  39213. float worldSpaceSize = 1.0 * size * r / getPointSizeAttenuation();
  39214. pointSize = (worldSpaceSize / uOrthoWidth) * resolution.x; //uScreenWidth;
  39215. maxSize_ = 3.0;
  39216. } else {
  39217. float worldSpaceSize = 1.0 * size * r / getPointSizeAttenuation();
  39218. pointSize = worldSpaceSize * projFactor;
  39219. }
  39220. #endif
  39221. pointSize = max(minSize, pointSize);
  39222. pointSize = min(maxSize_, pointSize);
  39223. vRadius = pointSize / projFactor;
  39224. return pointSize;
  39225. }
  39226. bool insideBox(mat4 clipBox){//add
  39227. vec4 clipPosition = clipBox * modelMatrix * vec4( position, 1.0 );
  39228. bool inside = -0.5 <= clipPosition.x && clipPosition.x <= 0.5;
  39229. inside = inside && -0.5 <= clipPosition.y && clipPosition.y <= 0.5;
  39230. inside = inside && -0.5 <= clipPosition.z && clipPosition.z <= 0.5;
  39231. return inside;
  39232. }
  39233. void doClipping(){
  39234. {
  39235. vec4 cl = getClassification();
  39236. if(cl.a == 0.0){
  39237. gl_Position = vec4(100.0, 100.0, 100.0, 0.0);
  39238. return;
  39239. }
  39240. }
  39241. #if defined(clip_return_number_enabled)
  39242. { // return number filter
  39243. vec2 range = uFilterReturnNumberRange;
  39244. if(returnNumber < range.x || returnNumber > range.y){
  39245. gl_Position = vec4(100.0, 100.0, 100.0, 0.0);
  39246. return;
  39247. }
  39248. }
  39249. #endif
  39250. #if defined(clip_number_of_returns_enabled)
  39251. { // number of return filter
  39252. vec2 range = uFilterNumberOfReturnsRange;
  39253. if(numberOfReturns < range.x || numberOfReturns > range.y){
  39254. gl_Position = vec4(100.0, 100.0, 100.0, 0.0);
  39255. return;
  39256. }
  39257. }
  39258. #endif
  39259. #if defined(clip_gps_enabled)
  39260. { // GPS time filter
  39261. float time = (gpsTime + uGpsOffset) * uGpsScale;
  39262. vec2 range = uFilterGPSTimeClipRange;
  39263. if(time < range.x || time > range.y){
  39264. gl_Position = vec4(100.0, 100.0, 100.0, 0.0);
  39265. return;
  39266. }
  39267. }
  39268. #endif
  39269. #if defined(clip_point_source_id_enabled)
  39270. { // point source id filter
  39271. vec2 range = uFilterPointSourceIDClipRange;
  39272. if(pointSourceID < range.x || pointSourceID > range.y){
  39273. gl_Position = vec4(100.0, 100.0, 100.0, 0.0);
  39274. return;
  39275. }
  39276. }
  39277. #endif
  39278. //总共三种box : 最外层可见、内层可见和不可见(外层可见和内层可见是交集,内层可见和内层不可见是并集)
  39279. #if defined(bigClipInBox)
  39280. if(!insideBox(clipBoxBig_in)){
  39281. gl_Position = vec4(100.0, 100.0, 100.0, 1.0);
  39282. return;;
  39283. }
  39284. #endif
  39285. #if defined(num_in_clipboxes) && num_in_clipboxes > 0
  39286. //当有可见box时,需要在任一可见box内才可见
  39287. bool visi1 = false;
  39288. for(int i = 0; i < num_in_clipboxes; i++){
  39289. if(insideBox(clipBoxes_in[i])){
  39290. visi1 = true;
  39291. break;
  39292. }
  39293. }
  39294. if(!visi1){
  39295. gl_Position = vec4(100.0, 100.0, 100.0, 1.0);
  39296. return;
  39297. }
  39298. #endif
  39299. #if defined(num_out_clipboxes) && num_out_clipboxes > 0
  39300. //当有不可见box时,不在所有不可见box内才可见
  39301. bool visi2 = true;
  39302. for(int i = 0; i < num_out_clipboxes; i++){
  39303. if(insideBox(clipBoxes_out[i])){
  39304. visi2 = false;
  39305. break;
  39306. }
  39307. }
  39308. if(!visi2){
  39309. gl_Position = vec4(100.0, 100.0, 100.0, 1.0);
  39310. return;
  39311. }
  39312. #endif
  39313. #if defined(num_highlightBox) && num_highlightBox > 0
  39314. //当有高亮box时,需要在任一可见高亮内都高宽
  39315. bool highlight = false;
  39316. for(int i = 0; i < num_highlightBox; i++){
  39317. if(insideBox(boxes_highlight[i])){
  39318. highlight = true;
  39319. break;
  39320. }
  39321. }
  39322. if(highlight){
  39323. vColor.r += 0.5;
  39324. }
  39325. #endif
  39326. }
  39327. //
  39328. // ## ## ### #### ## ##
  39329. // ### ### ## ## ## ### ##
  39330. // #### #### ## ## ## #### ##
  39331. // ## ### ## ## ## ## ## ## ##
  39332. // ## ## ######### ## ## ####
  39333. // ## ## ## ## ## ## ###
  39334. // ## ## ## ## #### ## ##
  39335. //
  39336. vec2 getSamplerCoord( vec3 direction )
  39337. {
  39338. direction = normalize(direction);
  39339. float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;
  39340. float ty=acos(direction.z)/PI;
  39341. return vec2(tx,ty);
  39342. }
  39343. vec3 transformAxis( vec3 direction ) //navvis->4dkk
  39344. {
  39345. float y = direction.y;
  39346. direction.y = direction.z;
  39347. direction.z = -y;
  39348. return direction;
  39349. }
  39350. void main() {
  39351. //bool filtered_by_normal = false;
  39352. float normalZ = 0.0;
  39353. #ifdef use_filter_by_normal
  39354. /*if(abs(getNormal().z) > 0.4) { //ufilterByNormalThreshold 暂定 3
  39355. // Move point outside clip space space to discard it.
  39356. //gl_Position = vec4(0.0, 0.0, 2.0, 1.0); //gl_Position的可视区域是 x,y,z都是[-1,1]
  39357. //return;
  39358. //filtered_by_normal = true; //标记一下。不直接不绘制,因为有的法线都是垂直向上
  39359. }*/
  39360. normalZ = abs(getNormal().z);
  39361. #endif
  39362. vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );
  39363. vViewPosition = mvPosition.xyz;
  39364. gl_Position = projectionMatrix * mvPosition;
  39365. vLogDepth = log2(-mvPosition.z);
  39366. // COLOR
  39367. //加-------------------
  39368. #if defined(usePanoMap)
  39369. vec4 worldPosition = modelMatrix * vec4(position, 1.0);
  39370. vec3 positionLocalToPanoCenter0 = worldPosition.xyz - pano0Position;
  39371. vec3 vWorldPosition0 = (vec4(positionLocalToPanoCenter0, 1.0) * pano0Matrix).xyz;
  39372. vWorldPosition0.x *= -1.0;
  39373. vWorldPosition0 = transformAxis(vWorldPosition0);
  39374. vec3 positionLocalToPanoCenter1 = worldPosition.xyz - pano1Position;
  39375. vec3 vWorldPosition1 = (vec4(positionLocalToPanoCenter1, 1.0) * pano1Matrix).xyz;
  39376. vWorldPosition1.x *= -1.0;
  39377. vWorldPosition1 = transformAxis(vWorldPosition1);
  39378. /*
  39379. vec2 samplerCoord0 = getSamplerCoord(vWorldPosition0.xyz);
  39380. vec2 samplerCoord1 = getSamplerCoord(vWorldPosition1.xyz);
  39381. vec4 colorFromPano0 = texture2D(pano0Map,samplerCoord0);
  39382. vec4 colorFromPano1 = texture2D(pano1Map,samplerCoord1);
  39383. */
  39384. vec4 colorFromPano0=textureCube(pano0Map,vWorldPosition0.xyz);
  39385. vec4 colorFromPano1=textureCube(pano1Map,vWorldPosition1.xyz);
  39386. vColor = mix(colorFromPano0,colorFromPano1,progress).xyz;
  39387. //float easeInOutRatio = 0.0; //缓冲,渐变点云到贴图的颜色
  39388. if(progress < easeInOutRatio){
  39389. float easeProgress = (easeInOutRatio - progress) / easeInOutRatio;
  39390. vec3 vColor1 = getColor();
  39391. vColor = mix(vColor,vColor1,easeProgress);
  39392. }else if(progress > 1.0 - easeInOutRatio){
  39393. float easeProgress = (progress - (1.0 - easeInOutRatio) ) / easeInOutRatio;
  39394. vec3 vColor1 = getColor();
  39395. vColor = mix(vColor,vColor1,easeProgress);
  39396. }
  39397. #else
  39398. vColor = getColor();
  39399. #endif
  39400. //-------------------
  39401. #ifdef attenuated_opacity
  39402. //zoom不会改变z 所以这并不是用在分屏时候的
  39403. //vOpacity = uOpacity * exp(-length(-mvPosition.xyz) / 1000.0); // e为底的指数函数 opacityAttenuation = 1000
  39404. vOpacity = uOpacity * exp(gl_Position.z/50.0);
  39405. vOpacity = clamp(vOpacity, 0.001, 1.0);
  39406. #else
  39407. vOpacity = uOpacity;
  39408. #endif
  39409. vOpacity *= max(0.1, (1.0 - normalZ));//垂直朝相机时降低透明度
  39410. // POINT SIZE
  39411. float pointSize = getPointSize();
  39412. gl_PointSize = pointSize;
  39413. vPointSize = pointSize;
  39414. // only for "replacing" approaches
  39415. // if(getLOD() != uLevel){
  39416. // gl_Position = vec4(10.0, 10.0, 10.0, 1.0);
  39417. // }
  39418. #if defined hq_depth_pass
  39419. float originalDepth = gl_Position.w;
  39420. float adjustedDepth = originalDepth + 2.0 * vRadius;
  39421. float adjust = adjustedDepth / originalDepth;
  39422. mvPosition.xyz = mvPosition.xyz * adjust;
  39423. gl_Position = projectionMatrix * mvPosition;
  39424. #endif
  39425. // CLIPPING
  39426. doClipping();
  39427. #if defined(num_clipspheres) && num_clipspheres > 0
  39428. for(int i = 0; i < num_clipspheres; i++){
  39429. vec4 sphereLocal = uClipSpheres[i] * mvPosition;
  39430. float distance = length(sphereLocal.xyz);
  39431. if(distance < 1.0){
  39432. float w = distance;
  39433. vec3 cGradient = texture2D(gradient, vec2(w, 1.0 - w)).rgb;
  39434. vColor = cGradient;
  39435. //vColor = cGradient * 0.7 + vColor * 0.3;
  39436. }
  39437. }
  39438. #endif
  39439. #if defined(num_shadowmaps) && num_shadowmaps > 0
  39440. const float sm_near = 0.1;
  39441. const float sm_far = 10000.0;
  39442. for(int i = 0; i < num_shadowmaps; i++){
  39443. vec3 viewPos = (uShadowWorldView[i] * vec4(position, 1.0)).xyz;
  39444. float distanceToLight = abs(viewPos.z);
  39445. vec4 projPos = uShadowProj[i] * uShadowWorldView[i] * vec4(position, 1);
  39446. vec3 nc = projPos.xyz / projPos.w;
  39447. float u = nc.x * 0.5 + 0.5;
  39448. float v = nc.y * 0.5 + 0.5;
  39449. vec2 sampleStep = vec2(1.0 / (2.0*1024.0), 1.0 / (2.0*1024.0)) * 1.5;
  39450. vec2 sampleLocations[9];
  39451. sampleLocations[0] = vec2(0.0, 0.0);
  39452. sampleLocations[1] = sampleStep;
  39453. sampleLocations[2] = -sampleStep;
  39454. sampleLocations[3] = vec2(sampleStep.x, -sampleStep.y);
  39455. sampleLocations[4] = vec2(-sampleStep.x, sampleStep.y);
  39456. sampleLocations[5] = vec2(0.0, sampleStep.y);
  39457. sampleLocations[6] = vec2(0.0, -sampleStep.y);
  39458. sampleLocations[7] = vec2(sampleStep.x, 0.0);
  39459. sampleLocations[8] = vec2(-sampleStep.x, 0.0);
  39460. float visibleSamples = 0.0;
  39461. float numSamples = 0.0;
  39462. float bias = vRadius * 2.0;
  39463. for(int j = 0; j < 9; j++){
  39464. vec4 depthMapValue = texture2D(uShadowMap[i], vec2(u, v) + sampleLocations[j]);
  39465. float linearDepthFromSM = depthMapValue.x + bias;
  39466. float linearDepthFromViewer = distanceToLight;
  39467. if(linearDepthFromSM > linearDepthFromViewer){
  39468. visibleSamples += 1.0;
  39469. }
  39470. numSamples += 1.0;
  39471. }
  39472. float visibility = visibleSamples / numSamples;
  39473. if(u < 0.0 || u > 1.0 || v < 0.0 || v > 1.0 || nc.x < -1.0 || nc.x > 1.0 || nc.y < -1.0 || nc.y > 1.0 || nc.z < -1.0 || nc.z > 1.0){
  39474. //vColor = vec3(0.0, 0.0, 0.2);
  39475. }else{
  39476. //vColor = vec3(1.0, 1.0, 1.0) * visibility + vec3(1.0, 1.0, 1.0) * vec3(0.5, 0.0, 0.0) * (1.0 - visibility);
  39477. vColor = vColor * visibility + vColor * uShadowColor * (1.0 - visibility);
  39478. }
  39479. }
  39480. #endif
  39481. }
  39482. `;
  39483. Shaders["pointcloud_new.fs"] = `
  39484. #if defined paraboloid_point_shape
  39485. #extension GL_EXT_frag_depth : enable
  39486. #endif
  39487. #define PI 3.141592653589793
  39488. precision highp float;
  39489. precision highp int;
  39490. /*
  39491. #if defined(usePanoMap)
  39492. uniform samplerCube pano0Map; //随便设置一个samplerCube去使用都会让点云消失
  39493. uniform samplerCube pano1Map;
  39494. uniform float progress;
  39495. uniform float easeInOutRatio;
  39496. uniform vec3 pano0Position;
  39497. uniform mat4 pano0Matrix;
  39498. uniform vec3 pano1Position;
  39499. uniform mat4 pano1Matrix;
  39500. varying vec3 vWorldPosition0;
  39501. varying vec3 vWorldPosition1;
  39502. #endif
  39503. */
  39504. //------------
  39505. uniform mat4 viewMatrix;
  39506. uniform mat4 uViewInv;
  39507. uniform mat4 uProjInv;
  39508. uniform vec3 cameraPosition;
  39509. uniform mat4 projectionMatrix;
  39510. //uniform float uOpacity;
  39511. varying float vOpacity; //add
  39512. uniform float blendHardness;
  39513. uniform float blendDepthSupplement;
  39514. uniform float fov;
  39515. uniform float uSpacing;
  39516. uniform float near;
  39517. uniform float far;
  39518. uniform float uPCIndex;
  39519. uniform float uScreenWidth;
  39520. uniform float uScreenHeight;
  39521. varying vec3 vColor;
  39522. varying float vLogDepth;
  39523. varying vec3 vViewPosition;
  39524. varying float vRadius;
  39525. varying float vPointSize;
  39526. varying vec3 vPosition;
  39527. float specularStrength = 1.0;
  39528. vec2 getSamplerCoord( vec3 direction )
  39529. {
  39530. direction = normalize(direction);
  39531. float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;
  39532. float ty=acos(direction.z)/PI;
  39533. return vec2(tx,ty);
  39534. }
  39535. void main() {
  39536. vec3 color = vColor;
  39537. /*#if defined(usePanoMap) //加 经测试,即使全部写在fragment里也是无论pointsize多大都是一个点一个颜色,所以干脆写在vectex里
  39538. vec4 colorFromPano0=textureCube(pano0Map,vWorldPosition0.xyz);
  39539. vec4 colorFromPano1=textureCube(pano1Map,vWorldPosition1.xyz);
  39540. color = mix(colorFromPano0,colorFromPano1,progress).xyz;
  39541. //float easeInOutRatio = 0.0; //缓冲,渐变点云到贴图的颜色
  39542. if(progress < easeInOutRatio){
  39543. float easeProgress = (easeInOutRatio - progress) / easeInOutRatio;
  39544. color = mix(color,vColor,easeProgress);
  39545. }else if(progress > 1.0 - easeInOutRatio){
  39546. float easeProgress = (progress - (1.0 - easeInOutRatio) ) / easeInOutRatio;
  39547. color = mix(color,vColor,easeProgress);
  39548. }
  39549. #else
  39550. color = vColor;
  39551. #endif*/
  39552. float depth = gl_FragCoord.z;
  39553. #if defined(circle_point_shape) || defined(paraboloid_point_shape)
  39554. float u = 2.0 * gl_PointCoord.x - 1.0;
  39555. float v = 2.0 * gl_PointCoord.y - 1.0;
  39556. #endif
  39557. #if defined(circle_point_shape)
  39558. float cc = u*u + v*v;
  39559. if(cc > 1.0){
  39560. discard;
  39561. }
  39562. #endif
  39563. #if defined color_type_indices //pick point recognize
  39564. gl_FragColor = vec4(color, uPCIndex / 255.0); //uPCIndex : node Index
  39565. #else
  39566. gl_FragColor = vec4(color, vOpacity);
  39567. #endif
  39568. #if defined paraboloid_point_shape
  39569. float wi = 0.0 - ( u*u + v*v);
  39570. vec4 pos = vec4(vViewPosition, 1.0);
  39571. pos.z += wi * vRadius;
  39572. float linearDepth = -pos.z;
  39573. pos = projectionMatrix * pos;
  39574. pos = pos / pos.w;
  39575. float expDepth = pos.z;
  39576. depth = (pos.z + 1.0) / 2.0;
  39577. gl_FragDepthEXT = depth;
  39578. gl_FragDepthEXT = clamp(gl_FragDepthEXT, 0.0, 1.0);
  39579. #if defined(color_type_depth)
  39580. color.r = linearDepth;
  39581. color.g = expDepth;
  39582. #endif
  39583. #if defined(use_edl)
  39584. gl_FragColor.a = log2(linearDepth);
  39585. #endif
  39586. #else
  39587. #if defined(use_edl)
  39588. gl_FragColor.a = vLogDepth;
  39589. #endif
  39590. #endif
  39591. #if defined(weighted_splats)
  39592. float distance = 2.0 * length(gl_PointCoord.xy - 0.5);
  39593. float weight = max(0.0, 1.0 - distance);
  39594. weight = pow(weight, 1.5);
  39595. gl_FragColor.a = weight;
  39596. gl_FragColor.xyz = gl_FragColor.xyz * weight;
  39597. #endif
  39598. //gl_FragColor = vec4(0.0, 0.7, 0.0, 1.0);
  39599. }
  39600. `;
  39601. Shaders["pointcloud_sm.vs"] = `
  39602. precision mediump float;
  39603. precision mediump int;
  39604. attribute vec3 position;
  39605. attribute vec3 color;
  39606. uniform mat4 modelMatrix;
  39607. uniform mat4 modelViewMatrix;
  39608. uniform mat4 projectionMatrix;
  39609. uniform mat4 viewMatrix;
  39610. uniform float uScreenWidth;
  39611. uniform float uScreenHeight;
  39612. uniform float near;
  39613. uniform float far;
  39614. uniform float uSpacing;
  39615. uniform float uOctreeSize;
  39616. uniform float uLevel;
  39617. uniform float uVNStart;
  39618. uniform sampler2D visibleNodes;
  39619. varying float vLinearDepth;
  39620. varying vec3 vColor;
  39621. #define PI 3.141592653589793
  39622. // ---------------------
  39623. // OCTREE
  39624. // ---------------------
  39625. #if defined(adaptive_point_size)
  39626. /**
  39627. * number of 1-bits up to inclusive index position
  39628. * number is treated as if it were an integer in the range 0-255
  39629. *
  39630. */
  39631. float numberOfOnes(float number, float index){
  39632. float tmp = mod(number, pow(2.0, index + 1.0));
  39633. float numOnes = 0.0;
  39634. for(float i = 0.0; i < 8.0; i++){
  39635. if(mod(tmp, 2.0) != 0.0){
  39636. numOnes++;
  39637. }
  39638. tmp = floor(tmp / 2.0);
  39639. }
  39640. return numOnes;
  39641. }
  39642. /**
  39643. * checks whether the bit at index is 1
  39644. * number is treated as if it were an integer in the range 0-255
  39645. *
  39646. */
  39647. bool isBitSet(float number, float index){
  39648. return mod(floor(number / pow(2.0, index)), 2.0) != 0.0;
  39649. }
  39650. /**
  39651. * find the LOD at the point position
  39652. */
  39653. float getLOD(){
  39654. vec3 offset = vec3(0.0, 0.0, 0.0);
  39655. float iOffset = uVNStart;
  39656. float depth = uLevel;
  39657. for(float i = 0.0; i <= 30.0; i++){
  39658. float nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);
  39659. vec3 index3d = (position-offset) / nodeSizeAtLevel;
  39660. index3d = floor(index3d + 0.5);
  39661. float index = 4.0 * index3d.x + 2.0 * index3d.y + index3d.z;
  39662. vec4 value = texture2D(visibleNodes, vec2(iOffset / 2048.0, 0.0));
  39663. float mask = value.r * 255.0;
  39664. if(isBitSet(mask, index)){
  39665. // there are more visible child nodes at this position
  39666. iOffset = iOffset + value.g * 255.0 * 256.0 + value.b * 255.0 + numberOfOnes(mask, index - 1.0);
  39667. depth++;
  39668. }else{
  39669. // no more visible child nodes at this position
  39670. return depth;
  39671. }
  39672. offset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;
  39673. }
  39674. return depth;
  39675. }
  39676. #endif
  39677. float getPointSize(){
  39678. float pointSize = 1.0;
  39679. float slope = tan(fov / 2.0);
  39680. float projFactor = -0.5 * uScreenHeight / (slope * vViewPosition.z);
  39681. float r = uOctreeSpacing * 1.5;
  39682. vRadius = r;
  39683. #if defined fixed_point_size
  39684. pointSize = size;
  39685. #elif defined attenuated_point_size
  39686. if(uUseOrthographicCamera){
  39687. pointSize = size;
  39688. }else{
  39689. pointSize = pointSize * projFactor;
  39690. }
  39691. #elif defined adaptive_point_size
  39692. if(uUseOrthographicCamera) {
  39693. float worldSpaceSize = 1.5 * size * r / getPointSizeAttenuation();
  39694. pointSize = (worldSpaceSize / uOrthoWidth) * uScreenWidth;
  39695. } else {
  39696. float worldSpaceSize = 1.5 * size * r / getPointSizeAttenuation();
  39697. pointSize = worldSpaceSize * projFactor;
  39698. }
  39699. #endif
  39700. pointSize = max(minSize, pointSize);
  39701. pointSize = min(maxSize, pointSize);
  39702. vRadius = pointSize / projFactor;
  39703. return pointSize;
  39704. }
  39705. void main() {
  39706. vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  39707. vLinearDepth = gl_Position.w;
  39708. float pointSize = getPointSize();
  39709. gl_PointSize = pointSize;
  39710. }
  39711. `;
  39712. Shaders["pointcloud_sm.fs"] = `
  39713. precision mediump float;
  39714. precision mediump int;
  39715. varying vec3 vColor;
  39716. varying float vLinearDepth;
  39717. void main() {
  39718. //gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  39719. //gl_FragColor = vec4(vColor, 1.0);
  39720. //gl_FragColor = vec4(vLinearDepth, pow(vLinearDepth, 2.0), 0.0, 1.0);
  39721. gl_FragColor = vec4(vLinearDepth, vLinearDepth / 30.0, vLinearDepth / 30.0, 1.0);
  39722. }
  39723. `;
  39724. Shaders["normalize.vs"] = `
  39725. precision mediump float;
  39726. precision mediump int;
  39727. attribute vec3 position;
  39728. attribute vec2 uv;
  39729. uniform mat4 projectionMatrix;
  39730. uniform mat4 modelViewMatrix;
  39731. varying vec2 vUv;
  39732. void main() {
  39733. vUv = uv;
  39734. gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
  39735. }`;
  39736. Shaders["normalize.fs"] = `
  39737. #extension GL_EXT_frag_depth : enable
  39738. precision mediump float;
  39739. precision mediump int;
  39740. uniform sampler2D uWeightMap;
  39741. uniform sampler2D uDepthMap;
  39742. varying vec2 vUv;
  39743. void main() {
  39744. float depth = texture2D(uDepthMap, vUv).r;
  39745. if(depth >= 1.0){
  39746. discard;
  39747. }
  39748. gl_FragColor = vec4(depth, 1.0, 0.0, 1.0);
  39749. vec4 color = texture2D(uWeightMap, vUv);
  39750. color = color / color.w;
  39751. gl_FragColor = vec4(color.xyz, 1.0);
  39752. gl_FragDepthEXT = depth;
  39753. }`;
  39754. Shaders["normalize_and_edl.fs"] = `
  39755. #extension GL_EXT_frag_depth : enable
  39756. //
  39757. // adapted from the EDL shader code from Christian Boucheny in cloud compare:
  39758. // https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL
  39759. //
  39760. precision mediump float;
  39761. precision mediump int;
  39762. uniform sampler2D uWeightMap;
  39763. uniform sampler2D uEDLMap;
  39764. uniform sampler2D uDepthMap;
  39765. uniform float screenWidth;
  39766. uniform float screenHeight;
  39767. uniform vec2 neighbours[NEIGHBOUR_COUNT];
  39768. uniform float edlStrength;
  39769. uniform float radius;
  39770. varying vec2 vUv;
  39771. float response(float depth){
  39772. vec2 uvRadius = radius / vec2(screenWidth, screenHeight);
  39773. float sum = 0.0;
  39774. for(int i = 0; i < NEIGHBOUR_COUNT; i++){
  39775. vec2 uvNeighbor = vUv + uvRadius * neighbours[i];
  39776. float neighbourDepth = texture2D(uEDLMap, uvNeighbor).a;
  39777. if(neighbourDepth != 0.0){
  39778. if(depth == 0.0){
  39779. sum += 100.0;
  39780. }else{
  39781. sum += max(0.0, depth - neighbourDepth);
  39782. }
  39783. }
  39784. }
  39785. return sum / float(NEIGHBOUR_COUNT);
  39786. }
  39787. void main() {
  39788. float edlDepth = texture2D(uEDLMap, vUv).a;
  39789. float res = response(edlDepth);
  39790. float shade = exp(-res * 300.0 * edlStrength);
  39791. float depth = texture2D(uDepthMap, vUv).r;
  39792. if(depth >= 1.0 && res == 0.0){
  39793. discard;
  39794. }
  39795. vec4 color = texture2D(uWeightMap, vUv);
  39796. color = color / color.w;
  39797. color = color * shade;
  39798. gl_FragColor = vec4(color.xyz, 1.0);
  39799. gl_FragDepthEXT = depth;
  39800. }`;
  39801. Shaders["edl_new.vs"] = `
  39802. precision mediump float;
  39803. precision mediump int;
  39804. attribute vec3 position;
  39805. attribute vec2 uv;
  39806. uniform mat4 projectionMatrix;
  39807. uniform mat4 modelViewMatrix;
  39808. varying vec2 vUv;
  39809. void main() {
  39810. vUv = uv;
  39811. vec4 mvPosition = modelViewMatrix * vec4(position,1.0);
  39812. gl_Position = projectionMatrix * mvPosition;
  39813. }`;
  39814. Shaders["edl_new.fs"] = `
  39815. #extension GL_EXT_frag_depth : enable
  39816. //
  39817. // adapted from the EDL shader code from Christian Boucheny in cloud compare:
  39818. // https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL
  39819. //
  39820. precision mediump float;
  39821. precision mediump int;
  39822. //uniform float screenWidth;
  39823. //uniform float screenHeight;
  39824. uniform vec2 resolution;
  39825. uniform vec2 neighbours[NEIGHBOUR_COUNT];
  39826. uniform float edlStrength;
  39827. uniform float radius;
  39828. uniform float opacity;
  39829. //uniform float uNear;
  39830. //uniform float uFar;
  39831. uniform mat4 uProj;
  39832. uniform sampler2D uEDLColor;
  39833. uniform sampler2D uEDLDepth;
  39834. varying vec2 vUv;
  39835. uniform int useEDL;
  39836. float response(float depth){
  39837. vec2 uvRadius = radius / resolution; //vec2(screenWidth, screenHeight);
  39838. float sum = 0.0;
  39839. for(int i = 0; i < NEIGHBOUR_COUNT; i++){
  39840. vec2 uvNeighbor = vUv + uvRadius * neighbours[i];
  39841. //获取周围八个格子的值
  39842. float neighbourDepth = texture2D(uEDLColor, uvNeighbor).a;
  39843. neighbourDepth = (neighbourDepth == 1.0) ? 0.0 : neighbourDepth;
  39844. if(neighbourDepth != 0.0){
  39845. //if(depth == 0.0){
  39846. // sum += 100.0;
  39847. //}else{
  39848. sum += max(0.0, depth - neighbourDepth); //获取差值
  39849. //}
  39850. }
  39851. }
  39852. return sum / float(NEIGHBOUR_COUNT);
  39853. }
  39854. void main(){
  39855. vec4 cEDL = texture2D(uEDLColor, vUv);
  39856. float depth = cEDL.a;
  39857. depth = (depth == 1.0) ? 0.0 : depth;
  39858. if(depth == 0.0){ //去掉这句就能在无点云像素的地方渲染outline,但会遮住其他mesh
  39859. discard;
  39860. }
  39861. if(useEDL == 1){
  39862. float res = response(depth);
  39863. float shade = exp(-res * 300.0 * edlStrength); //自然常数e为底的指数函数
  39864. const float min = 0.2; //add 使边缘色变浅 范围从0-1 变为min-1
  39865. shade = shade * (1.0-min) + min;
  39866. gl_FragColor = vec4(cEDL.rgb * shade, opacity);
  39867. }else{//加 不改颜色的情况
  39868. gl_FragColor = vec4(cEDL.rgb, opacity);
  39869. }
  39870. //注意,edlStrength越强,在相同depth的叠放的点云间的轮廓线颜色越深
  39871. //作用:勾勒边缘,强化深度差异,模拟阴影,加强结构立体感
  39872. { // write regular hyperbolic depth values to depth buffer 修改深度
  39873. float dl = pow(2.0, depth);
  39874. vec4 dp = uProj * vec4(0.0, 0.0, -dl, 1.0);
  39875. float pz = dp.z / dp.w;
  39876. float fragDepth = (pz + 1.0) / 2.0;
  39877. gl_FragDepthEXT = fragDepth;
  39878. }
  39879. }
  39880. `;
  39881. Shaders["blur.vs"] = `
  39882. varying vec2 vUv;
  39883. void main() {
  39884. vUv = uv;
  39885. gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
  39886. }`;
  39887. Shaders["blur.fs"] = `
  39888. uniform mat4 projectionMatrix;
  39889. uniform float screenWidth;
  39890. uniform float screenHeight;
  39891. uniform float near;
  39892. uniform float far;
  39893. uniform sampler2D map;
  39894. varying vec2 vUv;
  39895. void main() {
  39896. float dx = 1.0 / screenWidth;
  39897. float dy = 1.0 / screenHeight;
  39898. vec3 color = vec3(0.0, 0.0, 0.0);
  39899. color += texture2D(map, vUv + vec2(-dx, -dy)).rgb;
  39900. color += texture2D(map, vUv + vec2( 0, -dy)).rgb;
  39901. color += texture2D(map, vUv + vec2(+dx, -dy)).rgb;
  39902. color += texture2D(map, vUv + vec2(-dx, 0)).rgb;
  39903. color += texture2D(map, vUv + vec2( 0, 0)).rgb;
  39904. color += texture2D(map, vUv + vec2(+dx, 0)).rgb;
  39905. color += texture2D(map, vUv + vec2(-dx, dy)).rgb;
  39906. color += texture2D(map, vUv + vec2( 0, dy)).rgb;
  39907. color += texture2D(map, vUv + vec2(+dx, dy)).rgb;
  39908. color = color / 9.0;
  39909. gl_FragColor = vec4(color, 1.0);
  39910. }`;
  39911. Shaders["depthBasic.vs"] = `
  39912. varying vec2 vUv;
  39913. void main() {
  39914. vUv = uv;
  39915. gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  39916. }
  39917. `;
  39918. Shaders["depthBasic.fs"] = `varying vec2 vUv;
  39919. uniform float opacity;
  39920. uniform vec3 baseColor;
  39921. #if defined use_map
  39922. uniform sampler2D map;
  39923. #if defined mapColorReplace
  39924. uniform vec3 replaceColor;
  39925. uniform float beReplacedRed;
  39926. #endif
  39927. #endif
  39928. #if defined(GL_EXT_frag_depth) && defined(useDepth)
  39929. //似乎通过gl.getExtension('EXT_frag_depth')得到的GL_EXT_frag_depth
  39930. uniform sampler2D depthTexture;
  39931. uniform float nearPlane;
  39932. uniform float farPlane;
  39933. uniform vec2 resolution;
  39934. uniform vec2 viewportOffset; // viewportOffset 范围从0-整个画布的像素
  39935. uniform vec3 backColor;
  39936. uniform float occlusionDistance;
  39937. uniform float clipDistance;
  39938. uniform float maxClipFactor;
  39939. uniform float maxOcclusionFactor;
  39940. uniform bool uUseOrthographicCamera;
  39941. float convertToLinear(float zValue)
  39942. {
  39943. if(uUseOrthographicCamera){
  39944. return zValue*(farPlane-nearPlane)+nearPlane;
  39945. }else{
  39946. float z = zValue * 2.0 - 1.0;
  39947. return (2.0 * nearPlane * farPlane) / (farPlane + nearPlane - z * (farPlane - nearPlane));
  39948. }
  39949. }
  39950. #endif
  39951. vec4 getMapColor(vec4 color){
  39952. #if defined use_map
  39953. vec4 mapColor = texture2D(map, vUv);
  39954. #if defined mapColorReplace
  39955. //主要为了测量线marker。 假设此图中仅有两种颜色,另一种是白色
  39956. const vec3 mapAnotherColor = vec3(1.0,1.0,1.0);
  39957. //uniform vec4 replaceColor;//新的颜色
  39958. if(mapColor.r < beReplacedRed){//要被取代的颜色
  39959. mapColor = vec4(replaceColor, mapColor.a);
  39960. }/*else if(mapColor.r>mapTextColotR){
  39961. mapColor = vec4(textColor, mapColor.a);
  39962. }*/else{//抗锯齿 过渡
  39963. float replaceRatio = (mapColor.r - mapAnotherColor.r) / (beReplacedRed - mapAnotherColor.r);
  39964. mapColor = vec4( mix(mapAnotherColor, replaceColor, replaceRatio), mapColor.a);
  39965. }
  39966. #endif
  39967. color *= mapColor;
  39968. #endif
  39969. return color;
  39970. }
  39971. void main() {
  39972. vec4 color = vec4(baseColor, opacity);
  39973. #if defined(GL_EXT_frag_depth) && defined(useDepth)
  39974. // mixFactor and clipFactor define the color mixing proportion between the states of
  39975. // full visibility and occluded visibility
  39976. // and
  39977. // full visibility and total invisibility
  39978. float mixFactor = 0.0;
  39979. float clipFactor = 0.0;
  39980. // The linear depth value of the current fragment
  39981. float fragDepth = convertToLinear(gl_FragCoord.z);
  39982. // The coordinates of the current fragment in the depth texture
  39983. vec2 depthTxtCoords = vec2(gl_FragCoord.x-viewportOffset.x, gl_FragCoord.y - viewportOffset.y) / resolution;
  39984. //gl_FragCoord大小为 viewport client大小
  39985. // The linear depth value of the pixel occupied by this fragment in the depth buffer
  39986. float textureDepth = convertToLinear(texture2D(depthTexture, depthTxtCoords).r);
  39987. // The difference between the two depths
  39988. float delta = fragDepth - textureDepth;
  39989. if (delta > 0.0)//差距
  39990. {
  39991. // occlusionDistance and clipDistance define the width of the respective zones and
  39992. // mixFactor and clipFactor express the interpolation between the two colors depending on the position
  39993. // of the current fragment withing those zones.
  39994. mixFactor = clamp(delta / occlusionDistance, 0.0, maxOcclusionFactor);
  39995. clipFactor = clamp(delta / clipDistance, 0.0, maxClipFactor);
  39996. }
  39997. // If the fragment is totally transparent, don't bother drawing it
  39998. if (clipFactor == 1.0)
  39999. {
  40000. discard;
  40001. }else{
  40002. color = getMapColor(color);
  40003. color = vec4(mix(color.rgb, backColor, mixFactor), color.a * (1.0 - clipFactor));
  40004. }
  40005. #else
  40006. color = getMapColor(color);
  40007. #endif
  40008. gl_FragColor = color;
  40009. }
  40010. `;
  40011. Shaders["copyCubeMap.vs"] = `varying vec3 vWorldPos;
  40012. vec3 transformAxis( vec3 direction ) //navvis->4dkk
  40013. {
  40014. float y = direction.y;
  40015. direction.y = direction.z;
  40016. direction.z = -y;
  40017. return direction;
  40018. }
  40019. void main() {
  40020. vWorldPos = vec3(-position.x, -position.y, position.z);
  40021. //vWorldPos = transformAxis(vWorldPos);
  40022. gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  40023. }
  40024. `;
  40025. Shaders["copyCubeMap.fs"] = `varying vec3 vWorldPos;
  40026. uniform float alpha;
  40027. uniform samplerCube tDiffuse;
  40028. void main() {
  40029. vec4 texColor = textureCube(tDiffuse, vWorldPos);
  40030. gl_FragColor = vec4(texColor.rgb, texColor.a * alpha);
  40031. }
  40032. `;
  40033. Shaders["basicTextured.vs"] = `varying vec2 vUv;
  40034. void main() {
  40035. vUv = uv;
  40036. gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  40037. }
  40038. `;
  40039. Shaders["basicTextured.fs"] = `varying vec2 vUv;
  40040. uniform float opacity;
  40041. #ifdef HasMap
  40042. uniform sampler2D map;
  40043. #endif
  40044. #ifdef HasColor
  40045. uniform vec3 color;
  40046. #endif
  40047. void main() {
  40048. vec4 color_;
  40049. #ifdef HasColor
  40050. color_ = vec4(color, opacity);
  40051. #else
  40052. color_ = vec4(1.0,1.0,1.0, opacity);
  40053. #endif
  40054. #ifdef HasMap
  40055. vec4 texColor = texture2D(map, vUv);
  40056. gl_FragColor = texColor * color_;
  40057. #else
  40058. gl_FragColor = color_;
  40059. #endif
  40060. }
  40061. `;
  40062. Shaders["skybox.vs"] = `uniform mat4 matrix;
  40063. varying vec3 vWorldPosition;
  40064. void main()
  40065. {
  40066. vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz ; // - cameraPosition;
  40067. vWorldPosition = (vec4(vWorldPosition, 1.0) * matrix).xyz;
  40068. vWorldPosition.x *= -1.0;
  40069. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  40070. }`;
  40071. Shaders["skybox.fs"] = `varying vec3 vWorldPosition;
  40072. uniform sampler2D tDiffuse;
  40073. #define PI 3.141592653
  40074. /*vec2 getSamplerCoord( vec3 direction )
  40075. {
  40076. direction = normalize(direction);
  40077. float tx=atan(direction.x,direction.z)/(PI*2.0)+0.5;
  40078. float ty=acos(direction.y)/PI;
  40079. return vec2(tx,ty);
  40080. }*/
  40081. vec2 getSamplerCoord( vec3 direction )
  40082. {
  40083. direction = normalize(direction);
  40084. float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;
  40085. float ty=acos(direction.z)/PI;
  40086. return vec2(tx,ty);
  40087. }
  40088. void main()
  40089. {
  40090. vec2 samplerCoord = getSamplerCoord(vWorldPosition);
  40091. vec4 color = texture2D(tDiffuse, samplerCoord);
  40092. //gl_FragColor = RGBEToLinear( color ); //对于hdr必须加这一句,否则效果很奇怪。copy自meshBasicMaterial里的mat_fragment的mapTexelToLinear函数,只要有map就会使用该函数
  40093. gl_FragColor = color;
  40094. //#include <tonemapping_fragment>
  40095. //////#include <encodings_fragment>
  40096. }
  40097. `;
  40098. const ClassificationScheme = {
  40099. DEFAULT: {
  40100. 0: { visible: true, name: 'never classified' , color: [0.5, 0.5, 0.5, 1.0] },
  40101. 1: { visible: true, name: 'unclassified' , color: [0.5, 0.5, 0.5, 1.0] },
  40102. 2: { visible: true, name: 'ground' , color: [0.63, 0.32, 0.18, 1.0] },
  40103. 3: { visible: true, name: 'low vegetation' , color: [0.0, 1.0, 0.0, 1.0] },
  40104. 4: { visible: true, name: 'medium vegetation' , color: [0.0, 0.8, 0.0, 1.0] },
  40105. 5: { visible: true, name: 'high vegetation' , color: [0.0, 0.6, 0.0, 1.0] },
  40106. 6: { visible: true, name: 'building' , color: [1.0, 0.66, 0.0, 1.0] },
  40107. 7: { visible: true, name: 'low point(noise)' , color: [1.0, 0.0, 1.0, 1.0] },
  40108. 8: { visible: true, name: 'key-point' , color: [1.0, 0.0, 0.0, 1.0] },
  40109. 9: { visible: true, name: 'water' , color: [0.0, 0.0, 1.0, 1.0] },
  40110. 12: { visible: true, name: 'overlap' , color: [1.0, 1.0, 0.0, 1.0] },
  40111. DEFAULT: { visible: true, name: 'default' , color: [0.3, 0.6, 0.6, 0.5] },
  40112. }
  40113. };
  40114. Object.defineProperty(ClassificationScheme, 'RANDOM', {
  40115. get: function() {
  40116. let scheme = {};
  40117. for(let i = 0; i <= 255; i++){
  40118. scheme[i] = new Vector4(Math.random(), Math.random(), Math.random());
  40119. }
  40120. scheme["DEFAULT"] = new Vector4(Math.random(), Math.random(), Math.random());
  40121. return scheme;
  40122. }
  40123. });
  40124. class EnumItem{
  40125. constructor(object){
  40126. for(let key of Object.keys(object)){
  40127. this[key] = object[key];
  40128. }
  40129. }
  40130. inspect(){
  40131. return `Enum(${this.name}: ${this.value})`;
  40132. }
  40133. };
  40134. class Enum{
  40135. constructor(object){
  40136. this.object = object;
  40137. for(let key of Object.keys(object)){
  40138. let value = object[key];
  40139. if(typeof value === "object"){
  40140. value.name = key;
  40141. }else {
  40142. value = {name: key, value: value};
  40143. }
  40144. this[key] = new EnumItem(value);
  40145. }
  40146. }
  40147. fromValue(value){
  40148. for(let key of Object.keys(this.object)){
  40149. if(this[key].value === value){
  40150. return this[key];
  40151. }
  40152. }
  40153. throw new Error(`No enum for value: ${value}`);
  40154. }
  40155. };
  40156. const CameraMode = {
  40157. ORTHOGRAPHIC: 0,
  40158. PERSPECTIVE: 1,
  40159. VR: 2,
  40160. };
  40161. const ClipTask = {
  40162. NONE: 0,
  40163. HIGHLIGHT: 1,
  40164. SHOW_INSIDE: 2,
  40165. SHOW_OUTSIDE: 3
  40166. };
  40167. const ClipMethod = {
  40168. INSIDE_ANY: 0,
  40169. INSIDE_ALL: 1
  40170. };
  40171. const ElevationGradientRepeat = {
  40172. CLAMP: 0,
  40173. REPEAT: 1,
  40174. MIRRORED_REPEAT: 2,
  40175. };
  40176. const MOUSE$1 = {
  40177. LEFT: 0b0001,
  40178. RIGHT: 0b0010,
  40179. MIDDLE: 0b0100
  40180. };
  40181. const PointSizeType = {
  40182. FIXED: 0,
  40183. ATTENUATED: 1,
  40184. ADAPTIVE: 2
  40185. };
  40186. const PointShape$1 = {
  40187. SQUARE: 0,
  40188. CIRCLE: 1,
  40189. PARABOLOID: 2
  40190. };
  40191. const TreeType = {
  40192. OCTREE: 0,
  40193. KDTREE: 1
  40194. };
  40195. const LengthUnits = {
  40196. METER: {code: 'm', unitspermeter: 1.0},
  40197. FEET: {code: 'ft', unitspermeter: 3.28084},
  40198. INCH: {code: '\u2033', unitspermeter: 39.3701}
  40199. };
  40200. //
  40201. // how to calculate the radius of a projected sphere in screen space
  40202. // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
  40203. // http://stackoverflow.com/questions/3717226/radius-of-projected-sphere
  40204. //
  40205. class PointCloudMaterial$1 extends RawShaderMaterial {//base
  40206. constructor (parameters = {}) {
  40207. super();
  40208. this.visibleNodesTexture = Utils.generateDataTexture(2048, 1, new Color(0xffffff));
  40209. this.visibleNodesTexture.minFilter = NearestFilter;
  40210. this.visibleNodesTexture.magFilter = NearestFilter;
  40211. let getValid = (a, b) => {
  40212. if(a !== undefined){
  40213. return a;
  40214. }else {
  40215. return b;
  40216. }
  40217. };
  40218. let pointSize = getValid(parameters.size, 1.0);
  40219. let minSize = getValid(parameters.minSize, 2.0);
  40220. let maxSize = getValid(parameters.maxSize, 50.0);
  40221. let treeType = getValid(parameters.treeType, TreeType.OCTREE);
  40222. this._pointSizeType = PointSizeType.FIXED;
  40223. this._shape = PointShape$1.SQUARE;
  40224. this._useClipBox = false;
  40225. this.clipBoxes = [];
  40226. this.clipPolygons = [];
  40227. this._weighted = false;
  40228. this._gradient = Gradients.SPECTRAL;
  40229. this.gradientTexture = PointCloudMaterial$1.generateGradientTexture(this._gradient);
  40230. this._matcap = "matcap.jpg";
  40231. this.matcapTexture = PointCloudMaterial$1.generateMatcapTexture(this._matcap);
  40232. this.lights = false;
  40233. this.fog = false;
  40234. this._treeType = treeType;
  40235. this._useEDL = false;
  40236. this.defines = new Map();
  40237. this.ranges = new Map();
  40238. this._activeAttributeName = null;
  40239. this._defaultIntensityRangeChanged = false;
  40240. this._defaultElevationRangeChanged = false;
  40241. {
  40242. const [width, height] = [256, 1];
  40243. let data = new Uint8Array(width * 4);
  40244. let texture = new DataTexture(data, width, height, RGBAFormat);
  40245. texture.magFilter = NearestFilter;
  40246. texture.needsUpdate = true;
  40247. this.classificationTexture = texture;
  40248. }
  40249. this.attributes = {
  40250. position: { type: 'fv', value: [] },
  40251. color: { type: 'fv', value: [] },
  40252. normal: { type: 'fv', value: [] },
  40253. intensity: { type: 'f', value: [] },
  40254. classification: { type: 'f', value: [] },
  40255. returnNumber: { type: 'f', value: [] },
  40256. numberOfReturns: { type: 'f', value: [] },
  40257. pointSourceID: { type: 'f', value: [] },
  40258. indices: { type: 'fv', value: [] }
  40259. };
  40260. this.uniforms = {
  40261. level: { type: "f", value: 0.0 },
  40262. vnStart: { type: "f", value: 0.0 },
  40263. spacing: { type: "f", value: 1.0 },
  40264. blendHardness: { type: "f", value: 2.0 },
  40265. blendDepthSupplement: { type: "f", value: 0.0 },
  40266. fov: { type: "f", value: 1.0 },
  40267. screenWidth: { type: "f", value: 1.0 },
  40268. screenHeight: { type: "f", value: 1.0 },
  40269. near: { type: "f", value: 0.1 },
  40270. far: { type: "f", value: 1.0 },
  40271. uColor: { type: "c", value: new Color( 0xffffff ) },
  40272. uOpacity: { type: "f", value: 1.0 },
  40273. size: { type: "f", value: pointSize },
  40274. minSize: { type: "f", value: minSize },
  40275. maxSize: { type: "f", value: maxSize },
  40276. octreeSize: { type: "f", value: 0 },
  40277. bbSize: { type: "fv", value: [0, 0, 0] },
  40278. elevationRange: { type: "2fv", value: [0, 0] },
  40279. clipBoxCount: { type: "f", value: 0 },
  40280. //clipSphereCount: { type: "f", value: 0 },
  40281. clipPolygonCount: { type: "i", value: 0 },
  40282. clipBoxes: { type: "Matrix4fv", value: [] },
  40283. //clipSpheres: { type: "Matrix4fv", value: [] },
  40284. clipPolygons: { type: "3fv", value: [] },
  40285. clipPolygonVCount: { type: "iv", value: [] },
  40286. clipPolygonVP: { type: "Matrix4fv", value: [] },
  40287. visibleNodes: { type: "t", value: this.visibleNodesTexture },
  40288. pcIndex: { type: "f", value: 0 },
  40289. gradient: { type: "t", value: this.gradientTexture },
  40290. classificationLUT: { type: "t", value: this.classificationTexture },
  40291. uHQDepthMap: { type: "t", value: null },
  40292. toModel: { type: "Matrix4f", value: [] },
  40293. diffuse: { type: "fv", value: [1, 1, 1] },
  40294. transition: { type: "f", value: 0.5 },
  40295. intensityRange: { type: "fv", value: [Infinity, -Infinity] },
  40296. intensity_gbc: { type: "fv", value: [1, 0, 0]},
  40297. uRGB_gbc: { type: "fv", value: [1, 0, 0]},
  40298. // intensityGamma: { type: "f", value: 1 },
  40299. // intensityContrast: { type: "f", value: 0 },
  40300. // intensityBrightness:{ type: "f", value: 0 },
  40301. // rgbGamma: { type: "f", value: 1 },
  40302. // rgbContrast: { type: "f", value: 0 },
  40303. // rgbBrightness: { type: "f", value: 0 },
  40304. wRGB: { type: "f", value: 1 },
  40305. wIntensity: { type: "f", value: 0 },
  40306. wElevation: { type: "f", value: 0 },
  40307. wClassification: { type: "f", value: 0 },
  40308. wReturnNumber: { type: "f", value: 0 },
  40309. wSourceID: { type: "f", value: 0 },
  40310. useOrthographicCamera: { type: "b", value: false },
  40311. elevationGradientRepat: { type: "i", value: ElevationGradientRepeat.CLAMP },
  40312. clipTask: { type: "i", value: 1 },
  40313. clipMethod: { type: "i", value: 1 },
  40314. uShadowColor: { type: "3fv", value: [0, 0, 0] },
  40315. uExtraScale: { type: "f", value: 1},
  40316. uExtraOffset: { type: "f", value: 0},
  40317. uExtraRange: { type: "2fv", value: [0, 1] },
  40318. uExtraGammaBrightContr: { type: "3fv", value: [1, 0, 0] },
  40319. uFilterReturnNumberRange: { type: "fv", value: [0, 7]},
  40320. uFilterNumberOfReturnsRange: { type: "fv", value: [0, 7]},
  40321. uFilterGPSTimeClipRange: { type: "fv", value: [0, 7]},
  40322. uFilterPointSourceIDClipRange: { type: "fv", value: [0, 65535]},
  40323. matcapTextureUniform: { type: "t", value: this.matcapTexture },
  40324. backfaceCulling: { type: "b", value: false },
  40325. };
  40326. this.classification = ClassificationScheme.DEFAULT;
  40327. this.defaultAttributeValues.normal = [0, 0, 0];
  40328. this.defaultAttributeValues.classification = [0, 0, 0];
  40329. this.defaultAttributeValues.indices = [0, 0, 0, 0];
  40330. this.vertexShader = Shaders['pointcloud.vs'];
  40331. this.fragmentShader = Shaders['pointcloud.fs'];
  40332. this.vertexColors = VertexColors;
  40333. this.updateShaderSource();
  40334. }
  40335. setDefine(key, value){
  40336. if(value !== undefined && value !== null){
  40337. if(this.defines.get(key) !== value){
  40338. this.defines.set(key, value);
  40339. this.updateShaderSource();
  40340. }
  40341. }else {
  40342. this.removeDefine(key);
  40343. }
  40344. }
  40345. removeDefine(key){
  40346. this.defines.delete(key);
  40347. }
  40348. updateShaderSource () {
  40349. let vs = Shaders['pointcloud.vs'];
  40350. let fs = Shaders['pointcloud.fs'];
  40351. let definesString = this.getDefines();
  40352. let vsVersionIndex = vs.indexOf("#version ");
  40353. let fsVersionIndex = fs.indexOf("#version ");
  40354. if(vsVersionIndex >= 0){
  40355. vs = vs.replace(/(#version .*)/, `$1\n${definesString}`);
  40356. }else {
  40357. vs = `${definesString}\n${vs}`;
  40358. }
  40359. if(fsVersionIndex >= 0){
  40360. fs = fs.replace(/(#version .*)/, `$1\n${definesString}`);
  40361. }else {
  40362. fs = `${definesString}\n${fs}`;
  40363. }
  40364. this.vertexShader = vs;
  40365. this.fragmentShader = fs;
  40366. if (this.opacity === 1.0) {
  40367. this.blending = NoBlending;
  40368. this.transparent = false;
  40369. this.depthTest = true;
  40370. this.depthWrite = true;
  40371. this.depthFunc = LessEqualDepth;
  40372. } else if (this.opacity < 1.0 && !this.useEDL) {
  40373. this.blending = AdditiveBlending;
  40374. this.transparent = true;
  40375. this.depthTest = false;
  40376. this.depthWrite = true;
  40377. this.depthFunc = AlwaysDepth;
  40378. }
  40379. if (this.weighted) {
  40380. this.blending = AdditiveBlending;
  40381. this.transparent = true;
  40382. this.depthTest = true;
  40383. this.depthWrite = false;
  40384. }
  40385. this.needsUpdate = true;
  40386. }
  40387. getDefines () {
  40388. let defines = [];
  40389. if (this.pointSizeType === PointSizeType.FIXED) {
  40390. defines.push('#define fixed_point_size');
  40391. } else if (this.pointSizeType === PointSizeType.ATTENUATED) {
  40392. defines.push('#define attenuated_point_size');
  40393. } else if (this.pointSizeType === PointSizeType.ADAPTIVE) {
  40394. defines.push('#define adaptive_point_size');
  40395. }
  40396. if (this.shape === PointShape$1.SQUARE) {
  40397. defines.push('#define square_point_shape');
  40398. } else if (this.shape === PointShape$1.CIRCLE) {
  40399. defines.push('#define circle_point_shape');
  40400. } else if (this.shape === PointShape$1.PARABOLOID) {
  40401. defines.push('#define paraboloid_point_shape');
  40402. }
  40403. if (this._useEDL) {
  40404. defines.push('#define use_edl');
  40405. }
  40406. if(this.activeAttributeName){
  40407. let attributeName = this.activeAttributeName.replace(/[^a-zA-Z0-9]/g, '_');
  40408. defines.push(`#define color_type_${attributeName}`);
  40409. }
  40410. if(this._treeType === TreeType.OCTREE){
  40411. defines.push('#define tree_type_octree');
  40412. }else if(this._treeType === TreeType.KDTREE){
  40413. defines.push('#define tree_type_kdtree');
  40414. }
  40415. if (this.weighted) {
  40416. defines.push('#define weighted_splats');
  40417. }
  40418. for(let [key, value] of this.defines){
  40419. defines.push(value);
  40420. }
  40421. return defines.join("\n");
  40422. }
  40423. setClipBoxes (clipBoxes) {
  40424. if (!clipBoxes) {
  40425. return;
  40426. }
  40427. let doUpdate = (this.clipBoxes.length !== clipBoxes.length) && (clipBoxes.length === 0 || this.clipBoxes.length === 0);
  40428. this.uniforms.clipBoxCount.value = this.clipBoxes.length;
  40429. this.clipBoxes = clipBoxes;
  40430. if (doUpdate) {
  40431. this.updateShaderSource();
  40432. }
  40433. this.uniforms.clipBoxes.value = new Float32Array(this.clipBoxes.length * 16);
  40434. for (let i = 0; i < this.clipBoxes.length; i++) {
  40435. let box = clipBoxes[i];
  40436. this.uniforms.clipBoxes.value.set(box.inverse.elements, 16 * i);
  40437. }
  40438. for (let i = 0; i < this.uniforms.clipBoxes.value.length; i++) {
  40439. if (Number.isNaN(this.uniforms.clipBoxes.value[i])) {
  40440. this.uniforms.clipBoxes.value[i] = Infinity;
  40441. }
  40442. }
  40443. }
  40444. setClipPolygons(clipPolygons, maxPolygonVertices) {
  40445. if(!clipPolygons){
  40446. return;
  40447. }
  40448. this.clipPolygons = clipPolygons;
  40449. let doUpdate = (this.clipPolygons.length !== clipPolygons.length);
  40450. if(doUpdate){
  40451. this.updateShaderSource();
  40452. }
  40453. }
  40454. get gradient(){
  40455. return this._gradient;
  40456. }
  40457. set gradient (value) {//海拔贴图
  40458. if (this._gradient !== value) {
  40459. this._gradient = value;
  40460. this.gradientTexture = PointCloudMaterial$1.generateGradientTexture(this._gradient);
  40461. this.uniforms.gradient.value = this.gradientTexture;
  40462. }
  40463. }
  40464. get matcap(){
  40465. return this._matcap;
  40466. }
  40467. set matcap (value) {
  40468. if (this._matcap !== value) {
  40469. this._matcap = value;
  40470. this.matcapTexture = Potree.PointCloudMaterial.generateMatcapTexture(this._matcap);
  40471. this.uniforms.matcapTextureUniform.value = this.matcapTexture;
  40472. }
  40473. }
  40474. get useOrthographicCamera() {
  40475. return this.uniforms.useOrthographicCamera.value;
  40476. }
  40477. set useOrthographicCamera(value) {
  40478. if(this.uniforms.useOrthographicCamera.value !== value){
  40479. this.uniforms.useOrthographicCamera.value = value;
  40480. }
  40481. }
  40482. get backfaceCulling() {
  40483. return this.uniforms.backfaceCulling.value;
  40484. }
  40485. set backfaceCulling(value) {
  40486. if(this.uniforms.backfaceCulling.value !== value){
  40487. this.uniforms.backfaceCulling.value = value;
  40488. this.dispatchEvent({type: 'backface_changed', target: this});
  40489. }
  40490. }
  40491. recomputeClassification () {
  40492. const classification = this.classification;
  40493. const data = this.classificationTexture.image.data;
  40494. let width = 256;
  40495. const black = [1, 1, 1, 1];
  40496. let valuesChanged = false;
  40497. for (let i = 0; i < width; i++) {
  40498. let color;
  40499. let visible = true;
  40500. if (classification[i]) {
  40501. color = classification[i].color;
  40502. visible = classification[i].visible;
  40503. } else if (classification[i % 32]) {
  40504. color = classification[i % 32].color;
  40505. visible = classification[i % 32].visible;
  40506. } else if(classification.DEFAULT) {
  40507. color = classification.DEFAULT.color;
  40508. visible = classification.DEFAULT.visible;
  40509. }else {
  40510. color = black;
  40511. }
  40512. const r = parseInt(255 * color[0]);
  40513. const g = parseInt(255 * color[1]);
  40514. const b = parseInt(255 * color[2]);
  40515. const a = visible ? parseInt(255 * color[3]) : 0;
  40516. if(data[4 * i + 0] !== r){
  40517. data[4 * i + 0] = r;
  40518. valuesChanged = true;
  40519. }
  40520. if(data[4 * i + 1] !== g){
  40521. data[4 * i + 1] = g;
  40522. valuesChanged = true;
  40523. }
  40524. if(data[4 * i + 2] !== b){
  40525. data[4 * i + 2] = b;
  40526. valuesChanged = true;
  40527. }
  40528. if(data[4 * i + 3] !== a){
  40529. data[4 * i + 3] = a;
  40530. valuesChanged = true;
  40531. }
  40532. }
  40533. if(valuesChanged){
  40534. this.classificationTexture.needsUpdate = true;
  40535. this.dispatchEvent({
  40536. type: 'material_property_changed',
  40537. target: this
  40538. });
  40539. }
  40540. }
  40541. get spacing () {
  40542. return this.uniforms.spacing.value;
  40543. }
  40544. set spacing (value) {
  40545. if (this.uniforms.spacing.value !== value) { // 即 uOctreeSpacing 来自cloud.js里
  40546. this.uniforms.spacing.value = value;
  40547. }
  40548. }
  40549. get useClipBox () {
  40550. return this._useClipBox;
  40551. }
  40552. set useClipBox (value) {
  40553. if (this._useClipBox !== value) {
  40554. this._useClipBox = value;
  40555. this.updateShaderSource();
  40556. }
  40557. }
  40558. get clipTask(){
  40559. return this.uniforms.clipTask.value;
  40560. }
  40561. set clipTask(mode){
  40562. this.uniforms.clipTask.value = mode;
  40563. }
  40564. get elevationGradientRepat(){
  40565. return this.uniforms.elevationGradientRepat.value;
  40566. }
  40567. set elevationGradientRepat(mode){
  40568. this.uniforms.elevationGradientRepat.value = mode;
  40569. }
  40570. get clipMethod(){
  40571. return this.uniforms.clipMethod.value;
  40572. }
  40573. set clipMethod(mode){
  40574. this.uniforms.clipMethod.value = mode;
  40575. }
  40576. get weighted(){
  40577. return this._weighted;
  40578. }
  40579. set weighted (value) {
  40580. if (this._weighted !== value) {
  40581. this._weighted = value;
  40582. this.updateShaderSource();
  40583. }
  40584. }
  40585. get fov () {
  40586. return this.uniforms.fov.value;
  40587. }
  40588. set fov (value) {
  40589. if (this.uniforms.fov.value !== value) {
  40590. this.uniforms.fov.value = value;
  40591. // this.updateShaderSource();
  40592. }
  40593. }
  40594. get screenWidth () {
  40595. return this.uniforms.screenWidth.value;
  40596. }
  40597. set screenWidth (value) {
  40598. if (this.uniforms.screenWidth.value !== value) {
  40599. this.uniforms.screenWidth.value = value;
  40600. // this.updateShaderSource();
  40601. }
  40602. }
  40603. get screenHeight () {
  40604. return this.uniforms.screenHeight.value;
  40605. }
  40606. set screenHeight (value) {
  40607. if (this.uniforms.screenHeight.value !== value) {
  40608. this.uniforms.screenHeight.value = value;
  40609. // this.updateShaderSource();
  40610. }
  40611. }
  40612. get near () {
  40613. return this.uniforms.near.value;
  40614. }
  40615. set near (value) {
  40616. if (this.uniforms.near.value !== value) {
  40617. this.uniforms.near.value = value;
  40618. }
  40619. }
  40620. get far () {
  40621. return this.uniforms.far.value;
  40622. }
  40623. set far (value) {
  40624. if (this.uniforms.far.value !== value) {
  40625. this.uniforms.far.value = value;
  40626. }
  40627. }
  40628. get opacity(){
  40629. return this.uniforms.uOpacity.value;
  40630. }
  40631. set opacity (value) {
  40632. if (this.uniforms && this.uniforms.uOpacity) {
  40633. if (this.uniforms.uOpacity.value !== value) {
  40634. this.uniforms.uOpacity.value = value;
  40635. this.updateShaderSource();
  40636. this.dispatchEvent({
  40637. type: 'opacity_changed',
  40638. target: this
  40639. });
  40640. this.dispatchEvent({
  40641. type: 'material_property_changed',
  40642. target: this
  40643. });
  40644. }
  40645. }
  40646. }
  40647. get activeAttributeName(){
  40648. return this._activeAttributeName;
  40649. }
  40650. set activeAttributeName(value){
  40651. if (this._activeAttributeName !== value) {
  40652. this._activeAttributeName = value;
  40653. this.updateShaderSource();
  40654. this.dispatchEvent({
  40655. type: 'active_attribute_changed',
  40656. target: this
  40657. });
  40658. this.dispatchEvent({
  40659. type: 'material_property_changed',
  40660. target: this
  40661. });
  40662. }
  40663. }
  40664. get pointSizeType () {
  40665. return this._pointSizeType;
  40666. }
  40667. set pointSizeType (value) {
  40668. if (this._pointSizeType !== value) {
  40669. this._pointSizeType = value;
  40670. this.updateShaderSource(); //这句表明这个属性频繁更改会卡顿
  40671. this.dispatchEvent({
  40672. type: 'point_size_type_changed',
  40673. target: this
  40674. });
  40675. this.dispatchEvent({
  40676. type: 'material_property_changed',
  40677. target: this
  40678. });
  40679. }
  40680. }
  40681. get useEDL(){
  40682. return this._useEDL;
  40683. }
  40684. set useEDL (value) {
  40685. if (this._useEDL !== value) {
  40686. this._useEDL = value;
  40687. this.updateShaderSource();
  40688. }
  40689. }
  40690. get color () {
  40691. return this.uniforms.uColor.value;
  40692. }
  40693. set color (value) {
  40694. if (!this.uniforms.uColor.value.equals(value)) {
  40695. this.uniforms.uColor.value.copy(value);
  40696. this.dispatchEvent({
  40697. type: 'color_changed',
  40698. target: this
  40699. });
  40700. this.dispatchEvent({
  40701. type: 'material_property_changed',
  40702. target: this
  40703. });
  40704. }
  40705. }
  40706. get shape () {
  40707. return this._shape;
  40708. }
  40709. set shape (value) {
  40710. if (this._shape !== value) {
  40711. this._shape = value;
  40712. this.updateShaderSource();
  40713. this.dispatchEvent({type: 'point_shape_changed', target: this});
  40714. this.dispatchEvent({
  40715. type: 'material_property_changed',
  40716. target: this
  40717. });
  40718. }
  40719. }
  40720. get treeType () {
  40721. return this._treeType;
  40722. }
  40723. set treeType (value) {
  40724. if (this._treeType !== value) {
  40725. this._treeType = value;
  40726. this.updateShaderSource();
  40727. }
  40728. }
  40729. get bbSize () {
  40730. return this.uniforms.bbSize.value;
  40731. }
  40732. set bbSize (value) {
  40733. this.uniforms.bbSize.value = value;
  40734. }
  40735. get size () {
  40736. return this.uniforms.size.value;
  40737. }
  40738. set size (value) {
  40739. if (this.uniforms.size.value !== value) {
  40740. this.uniforms.size.value = value;
  40741. this.dispatchEvent({
  40742. type: 'point_size_changed',
  40743. target: this
  40744. });
  40745. this.dispatchEvent({
  40746. type: 'material_property_changed',
  40747. target: this
  40748. });
  40749. }
  40750. }
  40751. get minSize(){
  40752. return this.uniforms.minSize.value;
  40753. }
  40754. set minSize(value){
  40755. if (this.uniforms.minSize.value !== value) {
  40756. this.uniforms.minSize.value = value;
  40757. this.dispatchEvent({
  40758. type: 'point_size_changed',
  40759. target: this
  40760. });
  40761. this.dispatchEvent({
  40762. type: 'material_property_changed',
  40763. target: this
  40764. });
  40765. }
  40766. }
  40767. get elevationRange () {
  40768. return this.uniforms.elevationRange.value;
  40769. }
  40770. set elevationRange (value) {
  40771. let changed = this.uniforms.elevationRange.value[0] !== value[0]
  40772. || this.uniforms.elevationRange.value[1] !== value[1];
  40773. if(changed){
  40774. this.uniforms.elevationRange.value = value;
  40775. this._defaultElevationRangeChanged = true;
  40776. this.dispatchEvent({
  40777. type: 'material_property_changed',
  40778. target: this
  40779. });
  40780. }
  40781. }
  40782. get heightMin () {
  40783. return this.uniforms.elevationRange.value[0];
  40784. }
  40785. set heightMin (value) {
  40786. this.elevationRange = [value, this.elevationRange[1]];
  40787. }
  40788. get heightMax () {
  40789. return this.uniforms.elevationRange.value[1];
  40790. }
  40791. set heightMax (value) {
  40792. this.elevationRange = [this.elevationRange[0], value];
  40793. }
  40794. get transition () {
  40795. return this.uniforms.transition.value;
  40796. }
  40797. set transition (value) {
  40798. this.uniforms.transition.value = value;
  40799. }
  40800. get intensityRange () {
  40801. return this.uniforms.intensityRange.value;
  40802. }
  40803. set intensityRange (value) {
  40804. if (!(value instanceof Array && value.length === 2)) {
  40805. return;
  40806. }
  40807. if (value[0] === this.uniforms.intensityRange.value[0] &&
  40808. value[1] === this.uniforms.intensityRange.value[1]) {
  40809. return;
  40810. }
  40811. this.uniforms.intensityRange.value = value;
  40812. this._defaultIntensityRangeChanged = true;
  40813. this.dispatchEvent({
  40814. type: 'material_property_changed',
  40815. target: this
  40816. });
  40817. }
  40818. get intensityGamma () {
  40819. return this.uniforms.intensity_gbc.value[0];
  40820. }
  40821. set intensityGamma (value) {
  40822. if (this.uniforms.intensity_gbc.value[0] !== value) {
  40823. this.uniforms.intensity_gbc.value[0] = value;
  40824. this.dispatchEvent({
  40825. type: 'material_property_changed',
  40826. target: this
  40827. });
  40828. }
  40829. }
  40830. get intensityContrast () {
  40831. return this.uniforms.intensity_gbc.value[2];
  40832. }
  40833. set intensityContrast (value) {
  40834. if (this.uniforms.intensity_gbc.value[2] !== value) {
  40835. this.uniforms.intensity_gbc.value[2] = value;
  40836. this.dispatchEvent({
  40837. type: 'material_property_changed',
  40838. target: this
  40839. });
  40840. }
  40841. }
  40842. get intensityBrightness () {
  40843. return this.uniforms.intensity_gbc.value[1];
  40844. }
  40845. set intensityBrightness (value) {
  40846. if (this.uniforms.intensity_gbc.value[1] !== value) {
  40847. this.uniforms.intensity_gbc.value[1] = value;
  40848. this.dispatchEvent({
  40849. type: 'material_property_changed',
  40850. target: this
  40851. });
  40852. }
  40853. }
  40854. get rgbGamma () {
  40855. return this.uniforms.uRGB_gbc.value[0];
  40856. }
  40857. set rgbGamma (value) {
  40858. if (this.uniforms.uRGB_gbc.value[0] !== value) {
  40859. this.uniforms.uRGB_gbc.value[0] = value;
  40860. this.dispatchEvent({
  40861. type: 'material_property_changed',
  40862. target: this
  40863. });
  40864. }
  40865. }
  40866. get rgbContrast () {
  40867. return this.uniforms.uRGB_gbc.value[2];
  40868. }
  40869. set rgbContrast (value) {
  40870. if (this.uniforms.uRGB_gbc.value[2] !== value) {
  40871. this.uniforms.uRGB_gbc.value[2] = value;
  40872. this.dispatchEvent({
  40873. type: 'material_property_changed',
  40874. target: this
  40875. });
  40876. }
  40877. }
  40878. get rgbBrightness () {
  40879. return this.uniforms.uRGB_gbc.value[1];
  40880. }
  40881. set rgbBrightness (value) {
  40882. if (this.uniforms.uRGB_gbc.value[1] !== value) {
  40883. this.uniforms.uRGB_gbc.value[1] = value;
  40884. this.dispatchEvent({
  40885. type: 'material_property_changed',
  40886. target: this
  40887. });
  40888. }
  40889. }
  40890. get extraGamma () {
  40891. return this.uniforms.uExtraGammaBrightContr.value[0];
  40892. }
  40893. set extraGamma (value) {
  40894. if (this.uniforms.uExtraGammaBrightContr.value[0] !== value) {
  40895. this.uniforms.uExtraGammaBrightContr.value[0] = value;
  40896. this.dispatchEvent({
  40897. type: 'material_property_changed',
  40898. target: this
  40899. });
  40900. }
  40901. }
  40902. get extraBrightness () {
  40903. return this.uniforms.uExtraGammaBrightContr.value[1];
  40904. }
  40905. set extraBrightness (value) {
  40906. if (this.uniforms.uExtraGammaBrightContr.value[1] !== value) {
  40907. this.uniforms.uExtraGammaBrightContr.value[1] = value;
  40908. this.dispatchEvent({
  40909. type: 'material_property_changed',
  40910. target: this
  40911. });
  40912. }
  40913. }
  40914. get extraContrast () {
  40915. return this.uniforms.uExtraGammaBrightContr.value[2];
  40916. }
  40917. set extraContrast (value) {
  40918. if (this.uniforms.uExtraGammaBrightContr.value[2] !== value) {
  40919. this.uniforms.uExtraGammaBrightContr.value[2] = value;
  40920. this.dispatchEvent({
  40921. type: 'material_property_changed',
  40922. target: this
  40923. });
  40924. }
  40925. }
  40926. getRange(attributeName){
  40927. return this.ranges.get(attributeName);
  40928. }
  40929. setRange(attributeName, newRange){
  40930. let rangeChanged = false;
  40931. let oldRange = this.ranges.get(attributeName);
  40932. if(oldRange != null && newRange != null){
  40933. rangeChanged = oldRange[0] !== newRange[0] || oldRange[1] !== newRange[1];
  40934. }else {
  40935. rangeChanged = true;
  40936. }
  40937. this.ranges.set(attributeName, newRange);
  40938. if(rangeChanged){
  40939. this.dispatchEvent({
  40940. type: 'material_property_changed',
  40941. target: this
  40942. });
  40943. }
  40944. }
  40945. get extraRange () {
  40946. return this.uniforms.uExtraRange.value;
  40947. }
  40948. set extraRange (value) {
  40949. if (!(value instanceof Array && value.length === 2)) {
  40950. return;
  40951. }
  40952. if (value[0] === this.uniforms.uExtraRange.value[0] &&
  40953. value[1] === this.uniforms.uExtraRange.value[1]) {
  40954. return;
  40955. }
  40956. this.uniforms.uExtraRange.value = value;
  40957. this._defaultExtraRangeChanged = true;
  40958. this.dispatchEvent({
  40959. type: 'material_property_changed',
  40960. target: this
  40961. });
  40962. }
  40963. get weightRGB () {
  40964. return this.uniforms.wRGB.value;
  40965. }
  40966. set weightRGB (value) {
  40967. if(this.uniforms.wRGB.value !== value){
  40968. this.uniforms.wRGB.value = value;
  40969. this.dispatchEvent({
  40970. type: 'material_property_changed',
  40971. target: this
  40972. });
  40973. }
  40974. }
  40975. get weightIntensity () {
  40976. return this.uniforms.wIntensity.value;
  40977. }
  40978. set weightIntensity (value) {
  40979. if(this.uniforms.wIntensity.value !== value){
  40980. this.uniforms.wIntensity.value = value;
  40981. this.dispatchEvent({
  40982. type: 'material_property_changed',
  40983. target: this
  40984. });
  40985. }
  40986. }
  40987. get weightElevation () {
  40988. return this.uniforms.wElevation.value;
  40989. }
  40990. set weightElevation (value) {
  40991. if(this.uniforms.wElevation.value !== value){
  40992. this.uniforms.wElevation.value = value;
  40993. this.dispatchEvent({
  40994. type: 'material_property_changed',
  40995. target: this
  40996. });
  40997. }
  40998. }
  40999. get weightClassification () {
  41000. return this.uniforms.wClassification.value;
  41001. }
  41002. set weightClassification (value) {
  41003. if(this.uniforms.wClassification.value !== value){
  41004. this.uniforms.wClassification.value = value;
  41005. this.dispatchEvent({
  41006. type: 'material_property_changed',
  41007. target: this
  41008. });
  41009. }
  41010. }
  41011. get weightReturnNumber () {
  41012. return this.uniforms.wReturnNumber.value;
  41013. }
  41014. set weightReturnNumber (value) {
  41015. if(this.uniforms.wReturnNumber.value !== value){
  41016. this.uniforms.wReturnNumber.value = value;
  41017. this.dispatchEvent({
  41018. type: 'material_property_changed',
  41019. target: this
  41020. });
  41021. }
  41022. }
  41023. get weightSourceID () {
  41024. return this.uniforms.wSourceID.value;
  41025. }
  41026. set weightSourceID (value) {
  41027. if(this.uniforms.wSourceID.value !== value){
  41028. this.uniforms.wSourceID.value = value;
  41029. this.dispatchEvent({
  41030. type: 'material_property_changed',
  41031. target: this
  41032. });
  41033. }
  41034. }
  41035. static generateGradientTexture (gradient) {
  41036. let size = 64;
  41037. // create canvas
  41038. let canvas = document.createElement('canvas');
  41039. canvas.width = size;
  41040. canvas.height = size;
  41041. // get context
  41042. let context = canvas.getContext('2d');
  41043. // draw gradient
  41044. context.rect(0, 0, size, size);
  41045. let ctxGradient = context.createLinearGradient(0, 0, size, size);
  41046. for (let i = 0; i < gradient.length; i++) {
  41047. let step = gradient[i];
  41048. ctxGradient.addColorStop(step[0], '#' + step[1].getHexString());
  41049. }
  41050. context.fillStyle = ctxGradient;
  41051. context.fill();
  41052. //let texture = new THREE.Texture(canvas);
  41053. let texture = new CanvasTexture(canvas);
  41054. texture.needsUpdate = true;
  41055. texture.minFilter = LinearFilter;
  41056. texture.wrap = RepeatWrapping;
  41057. texture.repeat = 2;
  41058. // textureImage = texture.image;
  41059. return texture;
  41060. }
  41061. static generateMatcapTexture (matcap) {
  41062. var url = new URL(Potree.resourcePath + "/textures/matcap/" + matcap).href;
  41063. let texture = new TextureLoader().load( url );
  41064. texture.magFilter = texture.minFilter = LinearFilter;
  41065. texture.needsUpdate = true;
  41066. // PotreeConverter_1.6_2018_07_29_windows_x64\PotreeConverter.exe autzen_xyzrgbXYZ_ascii.xyz -f xyzrgbXYZ -a RGB NORMAL -o autzen_xyzrgbXYZ_ascii_a -p index --overwrite
  41067. // Switch matcap texture on the fly : viewer.scene.pointclouds[0].material.matcap = 'matcap1.jpg';
  41068. // For non power of 2, use LinearFilter and dont generate mipmaps, For power of 2, use NearestFilter and generate mipmaps : matcap2.jpg 1 2 8 11 12 13
  41069. return texture;
  41070. }
  41071. disableEvents(){
  41072. if(this._hiddenListeners === undefined){
  41073. this._hiddenListeners = this._listeners;
  41074. this._listeners = {};
  41075. }
  41076. };
  41077. enableEvents(){
  41078. this._listeners = this._hiddenListeners;
  41079. this._hiddenListeners = undefined;
  41080. };
  41081. // copyFrom(from){
  41082. // var a = 10;
  41083. // for(let name of Object.keys(this.uniforms)){
  41084. // this.uniforms[name].value = from.uniforms[name].value;
  41085. // }
  41086. // }
  41087. // copy(from){
  41088. // this.copyFrom(from);
  41089. // }
  41090. }
  41091. //见ExtendPointCloudOctree
  41092. class PointCloudOctreeNode extends PointCloudTreeNode {
  41093. constructor () {
  41094. super();
  41095. //this.children = {};
  41096. this.children = [];
  41097. this.sceneNode = null;
  41098. this.octree = null;
  41099. }
  41100. getNumPoints () {
  41101. return this.geometryNode.numPoints;
  41102. }
  41103. isLoaded () {
  41104. return true;
  41105. }
  41106. isTreeNode () {
  41107. return true;
  41108. }
  41109. isGeometryNode () {
  41110. return false;
  41111. }
  41112. getLevel () {
  41113. return this.geometryNode.level;
  41114. }
  41115. getBoundingSphere () {
  41116. return this.geometryNode.boundingSphere;
  41117. }
  41118. getBoundingBox () {
  41119. return this.geometryNode.boundingBox;
  41120. }
  41121. getChildren () {
  41122. let children = [];
  41123. for (let i = 0; i < 8; i++) {
  41124. if (this.children[i]) {
  41125. children.push(this.children[i]);
  41126. }
  41127. }
  41128. return children;
  41129. }
  41130. getPointsInBox(boxNode){
  41131. if(!this.sceneNode){
  41132. return null;
  41133. }
  41134. let buffer = this.geometryNode.buffer;
  41135. let posOffset = buffer.offset("position");
  41136. let stride = buffer.stride;
  41137. let view = new DataView(buffer.data);
  41138. let worldToBox = boxNode.matrixWorld.clone().invert();
  41139. let objectToBox = new Matrix4().multiplyMatrices(worldToBox, this.sceneNode.matrixWorld);
  41140. let inBox = [];
  41141. let pos = new Vector4();
  41142. for(let i = 0; i < buffer.numElements; i++){
  41143. let x = view.getFloat32(i * stride + posOffset + 0, true);
  41144. let y = view.getFloat32(i * stride + posOffset + 4, true);
  41145. let z = view.getFloat32(i * stride + posOffset + 8, true);
  41146. pos.set(x, y, z, 1);
  41147. pos.applyMatrix4(objectToBox);
  41148. if(-0.5 < pos.x && pos.x < 0.5){
  41149. if(-0.5 < pos.y && pos.y < 0.5){
  41150. if(-0.5 < pos.z && pos.z < 0.5){
  41151. pos.set(x, y, z, 1).applyMatrix4(this.sceneNode.matrixWorld);
  41152. inBox.push(new Vector3(pos.x, pos.y, pos.z));
  41153. }
  41154. }
  41155. }
  41156. }
  41157. return inBox;
  41158. }
  41159. get name () {
  41160. return this.geometryNode.name;
  41161. }
  41162. };
  41163. class PointCloudOctree extends PointCloudTree {//base
  41164. constructor (geometry, material) {
  41165. super();
  41166. this.pointBudget = Infinity; //一直是这个值
  41167. this.pcoGeometry = geometry;
  41168. this.boundingBox = this.pcoGeometry.boundingBox;
  41169. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  41170. this.material = material || new PointCloudMaterial$1();
  41171. this.visiblePointsTarget = 2 * 1000 * 1000;
  41172. this.minimumNodePixelSize = 150;
  41173. this.level = 0;
  41174. this.position.copy(geometry.offset);
  41175. this.updateMatrix();
  41176. {
  41177. let priorityQueue = ["rgba", "rgb", "intensity", "classification"];
  41178. let selected = "rgba";
  41179. for(let attributeName of priorityQueue){
  41180. let attribute = this.pcoGeometry.pointAttributes.attributes.find(a => a.name === attributeName);
  41181. if(!attribute){
  41182. continue;
  41183. }
  41184. let min = attribute.range[0].constructor.name === "Array" ? attribute.range[0] : [attribute.range[0]];
  41185. let max = attribute.range[1].constructor.name === "Array" ? attribute.range[1] : [attribute.range[1]];
  41186. let range_min = new Vector3(...min);
  41187. let range_max = new Vector3(...max);
  41188. let range = range_min.distanceTo(range_max);
  41189. if(range === 0){
  41190. continue;
  41191. }
  41192. selected = attributeName;
  41193. break;
  41194. }
  41195. this.material.activeAttributeName = selected;
  41196. }
  41197. this.showBoundingBox = false;
  41198. this.boundingBoxNodes = [];
  41199. this.loadQueue = [];
  41200. this.visibleBounds = new Box3();
  41201. this.visibleNodes = [];
  41202. this.visibleGeometry = [];
  41203. this.generateDEM = false;
  41204. this.profileRequests = [];
  41205. this.name = '';
  41206. this._visible = true;
  41207. {
  41208. let box = [this.pcoGeometry.tightBoundingBox, this.getBoundingBoxWorld()]
  41209. .find(v => v !== undefined);
  41210. this.updateMatrixWorld(true);
  41211. box = Utils.computeTransformedBoundingBox(box, this.matrixWorld);
  41212. let bMin = box.min.z;
  41213. let bMax = box.max.z;
  41214. this.material.heightMin = bMin;
  41215. this.material.heightMax = bMax;
  41216. }
  41217. // TODO read projection from file instead
  41218. this.projection = geometry.projection;
  41219. this.fallbackProjection = geometry.fallbackProjection;
  41220. this.root = this.pcoGeometry.root;
  41221. }
  41222. setName (name) {
  41223. if (this.name !== name) {
  41224. this.name = name;
  41225. this.dispatchEvent({type: 'name_changed', name: name, pointcloud: this});
  41226. }
  41227. }
  41228. getName () {
  41229. return this.name;
  41230. }
  41231. getAttribute(name){
  41232. const attribute = this.pcoGeometry.pointAttributes.attributes.find(a => a.name === name);
  41233. if(attribute){
  41234. return attribute;
  41235. }else {
  41236. return null;
  41237. }
  41238. }
  41239. getAttributes(){
  41240. return this.pcoGeometry.pointAttributes;
  41241. }
  41242. toTreeNode (geometryNode, parent) {
  41243. let node = new PointCloudOctreeNode();
  41244. // if(geometryNode.name === "r40206"){
  41245. // console.log("creating node for r40206");
  41246. // }
  41247. let sceneNode = new Points(geometryNode.geometry, this.material);
  41248. sceneNode.name = geometryNode.name;
  41249. sceneNode.position.copy(geometryNode.boundingBox.min);
  41250. sceneNode.frustumCulled = false;
  41251. sceneNode.onBeforeRender = (_this, scene, camera, geometry, material, group) => {
  41252. if (material.program) {
  41253. _this.getContext().useProgram(material.program.program);
  41254. if (material.program.getUniforms().map.level) {
  41255. let level = geometryNode.getLevel();
  41256. material.uniforms.level.value = level;
  41257. material.program.getUniforms().map.level.setValue(_this.getContext(), level);
  41258. }
  41259. if (this.visibleNodeTextureOffsets && material.program.getUniforms().map.vnStart) {
  41260. let vnStart = this.visibleNodeTextureOffsets.get(node);
  41261. material.uniforms.vnStart.value = vnStart;
  41262. material.program.getUniforms().map.vnStart.setValue(_this.getContext(), vnStart);
  41263. }
  41264. if (material.program.getUniforms().map.pcIndex) {
  41265. let i = node.pcIndex ? node.pcIndex : this.visibleNodes.indexOf(node);
  41266. material.uniforms.pcIndex.value = i;
  41267. material.program.getUniforms().map.pcIndex.setValue(_this.getContext(), i);
  41268. }
  41269. }
  41270. };
  41271. // { // DEBUG
  41272. // let sg = new THREE.SphereGeometry(1, 16, 16);
  41273. // let sm = new THREE.MeshNormalMaterial();
  41274. // let s = new THREE.Mesh(sg, sm);
  41275. // s.scale.set(5, 5, 5);
  41276. // s.position.copy(geometryNode.mean)
  41277. // .add(this.position)
  41278. // .add(geometryNode.boundingBox.min);
  41279. //
  41280. // viewer.scene.scene.add(s);
  41281. // }
  41282. node.geometryNode = geometryNode;
  41283. node.sceneNode = sceneNode;
  41284. node.pointcloud = this;
  41285. node.children = [];
  41286. //for (let key in geometryNode.children) {
  41287. // node.children[key] = geometryNode.children[key];
  41288. //}
  41289. for(let i = 0; i < 8; i++){
  41290. node.children[i] = geometryNode.children[i];
  41291. }
  41292. if (!parent) {
  41293. this.root = node;
  41294. this.add(sceneNode);
  41295. } else {
  41296. let childIndex = parseInt(geometryNode.name[geometryNode.name.length - 1]);
  41297. parent.sceneNode.add(sceneNode);
  41298. parent.children[childIndex] = node;
  41299. }
  41300. let disposeListener = function () {
  41301. let childIndex = parseInt(geometryNode.name[geometryNode.name.length - 1]);
  41302. parent.sceneNode.remove(node.sceneNode);
  41303. parent.children[childIndex] = geometryNode;
  41304. };
  41305. geometryNode.oneTimeDisposeHandlers.push(disposeListener);
  41306. return node;
  41307. }
  41308. updateVisibleBounds () {
  41309. let leafNodes = [];
  41310. for (let i = 0; i < this.visibleNodes.length; i++) {
  41311. let node = this.visibleNodes[i];
  41312. let isLeaf = true;
  41313. for (let j = 0; j < node.children.length; j++) {
  41314. let child = node.children[j];
  41315. if (child instanceof PointCloudOctreeNode) {
  41316. isLeaf = isLeaf && !child.sceneNode.visible;
  41317. } else if (child instanceof PointCloudOctreeGeometryNode) {
  41318. isLeaf = true;
  41319. }
  41320. }
  41321. if (isLeaf) {
  41322. leafNodes.push(node);
  41323. }
  41324. }
  41325. this.visibleBounds.min = new Vector3(Infinity, Infinity, Infinity);
  41326. this.visibleBounds.max = new Vector3(-Infinity, -Infinity, -Infinity);
  41327. for (let i = 0; i < leafNodes.length; i++) {
  41328. let node = leafNodes[i];
  41329. this.visibleBounds.expandByPoint(node.getBoundingBox().min);
  41330. this.visibleBounds.expandByPoint(node.getBoundingBox().max);
  41331. }
  41332. }
  41333. updateMaterial (material, visibleNodes, camera, renderer) {
  41334. material.fov = camera.fov * (Math.PI / 180);
  41335. material.screenWidth = renderer.domElement.clientWidth;
  41336. material.screenHeight = renderer.domElement.clientHeight;
  41337. material.spacing = this.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  41338. material.near = camera.near;
  41339. material.far = camera.far;
  41340. material.uniforms.octreeSize.value = this.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  41341. }
  41342. computeVisibilityTextureData(nodes, camera){
  41343. if(Potree.measureTimings) performance.mark("computeVisibilityTextureData-start");
  41344. let data = new Uint8Array(nodes.length * 4);
  41345. let visibleNodeTextureOffsets = new Map();
  41346. // copy array
  41347. nodes = nodes.slice();
  41348. // sort by level and index, e.g. r, r0, r3, r4, r01, r07, r30, ...
  41349. let sort = function (a, b) {
  41350. let na = a.geometryNode.name;
  41351. let nb = b.geometryNode.name;
  41352. if (na.length !== nb.length) return na.length - nb.length;
  41353. if (na < nb) return -1;
  41354. if (na > nb) return 1;
  41355. return 0;
  41356. };
  41357. nodes.sort(sort);
  41358. let worldDir = new Vector3();
  41359. let nodeMap = new Map();
  41360. let offsetsToChild = new Array(nodes.length).fill(Infinity);
  41361. for(let i = 0; i < nodes.length; i++){
  41362. let node = nodes[i];
  41363. nodeMap.set(node.name, node);
  41364. visibleNodeTextureOffsets.set(node, i);
  41365. if(i > 0){
  41366. let index = parseInt(node.name.slice(-1));
  41367. let parentName = node.name.slice(0, -1);
  41368. let parent = nodeMap.get(parentName);
  41369. let parentOffset = visibleNodeTextureOffsets.get(parent);
  41370. let parentOffsetToChild = (i - parentOffset);
  41371. offsetsToChild[parentOffset] = Math.min(offsetsToChild[parentOffset], parentOffsetToChild);
  41372. data[parentOffset * 4 + 0] = data[parentOffset * 4 + 0] | (1 << index);
  41373. data[parentOffset * 4 + 1] = (offsetsToChild[parentOffset] >> 8);
  41374. data[parentOffset * 4 + 2] = (offsetsToChild[parentOffset] % 256);
  41375. }
  41376. let density = node.geometryNode.density;
  41377. if(typeof density === "number"){
  41378. let lodOffset = Math.log2(density) / 2 - 1.5;
  41379. let offsetUint8 = (lodOffset + 10) * 10;
  41380. data[i * 4 + 3] = offsetUint8;
  41381. }else {
  41382. data[i * 4 + 3] = 100;
  41383. }
  41384. }
  41385. if(Potree.measureTimings){
  41386. performance.mark("computeVisibilityTextureData-end");
  41387. performance.measure("render.computeVisibilityTextureData", "computeVisibilityTextureData-start", "computeVisibilityTextureData-end");
  41388. }
  41389. return {
  41390. data: data,
  41391. offsets: visibleNodeTextureOffsets
  41392. };
  41393. }
  41394. nodeIntersectsProfile (node, profile) {
  41395. let bbWorld = node.boundingBox.clone().applyMatrix4(this.matrixWorld);
  41396. let bsWorld = bbWorld.getBoundingSphere(new Sphere());
  41397. let intersects = false;
  41398. for (let i = 0; i < profile.points.length - 1; i++) {
  41399. let start = new Vector3(profile.points[i + 0].x, profile.points[i + 0].y, bsWorld.center.z);
  41400. let end = new Vector3(profile.points[i + 1].x, profile.points[i + 1].y, bsWorld.center.z);
  41401. let closest = new Line3(start, end).closestPointToPoint(bsWorld.center, true, new Vector3());
  41402. let distance = closest.distanceTo(bsWorld.center);
  41403. intersects = intersects || (distance < (bsWorld.radius + profile.width));
  41404. }
  41405. //console.log(`${node.name}: ${intersects}`);
  41406. return intersects;
  41407. }
  41408. deepestNodeAt(position){
  41409. const toObjectSpace = this.matrixWorld.clone().invert();
  41410. const objPos = position.clone().applyMatrix4(toObjectSpace);
  41411. let current = this.root;
  41412. while(true){
  41413. let containingChild = null;
  41414. for(const child of current.children){
  41415. if(child !== undefined){
  41416. if(child.getBoundingBox().containsPoint(objPos)){
  41417. containingChild = child;
  41418. }
  41419. }
  41420. }
  41421. if(containingChild !== null && containingChild instanceof PointCloudOctreeNode){
  41422. current = containingChild;
  41423. }else {
  41424. break;
  41425. }
  41426. }
  41427. const deepest = current;
  41428. return deepest;
  41429. }
  41430. nodesOnRay (nodes, ray) {
  41431. let nodesOnRay = [];
  41432. let _ray = ray.clone();
  41433. for (let i = 0; i < nodes.length; i++) {
  41434. let node = nodes[i];
  41435. let sphere = node.getBoundingSphere().clone().applyMatrix4(this.matrixWorld);
  41436. if (_ray.intersectsSphere(sphere)) {
  41437. nodesOnRay.push(node);
  41438. }
  41439. }
  41440. return nodesOnRay;
  41441. }
  41442. updateMatrixWorld (force) {
  41443. if (this.matrixAutoUpdate === true) this.updateMatrix();
  41444. if (this.matrixWorldNeedsUpdate === true || force === true) {
  41445. if (!this.parent) {
  41446. this.matrixWorld.copy(this.matrix);
  41447. } else {
  41448. this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
  41449. }
  41450. this.matrixWorldNeedsUpdate = false;
  41451. force = true;
  41452. }
  41453. }
  41454. hideDescendants (object) {
  41455. let stack = [];
  41456. for (let i = 0; i < object.children.length; i++) {
  41457. let child = object.children[i];
  41458. if (child.visible) {
  41459. stack.push(child);
  41460. }
  41461. }
  41462. while (stack.length > 0) {
  41463. let object = stack.shift();
  41464. object.visible = false;
  41465. for (let i = 0; i < object.children.length; i++) {
  41466. let child = object.children[i];
  41467. if (child.visible) {
  41468. stack.push(child);
  41469. }
  41470. }
  41471. }
  41472. }
  41473. moveToOrigin () {
  41474. this.position.set(0, 0, 0);
  41475. this.updateMatrixWorld(true);
  41476. let box = this.boundingBox;
  41477. let transform = this.matrixWorld;
  41478. let tBox = Utils.computeTransformedBoundingBox(box, transform);
  41479. this.position.set(0, 0, 0).sub(tBox.getCenter(new Vector3()));
  41480. };
  41481. moveToGroundPlane () {
  41482. this.updateMatrixWorld(true);
  41483. let box = this.boundingBox;
  41484. let transform = this.matrixWorld;
  41485. let tBox = Utils.computeTransformedBoundingBox(box, transform);
  41486. this.position.y += -tBox.min.y;
  41487. };
  41488. getBoundingBoxWorld () {
  41489. this.updateMatrixWorld(true);
  41490. let box = this.boundingBox;
  41491. let transform = this.matrixWorld;
  41492. let tBox = Utils.computeTransformedBoundingBox(box, transform);
  41493. return tBox;
  41494. };
  41495. /**
  41496. * returns points inside the profile points
  41497. *
  41498. * maxDepth: search points up to the given octree depth
  41499. *
  41500. *
  41501. * The return value is an array with all segments of the profile path
  41502. * let segment = {
  41503. * start: THREE.Vector3,
  41504. * end: THREE.Vector3,
  41505. * points: {}
  41506. * project: function()
  41507. * };
  41508. *
  41509. * The project() function inside each segment can be used to transform
  41510. * that segments point coordinates to line up along the x-axis.
  41511. *
  41512. *
  41513. */
  41514. getPointsInProfile (profile, maxDepth, callback) {
  41515. if (callback) {
  41516. let request = new Potree.ProfileRequest(this, profile, maxDepth, callback);
  41517. this.profileRequests.push(request);
  41518. return request;
  41519. }
  41520. let points = {
  41521. segments: [],
  41522. boundingBox: new Box3(),
  41523. projectedBoundingBox: new Box2()
  41524. };
  41525. // evaluate segments
  41526. for (let i = 0; i < profile.points.length - 1; i++) {
  41527. let start = profile.points[i];
  41528. let end = profile.points[i + 1];
  41529. let ps = this.getProfile(start, end, profile.width, maxDepth);
  41530. let segment = {
  41531. start: start,
  41532. end: end,
  41533. points: ps,
  41534. project: null
  41535. };
  41536. points.segments.push(segment);
  41537. points.boundingBox.expandByPoint(ps.boundingBox.min);
  41538. points.boundingBox.expandByPoint(ps.boundingBox.max);
  41539. }
  41540. // add projection functions to the segments
  41541. let mileage = new Vector3();
  41542. for (let i = 0; i < points.segments.length; i++) {
  41543. let segment = points.segments[i];
  41544. let start = segment.start;
  41545. let end = segment.end;
  41546. let project = (function (_start, _end, _mileage, _boundingBox) {
  41547. let start = _start;
  41548. let end = _end;
  41549. let mileage = _mileage;
  41550. let boundingBox = _boundingBox;
  41551. let xAxis = new Vector3(1, 0, 0);
  41552. let dir = new Vector3().subVectors(end, start);
  41553. dir.y = 0;
  41554. dir.normalize();
  41555. let alpha = Math.acos(xAxis.dot(dir));
  41556. if (dir.z > 0) {
  41557. alpha = -alpha;
  41558. }
  41559. return function (position) {
  41560. let toOrigin = new Matrix4().makeTranslation(-start.x, -boundingBox.min.y, -start.z);
  41561. let alignWithX = new Matrix4().makeRotationY(-alpha);
  41562. let applyMileage = new Matrix4().makeTranslation(mileage.x, 0, 0);
  41563. let pos = position.clone();
  41564. pos.applyMatrix4(toOrigin);
  41565. pos.applyMatrix4(alignWithX);
  41566. pos.applyMatrix4(applyMileage);
  41567. return pos;
  41568. };
  41569. }(start, end, mileage.clone(), points.boundingBox.clone()));
  41570. segment.project = project;
  41571. mileage.x += new Vector3(start.x, 0, start.z).distanceTo(new Vector3(end.x, 0, end.z));
  41572. mileage.y += end.y - start.y;
  41573. }
  41574. points.projectedBoundingBox.min.x = 0;
  41575. points.projectedBoundingBox.min.y = points.boundingBox.min.y;
  41576. points.projectedBoundingBox.max.x = mileage.x;
  41577. points.projectedBoundingBox.max.y = points.boundingBox.max.y;
  41578. return points;
  41579. }
  41580. /**
  41581. * returns points inside the given profile bounds.
  41582. *
  41583. * start:
  41584. * end:
  41585. * width:
  41586. * depth: search points up to the given octree depth
  41587. * callback: if specified, points are loaded before searching
  41588. *
  41589. *
  41590. */
  41591. getProfile (start, end, width, depth, callback) {
  41592. let request = new Potree.ProfileRequest(start, end, width, depth, callback);
  41593. this.profileRequests.push(request);
  41594. };
  41595. getVisibleExtent () {
  41596. return this.visibleBounds.applyMatrix4(this.matrixWorld);
  41597. };
  41598. intersectsPoint(position){
  41599. let rootAvailable = this.pcoGeometry.root && this.pcoGeometry.root.geometry;
  41600. if(!rootAvailable){
  41601. return false;
  41602. }
  41603. if(typeof this.signedDistanceField === "undefined"){
  41604. const resolution = 32;
  41605. const field = new Float32Array(resolution ** 3).fill(Infinity);
  41606. const positions = this.pcoGeometry.root.geometry.attributes.position;
  41607. const boundingBox = this.boundingBox;
  41608. const n = positions.count;
  41609. for(let i = 0; i < n; i = i + 3){
  41610. const x = positions.array[3 * i + 0];
  41611. const y = positions.array[3 * i + 1];
  41612. const z = positions.array[3 * i + 2];
  41613. const ix = parseInt(Math.min(resolution * (x / boundingBox.max.x), resolution - 1));
  41614. const iy = parseInt(Math.min(resolution * (y / boundingBox.max.y), resolution - 1));
  41615. const iz = parseInt(Math.min(resolution * (z / boundingBox.max.z), resolution - 1));
  41616. const index = ix + iy * resolution + iz * resolution * resolution;
  41617. field[index] = 0;
  41618. }
  41619. const sdf = {
  41620. resolution: resolution,
  41621. field: field,
  41622. };
  41623. this.signedDistanceField = sdf;
  41624. }
  41625. {
  41626. const sdf = this.signedDistanceField;
  41627. const boundingBox = this.boundingBox;
  41628. const toObjectSpace = this.matrixWorld.clone().invert();
  41629. const objPos = position.clone().applyMatrix4(toObjectSpace);
  41630. const resolution = sdf.resolution;
  41631. const ix = parseInt(resolution * (objPos.x / boundingBox.max.x));
  41632. const iy = parseInt(resolution * (objPos.y / boundingBox.max.y));
  41633. const iz = parseInt(resolution * (objPos.z / boundingBox.max.z));
  41634. if(ix < 0 || iy < 0 || iz < 0){
  41635. return false;
  41636. }
  41637. if(ix >= resolution || iy >= resolution || iz >= resolution){
  41638. return false;
  41639. }
  41640. const index = ix + iy * resolution + iz * resolution * resolution;
  41641. const value = sdf.field[index];
  41642. if(value === 0){
  41643. return true;
  41644. }
  41645. }
  41646. return false;
  41647. }
  41648. /**
  41649. *
  41650. *
  41651. *
  41652. * params.pickWindowSize: Look for points inside a pixel window of this size.
  41653. * Use odd values: 1, 3, 5, ...
  41654. *
  41655. *
  41656. * TODO: only draw pixels that are actually read with readPixels().
  41657. *
  41658. */
  41659. pick(viewer, camera, ray, params = {}){
  41660. let renderer = viewer.renderer;
  41661. let pRenderer = viewer.pRenderer;
  41662. performance.mark("pick-start");
  41663. let getVal = (a, b) => a !== undefined ? a : b;
  41664. let pickWindowSize = getVal(params.pickWindowSize, 65);
  41665. let pickOutsideClipRegion = getVal(params.pickOutsideClipRegion, false);
  41666. let size = renderer.getSize(new Vector2());
  41667. let width = Math.ceil(getVal(params.width, size.width));
  41668. let height = Math.ceil(getVal(params.height, size.height));
  41669. let pointSizeType = getVal(params.pointSizeType, this.material.pointSizeType);
  41670. let pointSize = getVal(params.pointSize, this.material.size);
  41671. let nodes = this.nodesOnRay(this.visibleNodes, ray);
  41672. if (nodes.length === 0) {
  41673. return null;
  41674. }
  41675. if (!this.pickState) {
  41676. let scene = new Scene();
  41677. let material = new Potree.PointCloudMaterial();
  41678. material.activeAttributeName = "indices";
  41679. let renderTarget = new WebGLRenderTarget(
  41680. 1, 1,
  41681. { minFilter: LinearFilter,
  41682. magFilter: NearestFilter,
  41683. format: RGBAFormat }
  41684. );
  41685. this.pickState = {
  41686. renderTarget: renderTarget,
  41687. material: material,
  41688. scene: scene
  41689. };
  41690. };
  41691. let pickState = this.pickState;
  41692. let pickMaterial = pickState.material;
  41693. { // update pick material
  41694. pickMaterial.pointSizeType = pointSizeType;
  41695. //pickMaterial.shape = this.material.shape;
  41696. pickMaterial.shape = Potree.PointShape.PARABOLOID;
  41697. pickMaterial.uniforms.uFilterReturnNumberRange.value = this.material.uniforms.uFilterReturnNumberRange.value;
  41698. pickMaterial.uniforms.uFilterNumberOfReturnsRange.value = this.material.uniforms.uFilterNumberOfReturnsRange.value;
  41699. pickMaterial.uniforms.uFilterGPSTimeClipRange.value = this.material.uniforms.uFilterGPSTimeClipRange.value;
  41700. pickMaterial.uniforms.uFilterPointSourceIDClipRange.value = this.material.uniforms.uFilterPointSourceIDClipRange.value;
  41701. pickMaterial.activeAttributeName = "indices";
  41702. pickMaterial.size = pointSize;
  41703. pickMaterial.uniforms.minSize.value = this.material.uniforms.minSize.value;
  41704. pickMaterial.uniforms.maxSize.value = this.material.uniforms.maxSize.value;
  41705. pickMaterial.classification = this.material.classification;
  41706. pickMaterial.recomputeClassification();
  41707. if(params.pickClipped){
  41708. pickMaterial.clipBoxes = this.material.clipBoxes;
  41709. pickMaterial.uniforms.clipBoxes = this.material.uniforms.clipBoxes;
  41710. if(this.material.clipTask === Potree.ClipTask.HIGHLIGHT){
  41711. pickMaterial.clipTask = Potree.ClipTask.NONE;
  41712. }else {
  41713. pickMaterial.clipTask = this.material.clipTask;
  41714. }
  41715. pickMaterial.clipMethod = this.material.clipMethod;
  41716. }else {
  41717. pickMaterial.clipBoxes = [];
  41718. }
  41719. this.updateMaterial(pickMaterial, nodes, camera, renderer);
  41720. }
  41721. pickState.renderTarget.setSize(width, height);
  41722. let pixelPos = new Vector2(params.x, params.y);
  41723. let gl = renderer.getContext();
  41724. gl.enable(gl.SCISSOR_TEST);
  41725. gl.scissor(
  41726. parseInt(pixelPos.x - (pickWindowSize - 1) / 2),
  41727. parseInt(pixelPos.y - (pickWindowSize - 1) / 2),
  41728. parseInt(pickWindowSize), parseInt(pickWindowSize));
  41729. renderer.state.buffers.depth.setTest(pickMaterial.depthTest);
  41730. renderer.state.buffers.depth.setMask(pickMaterial.depthWrite);
  41731. renderer.state.setBlending(NoBlending);
  41732. { // RENDER
  41733. renderer.setRenderTarget(pickState.renderTarget);
  41734. gl.clearColor(0, 0, 0, 0);
  41735. renderer.clear(true, true, true);
  41736. let tmp = this.material;
  41737. this.material = pickMaterial;
  41738. pRenderer.renderOctree(this, nodes, camera, pickState.renderTarget);
  41739. this.material = tmp;
  41740. }
  41741. let clamp = (number, min, max) => Math.min(Math.max(min, number), max);
  41742. let x = parseInt(clamp(pixelPos.x - (pickWindowSize - 1) / 2, 0, width));
  41743. let y = parseInt(clamp(pixelPos.y - (pickWindowSize - 1) / 2, 0, height));
  41744. let w = parseInt(Math.min(x + pickWindowSize, width) - x);
  41745. let h = parseInt(Math.min(y + pickWindowSize, height) - y);
  41746. let pixelCount = w * h;
  41747. let buffer = new Uint8Array(4 * pixelCount);
  41748. gl.readPixels(x, y, pickWindowSize, pickWindowSize, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
  41749. renderer.setRenderTarget(null);
  41750. renderer.state.reset();
  41751. renderer.setScissorTest(false);
  41752. gl.disable(gl.SCISSOR_TEST);
  41753. let pixels = buffer;
  41754. let ibuffer = new Uint32Array(buffer.buffer);
  41755. // find closest hit inside pixelWindow boundaries
  41756. let min = Number.MAX_VALUE;
  41757. let hits = [];
  41758. for (let u = 0; u < pickWindowSize; u++) {
  41759. for (let v = 0; v < pickWindowSize; v++) {
  41760. let offset = (u + v * pickWindowSize);
  41761. let distance = Math.pow(u - (pickWindowSize - 1) / 2, 2) + Math.pow(v - (pickWindowSize - 1) / 2, 2);
  41762. let pcIndex = pixels[4 * offset + 3];
  41763. pixels[4 * offset + 3] = 0;
  41764. let pIndex = ibuffer[offset];
  41765. if(!(pcIndex === 0 && pIndex === 0) && (pcIndex !== undefined) && (pIndex !== undefined)){
  41766. let hit = {
  41767. pIndex: pIndex,
  41768. pcIndex: pcIndex,
  41769. distanceToCenter: distance
  41770. };
  41771. if(params.all){
  41772. hits.push(hit);
  41773. }else {
  41774. if(hits.length > 0){
  41775. if(distance < hits[0].distanceToCenter){
  41776. hits[0] = hit;
  41777. }
  41778. }else {
  41779. hits.push(hit);
  41780. }
  41781. }
  41782. }
  41783. }
  41784. }
  41785. // { // DEBUG: show panel with pick image
  41786. // let img = Utils.pixelsArrayToImage(buffer, w, h);
  41787. // let screenshot = img.src;
  41788. // if(!this.debugDIV){
  41789. // this.debugDIV = $(`
  41790. // <div id="pickDebug"
  41791. // style="position: absolute;
  41792. // right: 400px; width: 300px;
  41793. // bottom: 44px; width: 300px;
  41794. // z-index: 1000;
  41795. // "></div>`);
  41796. // $(document.body).append(this.debugDIV);
  41797. // }
  41798. // this.debugDIV.empty();
  41799. // this.debugDIV.append($(`<img src="${screenshot}"
  41800. // style="transform: scaleY(-1); width: 300px"/>`));
  41801. // //$(this.debugWindow.document).append($(`<img src="${screenshot}"/>`));
  41802. // //this.debugWindow.document.write('<img src="'+screenshot+'"/>');
  41803. // }
  41804. for(let hit of hits){
  41805. let point = {};
  41806. if (!nodes[hit.pcIndex]) {
  41807. return null;
  41808. }
  41809. let node = nodes[hit.pcIndex];
  41810. let pc = node.sceneNode;
  41811. let geometry = node.geometryNode.geometry;
  41812. for(let attributeName in geometry.attributes){
  41813. let attribute = geometry.attributes[attributeName];
  41814. if (attributeName === 'position') {
  41815. let x = attribute.array[3 * hit.pIndex + 0];
  41816. let y = attribute.array[3 * hit.pIndex + 1];
  41817. let z = attribute.array[3 * hit.pIndex + 2];
  41818. let position = new Vector3(x, y, z);
  41819. position.applyMatrix4(pc.matrixWorld);
  41820. point[attributeName] = position;
  41821. } else if (attributeName === 'indices') {
  41822. } else {
  41823. let values = attribute.array.slice(attribute.itemSize * hit.pIndex, attribute.itemSize * (hit.pIndex + 1)) ;
  41824. if(attribute.potree){
  41825. const {scale, offset} = attribute.potree;
  41826. values = values.map(v => v / scale + offset);
  41827. }
  41828. point[attributeName] = values;
  41829. //debugger;
  41830. //if (values.itemSize === 1) {
  41831. // point[attribute.name] = values.array[hit.pIndex];
  41832. //} else {
  41833. // let value = [];
  41834. // for (let j = 0; j < values.itemSize; j++) {
  41835. // value.push(values.array[values.itemSize * hit.pIndex + j]);
  41836. // }
  41837. // point[attribute.name] = value;
  41838. //}
  41839. }
  41840. }
  41841. hit.point = point;
  41842. }
  41843. performance.mark("pick-end");
  41844. performance.measure("pick", "pick-start", "pick-end");
  41845. if(params.all){
  41846. return hits.map(hit => hit.point);
  41847. }else {
  41848. if(hits.length === 0){
  41849. return null;
  41850. }else {
  41851. return hits[0].point;
  41852. //let sorted = hits.sort( (a, b) => a.distanceToCenter - b.distanceToCenter);
  41853. //return sorted[0].point;
  41854. }
  41855. }
  41856. };
  41857. * getFittedBoxGen(boxNode){
  41858. let start = performance.now();
  41859. let shrinkedLocalBounds = new Box3();
  41860. let worldToBox = boxNode.matrixWorld.clone().invert();
  41861. for(let node of this.visibleNodes){
  41862. if(!node.sceneNode){
  41863. continue;
  41864. }
  41865. let buffer = node.geometryNode.buffer;
  41866. let posOffset = buffer.offset("position");
  41867. let stride = buffer.stride;
  41868. let view = new DataView(buffer.data);
  41869. let objectToBox = new Matrix4().multiplyMatrices(worldToBox, node.sceneNode.matrixWorld);
  41870. let pos = new Vector4();
  41871. for(let i = 0; i < buffer.numElements; i++){
  41872. let x = view.getFloat32(i * stride + posOffset + 0, true);
  41873. let y = view.getFloat32(i * stride + posOffset + 4, true);
  41874. let z = view.getFloat32(i * stride + posOffset + 8, true);
  41875. pos.set(x, y, z, 1);
  41876. pos.applyMatrix4(objectToBox);
  41877. if(-0.5 < pos.x && pos.x < 0.5){
  41878. if(-0.5 < pos.y && pos.y < 0.5){
  41879. if(-0.5 < pos.z && pos.z < 0.5){
  41880. shrinkedLocalBounds.expandByPoint(pos);
  41881. }
  41882. }
  41883. }
  41884. }
  41885. yield;
  41886. }
  41887. let fittedPosition = shrinkedLocalBounds.getCenter(new Vector3()).applyMatrix4(boxNode.matrixWorld);
  41888. let fitted = new Object3D();
  41889. fitted.position.copy(fittedPosition);
  41890. fitted.scale.copy(boxNode.scale);
  41891. fitted.rotation.copy(boxNode.rotation);
  41892. let ds = new Vector3().subVectors(shrinkedLocalBounds.max, shrinkedLocalBounds.min);
  41893. fitted.scale.multiply(ds);
  41894. let duration = performance.now() - start;
  41895. console.log("duration: ", duration);
  41896. yield fitted;
  41897. }
  41898. getFittedBox(boxNode, maxLevel = Infinity){
  41899. maxLevel = Infinity;
  41900. let start = performance.now();
  41901. let shrinkedLocalBounds = new Box3();
  41902. let worldToBox = boxNode.matrixWorld.clone().invert();
  41903. for(let node of this.visibleNodes){
  41904. if(!node.sceneNode || node.getLevel() > maxLevel){
  41905. continue;
  41906. }
  41907. let buffer = node.geometryNode.buffer;
  41908. let posOffset = buffer.offset("position");
  41909. let stride = buffer.stride;
  41910. let view = new DataView(buffer.data);
  41911. let objectToBox = new Matrix4().multiplyMatrices(worldToBox, node.sceneNode.matrixWorld);
  41912. let pos = new Vector4();
  41913. for(let i = 0; i < buffer.numElements; i++){
  41914. let x = view.getFloat32(i * stride + posOffset + 0, true);
  41915. let y = view.getFloat32(i * stride + posOffset + 4, true);
  41916. let z = view.getFloat32(i * stride + posOffset + 8, true);
  41917. pos.set(x, y, z, 1);
  41918. pos.applyMatrix4(objectToBox);
  41919. if(-0.5 < pos.x && pos.x < 0.5){
  41920. if(-0.5 < pos.y && pos.y < 0.5){
  41921. if(-0.5 < pos.z && pos.z < 0.5){
  41922. shrinkedLocalBounds.expandByPoint(pos);
  41923. }
  41924. }
  41925. }
  41926. }
  41927. }
  41928. let fittedPosition = shrinkedLocalBounds.getCenter(new Vector3()).applyMatrix4(boxNode.matrixWorld);
  41929. let fitted = new Object3D();
  41930. fitted.position.copy(fittedPosition);
  41931. fitted.scale.copy(boxNode.scale);
  41932. fitted.rotation.copy(boxNode.rotation);
  41933. let ds = new Vector3().subVectors(shrinkedLocalBounds.max, shrinkedLocalBounds.min);
  41934. fitted.scale.multiply(ds);
  41935. let duration = performance.now() - start;
  41936. console.log("duration: ", duration);
  41937. return fitted;
  41938. }
  41939. get progress () {
  41940. return this.visibleNodes.length / this.visibleGeometry.length;
  41941. }
  41942. find(name){
  41943. let node = null;
  41944. for(let char of name){
  41945. if(char === "r"){
  41946. node = this.root;
  41947. }else {
  41948. node = node.children[char];
  41949. }
  41950. }
  41951. return node;
  41952. }
  41953. get visible(){
  41954. return this._visible;
  41955. }
  41956. set visible(value){
  41957. if(value !== this._visible){
  41958. this._visible = value;
  41959. this.dispatchEvent({type: 'visibility_changed', pointcloud: this});
  41960. }
  41961. }
  41962. }
  41963. class PointCloudArena4DNode extends PointCloudTreeNode {
  41964. constructor () {
  41965. super();
  41966. this.left = null;
  41967. this.right = null;
  41968. this.sceneNode = null;
  41969. this.kdtree = null;
  41970. }
  41971. getNumPoints () {
  41972. return this.geometryNode.numPoints;
  41973. }
  41974. isLoaded () {
  41975. return true;
  41976. }
  41977. isTreeNode () {
  41978. return true;
  41979. }
  41980. isGeometryNode () {
  41981. return false;
  41982. }
  41983. getLevel () {
  41984. return this.geometryNode.level;
  41985. }
  41986. getBoundingSphere () {
  41987. return this.geometryNode.boundingSphere;
  41988. }
  41989. getBoundingBox () {
  41990. return this.geometryNode.boundingBox;
  41991. }
  41992. toTreeNode (child) {
  41993. let geometryNode = null;
  41994. if (this.left === child) {
  41995. geometryNode = this.left;
  41996. } else if (this.right === child) {
  41997. geometryNode = this.right;
  41998. }
  41999. if (!geometryNode.loaded) {
  42000. return;
  42001. }
  42002. let node = new PointCloudArena4DNode();
  42003. let sceneNode = PointCloud(geometryNode.geometry, this.kdtree.material);
  42004. sceneNode.visible = false;
  42005. node.kdtree = this.kdtree;
  42006. node.geometryNode = geometryNode;
  42007. node.sceneNode = sceneNode;
  42008. node.parent = this;
  42009. node.left = this.geometryNode.left;
  42010. node.right = this.geometryNode.right;
  42011. }
  42012. getChildren () {
  42013. let children = [];
  42014. if (this.left) {
  42015. children.push(this.left);
  42016. }
  42017. if (this.right) {
  42018. children.push(this.right);
  42019. }
  42020. return children;
  42021. }
  42022. };
  42023. class PointCloudArena4D$1 extends PointCloudTree{
  42024. constructor (geometry) {
  42025. super();
  42026. this.root = null;
  42027. if (geometry.root) {
  42028. this.root = geometry.root;
  42029. } else {
  42030. geometry.addEventListener('hierarchy_loaded', () => {
  42031. this.root = geometry.root;
  42032. });
  42033. }
  42034. this.visiblePointsTarget = 2 * 1000 * 1000;
  42035. this.minimumNodePixelSize = 150;
  42036. this.position.sub(geometry.offset);
  42037. this.updateMatrix();
  42038. this.numVisibleNodes = 0;
  42039. this.numVisiblePoints = 0;
  42040. this.boundingBoxNodes = [];
  42041. this.loadQueue = [];
  42042. this.visibleNodes = [];
  42043. this.pcoGeometry = geometry;
  42044. this.boundingBox = this.pcoGeometry.boundingBox;
  42045. this.boundingSphere = this.pcoGeometry.boundingSphere;
  42046. this.material = new PointCloudMaterial$1({vertexColors: VertexColors, size: 0.05, treeType: TreeType.KDTREE});
  42047. this.material.sizeType = PointSizeType.ATTENUATED;
  42048. this.material.size = 0.05;
  42049. this.profileRequests = [];
  42050. this.name = '';
  42051. }
  42052. getBoundingBoxWorld () {
  42053. this.updateMatrixWorld(true);
  42054. let box = this.boundingBox;
  42055. let transform = this.matrixWorld;
  42056. let tBox = Utils.computeTransformedBoundingBox(box, transform);
  42057. return tBox;
  42058. };
  42059. setName (name) {
  42060. if (this.name !== name) {
  42061. this.name = name;
  42062. this.dispatchEvent({type: 'name_changed', name: name, pointcloud: this});
  42063. }
  42064. }
  42065. getName () {
  42066. return this.name;
  42067. }
  42068. getLevel () {
  42069. return this.level;
  42070. }
  42071. toTreeNode (geometryNode, parent) {
  42072. let node = new PointCloudArena4DNode();
  42073. let sceneNode = new Points(geometryNode.geometry, this.material);
  42074. sceneNode.frustumCulled = false;
  42075. sceneNode.onBeforeRender = (_this, scene, camera, geometry, material, group) => {
  42076. if (material.program) {
  42077. _this.getContext().useProgram(material.program.program);
  42078. if (material.program.getUniforms().map.level) {
  42079. let level = geometryNode.getLevel();
  42080. material.uniforms.level.value = level;
  42081. material.program.getUniforms().map.level.setValue(_this.getContext(), level);
  42082. }
  42083. if (this.visibleNodeTextureOffsets && material.program.getUniforms().map.vnStart) {
  42084. let vnStart = this.visibleNodeTextureOffsets.get(node);
  42085. material.uniforms.vnStart.value = vnStart;
  42086. material.program.getUniforms().map.vnStart.setValue(_this.getContext(), vnStart);
  42087. }
  42088. if (material.program.getUniforms().map.pcIndex) {
  42089. let i = node.pcIndex ? node.pcIndex : this.visibleNodes.indexOf(node);
  42090. material.uniforms.pcIndex.value = i;
  42091. material.program.getUniforms().map.pcIndex.setValue(_this.getContext(), i);
  42092. }
  42093. }
  42094. };
  42095. node.geometryNode = geometryNode;
  42096. node.sceneNode = sceneNode;
  42097. node.pointcloud = this;
  42098. node.left = geometryNode.left;
  42099. node.right = geometryNode.right;
  42100. if (!parent) {
  42101. this.root = node;
  42102. this.add(sceneNode);
  42103. } else {
  42104. parent.sceneNode.add(sceneNode);
  42105. if (parent.left === geometryNode) {
  42106. parent.left = node;
  42107. } else if (parent.right === geometryNode) {
  42108. parent.right = node;
  42109. }
  42110. }
  42111. let disposeListener = function () {
  42112. parent.sceneNode.remove(node.sceneNode);
  42113. if (parent.left === node) {
  42114. parent.left = geometryNode;
  42115. } else if (parent.right === node) {
  42116. parent.right = geometryNode;
  42117. }
  42118. };
  42119. geometryNode.oneTimeDisposeHandlers.push(disposeListener);
  42120. return node;
  42121. }
  42122. updateMaterial (material, visibleNodes, camera, renderer) {
  42123. material.fov = camera.fov * (Math.PI / 180);
  42124. material.screenWidth = renderer.domElement.clientWidth;
  42125. material.screenHeight = renderer.domElement.clientHeight;
  42126. material.spacing = this.pcoGeometry.spacing;
  42127. material.near = camera.near;
  42128. material.far = camera.far;
  42129. // reduce shader source updates by setting maxLevel slightly higher than actually necessary
  42130. if (this.maxLevel > material.levels) {
  42131. material.levels = this.maxLevel + 2;
  42132. }
  42133. // material.uniforms.octreeSize.value = this.boundingBox.size().x;
  42134. let bbSize = this.boundingBox.getSize(new Vector3());
  42135. material.bbSize = [bbSize.x, bbSize.y, bbSize.z];
  42136. }
  42137. updateVisibleBounds () {
  42138. }
  42139. hideDescendants (object) {
  42140. let stack = [];
  42141. for (let i = 0; i < object.children.length; i++) {
  42142. let child = object.children[i];
  42143. if (child.visible) {
  42144. stack.push(child);
  42145. }
  42146. }
  42147. while (stack.length > 0) {
  42148. let child = stack.shift();
  42149. child.visible = false;
  42150. if (child.boundingBoxNode) {
  42151. child.boundingBoxNode.visible = false;
  42152. }
  42153. for (let i = 0; i < child.children.length; i++) {
  42154. let childOfChild = child.children[i];
  42155. if (childOfChild.visible) {
  42156. stack.push(childOfChild);
  42157. }
  42158. }
  42159. }
  42160. }
  42161. updateMatrixWorld (force) {
  42162. // node.matrixWorld.multiplyMatrices( node.parent.matrixWorld, node.matrix );
  42163. if (this.matrixAutoUpdate === true) this.updateMatrix();
  42164. if (this.matrixWorldNeedsUpdate === true || force === true) {
  42165. if (this.parent === undefined) {
  42166. this.matrixWorld.copy(this.matrix);
  42167. } else {
  42168. this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
  42169. }
  42170. this.matrixWorldNeedsUpdate = false;
  42171. force = true;
  42172. }
  42173. }
  42174. nodesOnRay (nodes, ray) {
  42175. let nodesOnRay = [];
  42176. let _ray = ray.clone();
  42177. for (let i = 0; i < nodes.length; i++) {
  42178. let node = nodes[i];
  42179. let sphere = node.getBoundingSphere().clone().applyMatrix4(node.sceneNode.matrixWorld);
  42180. // TODO Unused: let box = node.getBoundingBox().clone().applyMatrix4(node.sceneNode.matrixWorld);
  42181. if (_ray.intersectsSphere(sphere)) {
  42182. nodesOnRay.push(node);
  42183. }
  42184. // if(_ray.isIntersectionBox(box)){
  42185. // nodesOnRay.push(node);
  42186. // }
  42187. }
  42188. return nodesOnRay;
  42189. }
  42190. pick(viewer, camera, ray, params = {}){
  42191. let renderer = viewer.renderer;
  42192. let pRenderer = viewer.pRenderer;
  42193. performance.mark("pick-start");
  42194. let getVal = (a, b) => a !== undefined ? a : b;
  42195. let pickWindowSize = getVal(params.pickWindowSize, 17);
  42196. let pickOutsideClipRegion = getVal(params.pickOutsideClipRegion, false);
  42197. let size = renderer.getSize(new Vector2());
  42198. let width = Math.ceil(getVal(params.width, size.width));
  42199. let height = Math.ceil(getVal(params.height, size.height));
  42200. let pointSizeType = getVal(params.pointSizeType, this.material.pointSizeType);
  42201. let pointSize = getVal(params.pointSize, this.material.size);
  42202. let nodes = this.nodesOnRay(this.visibleNodes, ray);
  42203. if (nodes.length === 0) {
  42204. return null;
  42205. }
  42206. if (!this.pickState) {
  42207. let scene = new Scene();
  42208. let material = new PointCloudMaterial$1();
  42209. material.activeAttributeName = "indices";
  42210. let renderTarget = new WebGLRenderTarget(
  42211. 1, 1,
  42212. { minFilter: LinearFilter,
  42213. magFilter: NearestFilter,
  42214. format: RGBAFormat }
  42215. );
  42216. this.pickState = {
  42217. renderTarget: renderTarget,
  42218. material: material,
  42219. scene: scene
  42220. };
  42221. };
  42222. let pickState = this.pickState;
  42223. let pickMaterial = pickState.material;
  42224. { // update pick material
  42225. pickMaterial.pointSizeType = pointSizeType;
  42226. pickMaterial.shape = this.material.shape;
  42227. pickMaterial.size = pointSize;
  42228. pickMaterial.uniforms.minSize.value = this.material.uniforms.minSize.value;
  42229. pickMaterial.uniforms.maxSize.value = this.material.uniforms.maxSize.value;
  42230. pickMaterial.classification = this.material.classification;
  42231. if(params.pickClipped){
  42232. pickMaterial.clipBoxes = this.material.clipBoxes;
  42233. if(this.material.clipTask === ClipTask.HIGHLIGHT){
  42234. pickMaterial.clipTask = ClipTask.NONE;
  42235. }else {
  42236. pickMaterial.clipTask = this.material.clipTask;
  42237. }
  42238. }else {
  42239. pickMaterial.clipBoxes = [];
  42240. }
  42241. this.updateMaterial(pickMaterial, nodes, camera, renderer);
  42242. }
  42243. pickState.renderTarget.setSize(width, height);
  42244. let pixelPos = new Vector2(params.x, params.y);
  42245. let gl = renderer.getContext();
  42246. gl.enable(gl.SCISSOR_TEST);
  42247. gl.scissor(
  42248. parseInt(pixelPos.x - (pickWindowSize - 1) / 2),
  42249. parseInt(pixelPos.y - (pickWindowSize - 1) / 2),
  42250. parseInt(pickWindowSize), parseInt(pickWindowSize));
  42251. renderer.state.buffers.depth.setTest(pickMaterial.depthTest);
  42252. renderer.state.buffers.depth.setMask(pickMaterial.depthWrite);
  42253. renderer.state.setBlending(NoBlending);
  42254. renderer.clearTarget(pickState.renderTarget, true, true, true);
  42255. { // RENDER
  42256. renderer.setRenderTarget(pickState.renderTarget);
  42257. gl.clearColor(0, 0, 0, 0);
  42258. renderer.clearTarget( pickState.renderTarget, true, true, true );
  42259. let tmp = this.material;
  42260. this.material = pickMaterial;
  42261. pRenderer.renderOctree(this, nodes, camera, pickState.renderTarget);
  42262. this.material = tmp;
  42263. }
  42264. let clamp = (number, min, max) => Math.min(Math.max(min, number), max);
  42265. let x = parseInt(clamp(pixelPos.x - (pickWindowSize - 1) / 2, 0, width));
  42266. let y = parseInt(clamp(pixelPos.y - (pickWindowSize - 1) / 2, 0, height));
  42267. let w = parseInt(Math.min(x + pickWindowSize, width) - x);
  42268. let h = parseInt(Math.min(y + pickWindowSize, height) - y);
  42269. let pixelCount = w * h;
  42270. let buffer = new Uint8Array(4 * pixelCount);
  42271. gl.readPixels(x, y, pickWindowSize, pickWindowSize, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
  42272. renderer.setRenderTarget(null);
  42273. renderer.state.reset();
  42274. renderer.setScissorTest(false);
  42275. gl.disable(gl.SCISSOR_TEST);
  42276. let pixels = buffer;
  42277. let ibuffer = new Uint32Array(buffer.buffer);
  42278. // find closest hit inside pixelWindow boundaries
  42279. let min = Number.MAX_VALUE;
  42280. let hits = [];
  42281. for (let u = 0; u < pickWindowSize; u++) {
  42282. for (let v = 0; v < pickWindowSize; v++) {
  42283. let offset = (u + v * pickWindowSize);
  42284. let distance = Math.pow(u - (pickWindowSize - 1) / 2, 2) + Math.pow(v - (pickWindowSize - 1) / 2, 2);
  42285. let pcIndex = pixels[4 * offset + 3];
  42286. pixels[4 * offset + 3] = 0;
  42287. let pIndex = ibuffer[offset];
  42288. if(!(pcIndex === 0 && pIndex === 0) && (pcIndex !== undefined) && (pIndex !== undefined)){
  42289. let hit = {
  42290. pIndex: pIndex,
  42291. pcIndex: pcIndex,
  42292. distanceToCenter: distance
  42293. };
  42294. if(params.all){
  42295. hits.push(hit);
  42296. }else {
  42297. if(hits.length > 0){
  42298. if(distance < hits[0].distanceToCenter){
  42299. hits[0] = hit;
  42300. }
  42301. }else {
  42302. hits.push(hit);
  42303. }
  42304. }
  42305. }
  42306. }
  42307. }
  42308. for(let hit of hits){
  42309. let point = {};
  42310. if (!nodes[hit.pcIndex]) {
  42311. return null;
  42312. }
  42313. let node = nodes[hit.pcIndex];
  42314. let pc = node.sceneNode;
  42315. let geometry = node.geometryNode.geometry;
  42316. for(let attributeName in geometry.attributes){
  42317. let attribute = geometry.attributes[attributeName];
  42318. if (attributeName === 'position') {
  42319. let x = attribute.array[3 * hit.pIndex + 0];
  42320. let y = attribute.array[3 * hit.pIndex + 1];
  42321. let z = attribute.array[3 * hit.pIndex + 2];
  42322. let position = new Vector3(x, y, z);
  42323. position.applyMatrix4(pc.matrixWorld);
  42324. point[attributeName] = position;
  42325. } else if (attributeName === 'indices') {
  42326. } else {
  42327. //if (values.itemSize === 1) {
  42328. // point[attribute.name] = values.array[hit.pIndex];
  42329. //} else {
  42330. // let value = [];
  42331. // for (let j = 0; j < values.itemSize; j++) {
  42332. // value.push(values.array[values.itemSize * hit.pIndex + j]);
  42333. // }
  42334. // point[attribute.name] = value;
  42335. //}
  42336. }
  42337. }
  42338. hit.point = point;
  42339. }
  42340. performance.mark("pick-end");
  42341. performance.measure("pick", "pick-start", "pick-end");
  42342. if(params.all){
  42343. return hits.map(hit => hit.point);
  42344. }else {
  42345. if(hits.length === 0){
  42346. return null;
  42347. }else {
  42348. return hits[0].point;
  42349. }
  42350. }
  42351. }
  42352. computeVisibilityTextureData(nodes){
  42353. if(exports.measureTimings) performance.mark("computeVisibilityTextureData-start");
  42354. let data = new Uint8Array(nodes.length * 3);
  42355. let visibleNodeTextureOffsets = new Map();
  42356. // copy array
  42357. nodes = nodes.slice();
  42358. // sort by level and number
  42359. let sort = function (a, b) {
  42360. let la = a.geometryNode.level;
  42361. let lb = b.geometryNode.level;
  42362. let na = a.geometryNode.number;
  42363. let nb = b.geometryNode.number;
  42364. if (la !== lb) return la - lb;
  42365. if (na < nb) return -1;
  42366. if (na > nb) return 1;
  42367. return 0;
  42368. };
  42369. nodes.sort(sort);
  42370. let visibleNodeNames = [];
  42371. for (let i = 0; i < nodes.length; i++) {
  42372. visibleNodeNames.push(nodes[i].geometryNode.number);
  42373. }
  42374. for (let i = 0; i < nodes.length; i++) {
  42375. let node = nodes[i];
  42376. visibleNodeTextureOffsets.set(node, i);
  42377. let b1 = 0; // children
  42378. let b2 = 0; // offset to first child
  42379. let b3 = 0; // split
  42380. if (node.geometryNode.left && visibleNodeNames.indexOf(node.geometryNode.left.number) > 0) {
  42381. b1 += 1;
  42382. b2 = visibleNodeNames.indexOf(node.geometryNode.left.number) - i;
  42383. }
  42384. if (node.geometryNode.right && visibleNodeNames.indexOf(node.geometryNode.right.number) > 0) {
  42385. b1 += 2;
  42386. b2 = (b2 === 0) ? visibleNodeNames.indexOf(node.geometryNode.right.number) - i : b2;
  42387. }
  42388. if (node.geometryNode.split === 'X') {
  42389. b3 = 1;
  42390. } else if (node.geometryNode.split === 'Y') {
  42391. b3 = 2;
  42392. } else if (node.geometryNode.split === 'Z') {
  42393. b3 = 4;
  42394. }
  42395. data[i * 3 + 0] = b1;
  42396. data[i * 3 + 1] = b2;
  42397. data[i * 3 + 2] = b3;
  42398. }
  42399. if(exports.measureTimings){
  42400. performance.mark("computeVisibilityTextureData-end");
  42401. performance.measure("render.computeVisibilityTextureData", "computeVisibilityTextureData-start", "computeVisibilityTextureData-end");
  42402. }
  42403. return {
  42404. data: data,
  42405. offsets: visibleNodeTextureOffsets
  42406. };
  42407. }
  42408. get progress () {
  42409. if (this.pcoGeometry.root) {
  42410. return exports.numNodesLoading > 0 ? 0 : 1;
  42411. } else {
  42412. return 0;
  42413. }
  42414. }
  42415. };
  42416. // Copied from three.js: WebGLRenderer.js
  42417. function paramThreeToGL(_gl, p) {
  42418. let extension;
  42419. if (p === RepeatWrapping) return _gl.REPEAT;
  42420. if (p === ClampToEdgeWrapping) return _gl.CLAMP_TO_EDGE;
  42421. if (p === MirroredRepeatWrapping) return _gl.MIRRORED_REPEAT;
  42422. if (p === NearestFilter) return _gl.NEAREST;
  42423. if (p === NearestMipMapNearestFilter) return _gl.NEAREST_MIPMAP_NEAREST;
  42424. if (p === NearestMipMapLinearFilter) return _gl.NEAREST_MIPMAP_LINEAR;
  42425. if (p === LinearFilter) return _gl.LINEAR;
  42426. if (p === LinearMipMapNearestFilter) return _gl.LINEAR_MIPMAP_NEAREST;
  42427. if (p === LinearMipMapLinearFilter) return _gl.LINEAR_MIPMAP_LINEAR;
  42428. if (p === UnsignedByteType) return _gl.UNSIGNED_BYTE;
  42429. if (p === UnsignedShort4444Type) return _gl.UNSIGNED_SHORT_4_4_4_4;
  42430. if (p === UnsignedShort5551Type) return _gl.UNSIGNED_SHORT_5_5_5_1;
  42431. if (p === UnsignedShort565Type) return _gl.UNSIGNED_SHORT_5_6_5;
  42432. if (p === ByteType) return _gl.BYTE;
  42433. if (p === ShortType) return _gl.SHORT;
  42434. if (p === UnsignedShortType) return _gl.UNSIGNED_SHORT;
  42435. if (p === IntType) return _gl.INT;
  42436. if (p === UnsignedIntType) return _gl.UNSIGNED_INT;
  42437. if (p === FloatType) return _gl.FLOAT;
  42438. if (p === HalfFloatType) {
  42439. extension = extensions.get('OES_texture_half_float');
  42440. if (extension !== null) return extension.HALF_FLOAT_OES;
  42441. }
  42442. if (p === AlphaFormat) return _gl.ALPHA;
  42443. if (p === RGBFormat) return _gl.RGB;
  42444. if (p === RGBAFormat) return _gl.RGBA;
  42445. if (p === LuminanceFormat) return _gl.LUMINANCE;
  42446. if (p === LuminanceAlphaFormat) return _gl.LUMINANCE_ALPHA;
  42447. if (p === DepthFormat) return _gl.DEPTH_COMPONENT;
  42448. if (p === DepthStencilFormat) return _gl.DEPTH_STENCIL;
  42449. if (p === AddEquation) return _gl.FUNC_ADD;
  42450. if (p === SubtractEquation) return _gl.FUNC_SUBTRACT;
  42451. if (p === ReverseSubtractEquation) return _gl.FUNC_REVERSE_SUBTRACT;
  42452. if (p === ZeroFactor) return _gl.ZERO;
  42453. if (p === OneFactor) return _gl.ONE;
  42454. if (p === SrcColorFactor) return _gl.SRC_COLOR;
  42455. if (p === OneMinusSrcColorFactor) return _gl.ONE_MINUS_SRC_COLOR;
  42456. if (p === SrcAlphaFactor) return _gl.SRC_ALPHA;
  42457. if (p === OneMinusSrcAlphaFactor) return _gl.ONE_MINUS_SRC_ALPHA;
  42458. if (p === DstAlphaFactor) return _gl.DST_ALPHA;
  42459. if (p === OneMinusDstAlphaFactor) return _gl.ONE_MINUS_DST_ALPHA;
  42460. if (p === DstColorFactor) return _gl.DST_COLOR;
  42461. if (p === OneMinusDstColorFactor) return _gl.ONE_MINUS_DST_COLOR;
  42462. if (p === SrcAlphaSaturateFactor) return _gl.SRC_ALPHA_SATURATE;
  42463. if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
  42464. p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
  42465. extension = extensions.get('WEBGL_compressed_texture_s3tc');
  42466. if (extension !== null) {
  42467. if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
  42468. if (p === RGBA_S3TC_DXT1_Format$1) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
  42469. if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
  42470. if (p === RGBA_S3TC_DXT5_Format$1) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
  42471. }
  42472. }
  42473. if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
  42474. p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
  42475. extension = extensions.get('WEBGL_compressed_texture_pvrtc');
  42476. if (extension !== null) {
  42477. if (p === RGB_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  42478. if (p === RGB_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  42479. if (p === RGBA_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  42480. if (p === RGBA_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  42481. }
  42482. }
  42483. if (p === RGB_ETC1_Format) {
  42484. extension = extensions.get('WEBGL_compressed_texture_etc1');
  42485. if (extension !== null) return extension.COMPRESSED_RGB_ETC1_WEBGL;
  42486. }
  42487. if (p === MinEquation || p === MaxEquation) {
  42488. extension = extensions.get('EXT_blend_minmax');
  42489. if (extension !== null) {
  42490. if (p === MinEquation) return extension.MIN_EXT;
  42491. if (p === MaxEquation) return extension.MAX_EXT;
  42492. }
  42493. }
  42494. if (p === UnsignedInt248Type) {
  42495. extension = extensions.get('WEBGL_depth_texture');
  42496. if (extension !== null) return extension.UNSIGNED_INT_24_8_WEBGL;
  42497. }
  42498. return 0;
  42499. };
  42500. let attributeLocations = {
  42501. "position": {name: "position", location: 0},
  42502. "color": {name: "color", location: 1},
  42503. "rgba": {name: "color", location: 1},
  42504. "intensity": {name: "intensity", location: 2},
  42505. "classification": {name: "classification", location: 3},
  42506. "returnNumber": {name: "returnNumber", location: 4},
  42507. "return number": {name: "returnNumber", location: 4},
  42508. "returns": {name: "returnNumber", location: 4},
  42509. "numberOfReturns": {name: "numberOfReturns", location: 5},
  42510. "number of returns": {name: "numberOfReturns", location: 5},
  42511. "pointSourceID": {name: "pointSourceID", location: 6},
  42512. "source id": {name: "pointSourceID", location: 6},
  42513. "point source id": {name: "pointSourceID", location: 6},
  42514. "indices": {name: "indices", location: 7},
  42515. "normal": {name: "normal", location: 8},
  42516. "spacing": {name: "spacing", location: 9},
  42517. "gps-time": {name: "gpsTime", location: 10},
  42518. "aExtra": {name: "aExtra", location: 11},
  42519. };
  42520. class Shader {
  42521. constructor(gl, name, vsSource, fsSource) {
  42522. this.gl = gl;
  42523. this.name = name;
  42524. this.vsSource = vsSource;
  42525. this.fsSource = fsSource;
  42526. this.cache = new Map();
  42527. this.vs = null;
  42528. this.fs = null;
  42529. this.program = null;
  42530. this.uniformLocations = {};
  42531. this.attributeLocations = {};
  42532. this.uniformBlockIndices = {};
  42533. this.uniformBlocks = {};
  42534. this.uniforms = {};
  42535. this.update(vsSource, fsSource);
  42536. }
  42537. update(vsSource, fsSource) {
  42538. this.vsSource = vsSource;
  42539. this.fsSource = fsSource;
  42540. this.linkProgram();
  42541. }
  42542. compileShader(shader, source){
  42543. let gl = this.gl;
  42544. gl.shaderSource(shader, source);
  42545. gl.compileShader(shader);
  42546. let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  42547. if (!success) {
  42548. let info = gl.getShaderInfoLog(shader);
  42549. let numberedSource = source.split("\n").map((a, i) => `${i + 1}`.padEnd(5) + a).join("\n");
  42550. throw `could not compile shader ${this.name}: ${info}, \n${numberedSource}`;
  42551. }
  42552. }
  42553. linkProgram() {
  42554. const tStart = performance.now();
  42555. let gl = this.gl;
  42556. this.uniformLocations = {};
  42557. this.attributeLocations = {};
  42558. this.uniforms = {};
  42559. gl.useProgram(null);
  42560. let cached = this.cache.get(`${this.vsSource}, ${this.fsSource}`);
  42561. if (cached) {
  42562. this.program = cached.program;
  42563. this.vs = cached.vs;
  42564. this.fs = cached.fs;
  42565. this.attributeLocations = cached.attributeLocations;
  42566. this.uniformLocations = cached.uniformLocations;
  42567. this.uniformBlocks = cached.uniformBlocks;
  42568. this.uniforms = cached.uniforms;
  42569. return;
  42570. } else {
  42571. this.vs = gl.createShader(gl.VERTEX_SHADER);
  42572. this.fs = gl.createShader(gl.FRAGMENT_SHADER);
  42573. this.program = gl.createProgram();
  42574. for(let name of Object.keys(attributeLocations)){
  42575. let location = attributeLocations[name].location;
  42576. let glslName = attributeLocations[name].name;
  42577. gl.bindAttribLocation(this.program, location, glslName);
  42578. }
  42579. this.compileShader(this.vs, this.vsSource);
  42580. this.compileShader(this.fs, this.fsSource);
  42581. let program = this.program;
  42582. gl.attachShader(program, this.vs);
  42583. gl.attachShader(program, this.fs);
  42584. gl.linkProgram(program);
  42585. gl.detachShader(program, this.vs);
  42586. gl.detachShader(program, this.fs);
  42587. let success = gl.getProgramParameter(program, gl.LINK_STATUS);
  42588. if (!success) {
  42589. let info = gl.getProgramInfoLog(program);
  42590. throw `could not link program ${this.name}: ${info}`;
  42591. }
  42592. { // attribute locations
  42593. let numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
  42594. for (let i = 0; i < numAttributes; i++) {
  42595. let attribute = gl.getActiveAttrib(program, i);
  42596. let location = gl.getAttribLocation(program, attribute.name);
  42597. this.attributeLocations[attribute.name] = location;
  42598. }
  42599. }
  42600. { // uniform locations
  42601. let numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  42602. for (let i = 0; i < numUniforms; i++) {
  42603. let uniform = gl.getActiveUniform(program, i);
  42604. let location = gl.getUniformLocation(program, uniform.name);
  42605. this.uniformLocations[uniform.name] = location;
  42606. this.uniforms[uniform.name] = {
  42607. location: location,
  42608. value: null,
  42609. };
  42610. }
  42611. }
  42612. // uniform blocks
  42613. if(typeof WebGL2RenderingContext != 'undefined' && gl instanceof WebGL2RenderingContext){
  42614. let numBlocks = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
  42615. for (let i = 0; i < numBlocks; i++) {
  42616. let blockName = gl.getActiveUniformBlockName(program, i);
  42617. let blockIndex = gl.getUniformBlockIndex(program, blockName);
  42618. this.uniformBlockIndices[blockName] = blockIndex;
  42619. gl.uniformBlockBinding(program, blockIndex, blockIndex);
  42620. let dataSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
  42621. let uBuffer = gl.createBuffer();
  42622. gl.bindBuffer(gl.UNIFORM_BUFFER, uBuffer);
  42623. gl.bufferData(gl.UNIFORM_BUFFER, dataSize, gl.DYNAMIC_READ);
  42624. gl.bindBufferBase(gl.UNIFORM_BUFFER, blockIndex, uBuffer);
  42625. gl.bindBuffer(gl.UNIFORM_BUFFER, null);
  42626. this.uniformBlocks[blockName] = {
  42627. name: blockName,
  42628. index: blockIndex,
  42629. dataSize: dataSize,
  42630. buffer: uBuffer
  42631. };
  42632. }
  42633. }
  42634. let cached = {
  42635. program: this.program,
  42636. vs: this.vs,
  42637. fs: this.fs,
  42638. attributeLocations: this.attributeLocations,
  42639. uniformLocations: this.uniformLocations,
  42640. uniforms: this.uniforms,
  42641. uniformBlocks: this.uniformBlocks,
  42642. };
  42643. this.cache.set(`${this.vsSource}, ${this.fsSource}`, cached);
  42644. }
  42645. const tEnd = performance.now();
  42646. const duration = tEnd - tStart;
  42647. console.log(`shader compile duration: ${duration.toFixed(3)}`);
  42648. }
  42649. setUniformMatrix4(name, value) {
  42650. const gl = this.gl;
  42651. const location = this.uniformLocations[name];
  42652. if (location == null) {
  42653. return;
  42654. }
  42655. let tmp = new Float32Array(value.elements);
  42656. gl.uniformMatrix4fv(location, false, tmp);
  42657. }
  42658. setUniform1f(name, value) {
  42659. const gl = this.gl;
  42660. const uniform = this.uniforms[name];
  42661. if (uniform === undefined) {
  42662. return;
  42663. }
  42664. if(uniform.value === value){
  42665. return;
  42666. }
  42667. uniform.value = value;
  42668. gl.uniform1f(uniform.location, value);
  42669. }
  42670. setUniformBoolean(name, value) {
  42671. const gl = this.gl;
  42672. const uniform = this.uniforms[name];
  42673. if (uniform === undefined) {
  42674. return;
  42675. }
  42676. if(uniform.value === value){
  42677. return;
  42678. }
  42679. uniform.value = value;
  42680. gl.uniform1i(uniform.location, value);
  42681. }
  42682. setUniformTexture(name, value) {
  42683. const gl = this.gl;
  42684. const location = this.uniformLocations[name];
  42685. if (location == null) {
  42686. return;
  42687. }
  42688. gl.uniform1i(location, value);
  42689. }
  42690. setUniform2f(name, value) {
  42691. const gl = this.gl;
  42692. const location = this.uniformLocations[name];
  42693. if (location == null) {
  42694. return;
  42695. }
  42696. gl.uniform2f(location, value[0], value[1]);
  42697. }
  42698. setUniform3f(name, value) {
  42699. const gl = this.gl;
  42700. const location = this.uniformLocations[name];
  42701. if (location == null) {
  42702. return;
  42703. }
  42704. gl.uniform3f(location, value[0], value[1], value[2]);
  42705. }
  42706. setUniform(name, value) {
  42707. if (value.constructor === Matrix4) {
  42708. this.setUniformMatrix4(name, value);
  42709. } else if (typeof value === "number") {
  42710. this.setUniform1f(name, value);
  42711. } else if (typeof value === "boolean") {
  42712. this.setUniformBoolean(name, value);
  42713. } else if (value instanceof WebGLTexture) {
  42714. this.setUniformTexture(name, value);
  42715. } else if (value instanceof Array) {
  42716. if (value.length === 2) {
  42717. this.setUniform2f(name, value);
  42718. } else if (value.length === 3) {
  42719. this.setUniform3f(name, value);
  42720. }
  42721. } else {
  42722. console.error("unhandled uniform type: ", name, value);
  42723. }
  42724. }
  42725. setUniform1i(name, value) {
  42726. let gl = this.gl;
  42727. let location = this.uniformLocations[name];
  42728. if (location == null) {
  42729. return;
  42730. }
  42731. gl.uniform1i(location, value);
  42732. }
  42733. };
  42734. class WebGLTexture {
  42735. constructor(gl, texture) {
  42736. this.gl = gl;
  42737. this.texture = texture;
  42738. this.id = gl.createTexture();
  42739. this.target = gl.TEXTURE_2D;
  42740. this.version = -1;
  42741. this.update(texture);
  42742. }
  42743. update() {
  42744. if (!this.texture.image) {
  42745. this.version = this.texture.version;
  42746. return;
  42747. }
  42748. let gl = this.gl;
  42749. let texture = this.texture;
  42750. if (this.version === texture.version) {
  42751. return;
  42752. }
  42753. this.target = gl.TEXTURE_2D;
  42754. gl.bindTexture(this.target, this.id);
  42755. let level = 0;
  42756. let internalFormat = paramThreeToGL(gl, texture.format);
  42757. let width = texture.image.width;
  42758. let height = texture.image.height;
  42759. let border = 0;
  42760. let srcFormat = internalFormat;
  42761. let srcType = paramThreeToGL(gl, texture.type);
  42762. let data;
  42763. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
  42764. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha);
  42765. gl.pixelStorei(gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
  42766. if (texture instanceof DataTexture) {
  42767. data = texture.image.data;
  42768. gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  42769. gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  42770. gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, paramThreeToGL(gl, texture.magFilter));
  42771. gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, paramThreeToGL(gl, texture.minFilter));
  42772. gl.texImage2D(this.target, level, internalFormat,
  42773. width, height, border, srcFormat, srcType,
  42774. data);
  42775. } else if ((texture instanceof CanvasTexture) || (texture instanceof Texture)) {
  42776. data = texture.image;
  42777. gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, paramThreeToGL(gl, texture.wrapS));
  42778. gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, paramThreeToGL(gl, texture.wrapT));
  42779. gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, paramThreeToGL(gl, texture.magFilter));
  42780. gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, paramThreeToGL(gl, texture.minFilter));
  42781. gl.texImage2D(this.target, level, internalFormat,
  42782. internalFormat, srcType, data);
  42783. if (texture instanceof Texture) {gl.generateMipmap(gl.TEXTURE_2D);}
  42784. }
  42785. gl.bindTexture(this.target, null);
  42786. this.version = texture.version;
  42787. }
  42788. };
  42789. class WebGLBuffer {
  42790. constructor() {
  42791. this.numElements = 0;
  42792. this.vao = null;
  42793. this.vbos = new Map();
  42794. }
  42795. };
  42796. class Renderer {
  42797. constructor(threeRenderer) {
  42798. this.threeRenderer = threeRenderer;
  42799. this.gl = this.threeRenderer.getContext();
  42800. this.buffers = new Map();
  42801. this.shaders = new Map();
  42802. this.textures = new Map();
  42803. this.glTypeMapping = new Map();
  42804. this.glTypeMapping.set(Float32Array, this.gl.FLOAT);
  42805. this.glTypeMapping.set(Uint8Array, this.gl.UNSIGNED_BYTE);
  42806. this.glTypeMapping.set(Uint16Array, this.gl.UNSIGNED_SHORT);
  42807. this.toggle = 0;
  42808. }
  42809. deleteBuffer(geometry) {
  42810. let gl = this.gl;
  42811. let webglBuffer = this.buffers.get(geometry);
  42812. if (webglBuffer != null) {
  42813. for (let attributeName in geometry.attributes) {
  42814. gl.deleteBuffer(webglBuffer.vbos.get(attributeName).handle);
  42815. }
  42816. this.buffers.delete(geometry);
  42817. }
  42818. }
  42819. createBuffer(geometry){
  42820. let gl = this.gl;
  42821. let webglBuffer = new WebGLBuffer();
  42822. webglBuffer.vao = gl.createVertexArray();
  42823. webglBuffer.numElements = geometry.attributes.position.count;
  42824. gl.bindVertexArray(webglBuffer.vao);
  42825. for(let attributeName in geometry.attributes){
  42826. let bufferAttribute = geometry.attributes[attributeName];
  42827. let vbo = gl.createBuffer();
  42828. gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  42829. gl.bufferData(gl.ARRAY_BUFFER, bufferAttribute.array, gl.STATIC_DRAW);
  42830. let normalized = bufferAttribute.normalized;
  42831. let type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  42832. if(attributeLocations[attributeName] === undefined){
  42833. //attributeLocation = attributeLocations["aExtra"];
  42834. }else {
  42835. let attributeLocation = attributeLocations[attributeName].location;
  42836. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  42837. gl.enableVertexAttribArray(attributeLocation);
  42838. }
  42839. webglBuffer.vbos.set(attributeName, {
  42840. handle: vbo,
  42841. name: attributeName,
  42842. count: bufferAttribute.count,
  42843. itemSize: bufferAttribute.itemSize,
  42844. type: geometry.attributes.position.array.constructor,
  42845. version: 0
  42846. });
  42847. }
  42848. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  42849. gl.bindVertexArray(null);
  42850. let disposeHandler = (event) => {
  42851. this.deleteBuffer(geometry);
  42852. geometry.removeEventListener("dispose", disposeHandler);
  42853. };
  42854. geometry.addEventListener("dispose", disposeHandler);
  42855. return webglBuffer;
  42856. }
  42857. updateBuffer(geometry){
  42858. let gl = this.gl;
  42859. let webglBuffer = this.buffers.get(geometry);
  42860. gl.bindVertexArray(webglBuffer.vao);
  42861. for(let attributeName in geometry.attributes){
  42862. let bufferAttribute = geometry.attributes[attributeName];
  42863. let normalized = bufferAttribute.normalized;
  42864. let type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  42865. let vbo = null;
  42866. if(!webglBuffer.vbos.has(attributeName)){
  42867. vbo = gl.createBuffer();
  42868. webglBuffer.vbos.set(attributeName, {
  42869. handle: vbo,
  42870. name: attributeName,
  42871. count: bufferAttribute.count,
  42872. itemSize: bufferAttribute.itemSize,
  42873. type: geometry.attributes.position.array.constructor,
  42874. version: bufferAttribute.version
  42875. });
  42876. }else {
  42877. vbo = webglBuffer.vbos.get(attributeName).handle;
  42878. webglBuffer.vbos.get(attributeName).version = bufferAttribute.version;
  42879. }
  42880. gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  42881. gl.bufferData(gl.ARRAY_BUFFER, bufferAttribute.array, gl.STATIC_DRAW);
  42882. if(attributeLocations[attributeName] === undefined){
  42883. //attributeLocation = attributeLocations["aExtra"];
  42884. }else {
  42885. let attributeLocation = attributeLocations[attributeName].location;
  42886. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  42887. gl.enableVertexAttribArray(attributeLocation);
  42888. }
  42889. }
  42890. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  42891. gl.bindVertexArray(null);
  42892. }
  42893. traverse(scene) {
  42894. let octrees = [];
  42895. let stack = [scene];
  42896. while (stack.length > 0) {
  42897. let node = stack.pop();
  42898. if (node instanceof PointCloudTree) {
  42899. octrees.push(node);
  42900. continue;
  42901. }
  42902. let visibleChildren = node.children.filter(c => c.visible);
  42903. stack.push(...visibleChildren);
  42904. }
  42905. let result = {
  42906. octrees: octrees
  42907. };
  42908. return result;
  42909. }
  42910. renderNodes(octree, nodes, visibilityTextureData, camera, target, shader, params) {
  42911. if (exports.measureTimings) performance.mark("renderNodes-start");
  42912. let gl = this.gl;
  42913. let material = params.material ? params.material : octree.material;
  42914. let shadowMaps = params.shadowMaps == null ? [] : params.shadowMaps;
  42915. let view = camera.matrixWorldInverse;
  42916. if(params.viewOverride){
  42917. view = params.viewOverride;
  42918. }
  42919. let worldView = new Matrix4();
  42920. let mat4holder = new Float32Array(16);
  42921. let i = 0;
  42922. for (let node of nodes) {
  42923. if(exports.debug.allowedNodes !== undefined){
  42924. if(!exports.debug.allowedNodes.includes(node.name)){
  42925. continue;
  42926. }
  42927. }
  42928. let world = node.sceneNode.matrixWorld;
  42929. worldView.multiplyMatrices(view, world);
  42930. if (visibilityTextureData) {
  42931. let vnStart = visibilityTextureData.offsets.get(node);
  42932. shader.setUniform1f("uVNStart", vnStart);
  42933. }
  42934. let level = node.getLevel();
  42935. if(node.debug){
  42936. shader.setUniform("uDebug", true);
  42937. }else {
  42938. shader.setUniform("uDebug", false);
  42939. }
  42940. // let isLeaf = false;
  42941. // if(node instanceof PointCloudOctreeNode){
  42942. // isLeaf = Object.keys(node.children).length === 0;
  42943. // }else if(node instanceof PointCloudArena4DNode){
  42944. // isLeaf = node.geometryNode.isLeaf;
  42945. // }
  42946. // shader.setUniform("uIsLeafNode", isLeaf);
  42947. // let isLeaf = node.children.filter(n => n != null).length === 0;
  42948. // if(!isLeaf){
  42949. // continue;
  42950. // }
  42951. // TODO consider passing matrices in an array to avoid uniformMatrix4fv overhead
  42952. const lModel = shader.uniformLocations["modelMatrix"];
  42953. if (lModel) {
  42954. mat4holder.set(world.elements);
  42955. gl.uniformMatrix4fv(lModel, false, mat4holder);
  42956. }
  42957. const lModelView = shader.uniformLocations["modelViewMatrix"];
  42958. //mat4holder.set(worldView.elements);
  42959. // faster then set in chrome 63
  42960. for(let j = 0; j < 16; j++){
  42961. mat4holder[j] = worldView.elements[j];
  42962. }
  42963. gl.uniformMatrix4fv(lModelView, false, mat4holder);
  42964. { // Clip Polygons
  42965. if(material.clipPolygons && material.clipPolygons.length > 0){
  42966. let clipPolygonVCount = [];
  42967. let worldViewProjMatrices = [];
  42968. for(let clipPolygon of material.clipPolygons){
  42969. let view = clipPolygon.viewMatrix;
  42970. let proj = clipPolygon.projMatrix;
  42971. let worldViewProj = proj.clone().multiply(view).multiply(world);
  42972. clipPolygonVCount.push(clipPolygon.markers.length);
  42973. worldViewProjMatrices.push(worldViewProj);
  42974. }
  42975. let flattenedMatrices = [].concat(...worldViewProjMatrices.map(m => m.elements));
  42976. let flattenedVertices = new Array(8 * 3 * material.clipPolygons.length);
  42977. for(let i = 0; i < material.clipPolygons.length; i++){
  42978. let clipPolygon = material.clipPolygons[i];
  42979. for(let j = 0; j < clipPolygon.markers.length; j++){
  42980. flattenedVertices[i * 24 + (j * 3 + 0)] = clipPolygon.markers[j].position.x;
  42981. flattenedVertices[i * 24 + (j * 3 + 1)] = clipPolygon.markers[j].position.y;
  42982. flattenedVertices[i * 24 + (j * 3 + 2)] = clipPolygon.markers[j].position.z;
  42983. }
  42984. }
  42985. const lClipPolygonVCount = shader.uniformLocations["uClipPolygonVCount[0]"];
  42986. gl.uniform1iv(lClipPolygonVCount, clipPolygonVCount);
  42987. const lClipPolygonVP = shader.uniformLocations["uClipPolygonWVP[0]"];
  42988. gl.uniformMatrix4fv(lClipPolygonVP, false, flattenedMatrices);
  42989. const lClipPolygons = shader.uniformLocations["uClipPolygonVertices[0]"];
  42990. gl.uniform3fv(lClipPolygons, flattenedVertices);
  42991. }
  42992. }
  42993. //shader.setUniformMatrix4("modelMatrix", world);
  42994. //shader.setUniformMatrix4("modelViewMatrix", worldView);
  42995. shader.setUniform1f("uLevel", level);
  42996. shader.setUniform1f("uNodeSpacing", node.geometryNode.estimatedSpacing);
  42997. shader.setUniform1f("uPCIndex", i);
  42998. // uBBSize
  42999. if (shadowMaps.length > 0) {
  43000. const lShadowMap = shader.uniformLocations["uShadowMap[0]"];
  43001. shader.setUniform3f("uShadowColor", material.uniforms.uShadowColor.value);
  43002. let bindingStart = 5;
  43003. let bindingPoints = new Array(shadowMaps.length).fill(bindingStart).map((a, i) => (a + i));
  43004. gl.uniform1iv(lShadowMap, bindingPoints);
  43005. for (let i = 0; i < shadowMaps.length; i++) {
  43006. let shadowMap = shadowMaps[i];
  43007. let bindingPoint = bindingPoints[i];
  43008. let glTexture = this.threeRenderer.properties.get(shadowMap.target.texture).__webglTexture;
  43009. gl.activeTexture(gl[`TEXTURE${bindingPoint}`]);
  43010. gl.bindTexture(gl.TEXTURE_2D, glTexture);
  43011. }
  43012. {
  43013. let worldViewMatrices = shadowMaps
  43014. .map(sm => sm.camera.matrixWorldInverse)
  43015. .map(view => new Matrix4().multiplyMatrices(view, world));
  43016. let flattenedMatrices = [].concat(...worldViewMatrices.map(c => c.elements));
  43017. const lWorldView = shader.uniformLocations["uShadowWorldView[0]"];
  43018. gl.uniformMatrix4fv(lWorldView, false, flattenedMatrices);
  43019. }
  43020. {
  43021. let flattenedMatrices = [].concat(...shadowMaps.map(sm => sm.camera.projectionMatrix.elements));
  43022. const lProj = shader.uniformLocations["uShadowProj[0]"];
  43023. gl.uniformMatrix4fv(lProj, false, flattenedMatrices);
  43024. }
  43025. }
  43026. const geometry = node.geometryNode.geometry;
  43027. if(geometry.attributes["gps-time"]){
  43028. const bufferAttribute = geometry.attributes["gps-time"];
  43029. const attGPS = octree.getAttribute("gps-time");
  43030. let initialRange = attGPS.initialRange;
  43031. let initialRangeSize = initialRange[1] - initialRange[0];
  43032. let globalRange = attGPS.range;
  43033. let globalRangeSize = globalRange[1] - globalRange[0];
  43034. let scale = initialRangeSize / globalRangeSize;
  43035. let offset = -(globalRange[0] - initialRange[0]) / initialRangeSize;
  43036. scale = Number.isNaN(scale) ? 1 : scale;
  43037. offset = Number.isNaN(offset) ? 0 : offset;
  43038. shader.setUniform1f("uGpsScale", scale);
  43039. shader.setUniform1f("uGpsOffset", offset);
  43040. //shader.setUniform2f("uFilterGPSTimeClipRange", [-Infinity, Infinity]);
  43041. let uFilterGPSTimeClipRange = material.uniforms.uFilterGPSTimeClipRange.value;
  43042. // let gpsCliPRangeMin = uFilterGPSTimeClipRange[0]
  43043. // let gpsCliPRangeMax = uFilterGPSTimeClipRange[1]
  43044. // shader.setUniform2f("uFilterGPSTimeClipRange", [gpsCliPRangeMin, gpsCliPRangeMax]);
  43045. let normalizedClipRange = [
  43046. (uFilterGPSTimeClipRange[0] - globalRange[0]) / globalRangeSize,
  43047. (uFilterGPSTimeClipRange[1] - globalRange[0]) / globalRangeSize,
  43048. ];
  43049. shader.setUniform2f("uFilterGPSTimeClipRange", normalizedClipRange);
  43050. // // ranges in full gps coordinate system
  43051. // const globalRange = attGPS.range;
  43052. // const bufferRange = bufferAttribute.potree.range;
  43053. // // ranges in [0, 1]
  43054. // // normalizedGlobalRange = [0, 1]
  43055. // // normalizedBufferRange: norm buffer within norm global range e.g. [0.2, 0.8]
  43056. // const globalWidth = globalRange[1] - globalRange[0];
  43057. // const normalizedBufferRange = [
  43058. // (bufferRange[0] - globalRange[0]) / globalWidth,
  43059. // (bufferRange[1] - globalRange[0]) / globalWidth,
  43060. // ];
  43061. // shader.setUniform2f("uNormalizedGpsBufferRange", normalizedBufferRange);
  43062. // let uFilterGPSTimeClipRange = material.uniforms.uFilterGPSTimeClipRange.value;
  43063. // let gpsCliPRangeMin = uFilterGPSTimeClipRange[0]
  43064. // let gpsCliPRangeMax = uFilterGPSTimeClipRange[1]
  43065. // shader.setUniform2f("uFilterGPSTimeClipRange", [gpsCliPRangeMin, gpsCliPRangeMax]);
  43066. // shader.setUniform1f("uGpsScale", bufferAttribute.potree.scale);
  43067. // shader.setUniform1f("uGpsOffset", bufferAttribute.potree.offset);
  43068. }
  43069. {
  43070. let uFilterReturnNumberRange = material.uniforms.uFilterReturnNumberRange.value;
  43071. let uFilterNumberOfReturnsRange = material.uniforms.uFilterNumberOfReturnsRange.value;
  43072. let uFilterPointSourceIDClipRange = material.uniforms.uFilterPointSourceIDClipRange.value;
  43073. shader.setUniform2f("uFilterReturnNumberRange", uFilterReturnNumberRange);
  43074. shader.setUniform2f("uFilterNumberOfReturnsRange", uFilterNumberOfReturnsRange);
  43075. shader.setUniform2f("uFilterPointSourceIDClipRange", uFilterPointSourceIDClipRange);
  43076. }
  43077. let webglBuffer = null;
  43078. if(!this.buffers.has(geometry)){
  43079. webglBuffer = this.createBuffer(geometry);
  43080. this.buffers.set(geometry, webglBuffer);
  43081. }else {
  43082. webglBuffer = this.buffers.get(geometry);
  43083. for(let attributeName in geometry.attributes){
  43084. let attribute = geometry.attributes[attributeName];
  43085. if(attribute.version > webglBuffer.vbos.get(attributeName).version){
  43086. this.updateBuffer(geometry);
  43087. }
  43088. }
  43089. }
  43090. gl.bindVertexArray(webglBuffer.vao);
  43091. let isExtraAttribute =
  43092. attributeLocations[material.activeAttributeName] === undefined
  43093. && Object.keys(geometry.attributes).includes(material.activeAttributeName);
  43094. if(isExtraAttribute){
  43095. const attributeLocation = attributeLocations["aExtra"].location;
  43096. for(const attributeName in geometry.attributes){
  43097. const bufferAttribute = geometry.attributes[attributeName];
  43098. const vbo = webglBuffer.vbos.get(attributeName);
  43099. gl.bindBuffer(gl.ARRAY_BUFFER, vbo.handle);
  43100. gl.disableVertexAttribArray(attributeLocation);
  43101. }
  43102. const attName = material.activeAttributeName;
  43103. const bufferAttribute = geometry.attributes[attName];
  43104. const vbo = webglBuffer.vbos.get(attName);
  43105. if(bufferAttribute !== undefined && vbo !== undefined){
  43106. let type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  43107. let normalized = bufferAttribute.normalized;
  43108. gl.bindBuffer(gl.ARRAY_BUFFER, vbo.handle);
  43109. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  43110. gl.enableVertexAttribArray(attributeLocation);
  43111. }
  43112. {
  43113. const attExtra = octree.pcoGeometry.pointAttributes.attributes
  43114. .find(a => a.name === attName);
  43115. let range = material.getRange(attName);
  43116. if(!range){
  43117. range = attExtra.range;
  43118. }
  43119. if(!range){
  43120. range = [0, 1];
  43121. }
  43122. let initialRange = attExtra.initialRange;
  43123. let initialRangeSize = initialRange[1] - initialRange[0];
  43124. let globalRange = range;
  43125. let globalRangeSize = globalRange[1] - globalRange[0];
  43126. let scale = initialRangeSize / globalRangeSize;
  43127. let offset = -(globalRange[0] - initialRange[0]) / initialRangeSize;
  43128. scale = Number.isNaN(scale) ? 1 : scale;
  43129. offset = Number.isNaN(offset) ? 0 : offset;
  43130. shader.setUniform1f("uExtraScale", scale);
  43131. shader.setUniform1f("uExtraOffset", offset);
  43132. }
  43133. }else {
  43134. for(const attributeName in geometry.attributes){
  43135. const bufferAttribute = geometry.attributes[attributeName];
  43136. const vbo = webglBuffer.vbos.get(attributeName);
  43137. if(attributeLocations[attributeName] !== undefined){
  43138. const attributeLocation = attributeLocations[attributeName].location;
  43139. let type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  43140. let normalized = bufferAttribute.normalized;
  43141. gl.bindBuffer(gl.ARRAY_BUFFER, vbo.handle);
  43142. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  43143. gl.enableVertexAttribArray(attributeLocation);
  43144. }
  43145. }
  43146. }
  43147. let numPoints = webglBuffer.numElements;
  43148. gl.drawArrays(gl.POINTS, 0, numPoints);
  43149. i++;
  43150. }
  43151. gl.bindVertexArray(null);
  43152. if (exports.measureTimings) {
  43153. performance.mark("renderNodes-end");
  43154. performance.measure("render.renderNodes", "renderNodes-start", "renderNodes-end");
  43155. }
  43156. }
  43157. renderOctree(octree, nodes, camera, target, params = {}){
  43158. let gl = this.gl;
  43159. let material = params.material ? params.material : octree.material;
  43160. let shadowMaps = params.shadowMaps == null ? [] : params.shadowMaps;
  43161. let view = camera.matrixWorldInverse;
  43162. let viewInv = camera.matrixWorld;
  43163. if(params.viewOverride){
  43164. view = params.viewOverride;
  43165. viewInv = view.clone().invert();
  43166. }
  43167. let proj = camera.projectionMatrix;
  43168. let projInv = proj.clone().invert();
  43169. //let worldView = new THREE.Matrix4();
  43170. let shader = null;
  43171. let visibilityTextureData = null;
  43172. let currentTextureBindingPoint = 0;
  43173. if (material.pointSizeType >= 0) {
  43174. if (material.pointSizeType === PointSizeType.ADAPTIVE ||
  43175. material.activeAttributeName === "level of detail") {
  43176. let vnNodes = (params.vnTextureNodes != null) ? params.vnTextureNodes : nodes;
  43177. visibilityTextureData = octree.computeVisibilityTextureData(vnNodes, camera);
  43178. const vnt = material.visibleNodesTexture;
  43179. const data = vnt.image.data;
  43180. data.set(visibilityTextureData.data);
  43181. vnt.needsUpdate = true;
  43182. }
  43183. }
  43184. { // UPDATE SHADER AND TEXTURES
  43185. if (!this.shaders.has(material)) {
  43186. let [vs, fs] = [material.vertexShader, material.fragmentShader];
  43187. let shader = new Shader(gl, "pointcloud", vs, fs);
  43188. this.shaders.set(material, shader);
  43189. }
  43190. shader = this.shaders.get(material);
  43191. //if(material.needsUpdate){
  43192. {
  43193. let [vs, fs] = [material.vertexShader, material.fragmentShader];
  43194. let numSnapshots = material.snapEnabled ? material.numSnapshots : 0;
  43195. let numClipBoxes = (material.clipBoxes && material.clipBoxes.length) ? material.clipBoxes.length : 0;
  43196. let numClipSpheres = (params.clipSpheres && params.clipSpheres.length) ? params.clipSpheres.length : 0;
  43197. let numClipPolygons = (material.clipPolygons && material.clipPolygons.length) ? material.clipPolygons.length : 0;
  43198. let defines = [
  43199. `#define num_shadowmaps ${shadowMaps.length}`,
  43200. `#define num_snapshots ${numSnapshots}`,
  43201. `#define num_clipboxes ${numClipBoxes}`,
  43202. `#define num_clipspheres ${numClipSpheres}`,
  43203. `#define num_clippolygons ${numClipPolygons}`,
  43204. ];
  43205. if(octree.pcoGeometry.root.isLoaded()){
  43206. let attributes = octree.pcoGeometry.root.geometry.attributes;
  43207. if(attributes["gps-time"]){
  43208. defines.push("#define clip_gps_enabled");
  43209. }
  43210. if(attributes["return number"]){
  43211. defines.push("#define clip_return_number_enabled");
  43212. }
  43213. if(attributes["number of returns"]){
  43214. defines.push("#define clip_number_of_returns_enabled");
  43215. }
  43216. if(attributes["source id"] || attributes["point source id"]){
  43217. defines.push("#define clip_point_source_id_enabled");
  43218. }
  43219. }
  43220. let definesString = defines.join("\n");
  43221. let vsVersionIndex = vs.indexOf("#version ");
  43222. let fsVersionIndex = fs.indexOf("#version ");
  43223. if(vsVersionIndex >= 0){
  43224. vs = vs.replace(/(#version .*)/, `$1\n${definesString}`);
  43225. }else {
  43226. vs = `${definesString}\n${vs}`;
  43227. }
  43228. if(fsVersionIndex >= 0){
  43229. fs = fs.replace(/(#version .*)/, `$1\n${definesString}`);
  43230. }else {
  43231. fs = `${definesString}\n${fs}`;
  43232. }
  43233. shader.update(vs, fs);
  43234. material.needsUpdate = false;
  43235. }
  43236. for (let uniformName of Object.keys(material.uniforms)) {
  43237. let uniform = material.uniforms[uniformName];
  43238. if (uniform.type == "t") {
  43239. let texture = uniform.value;
  43240. if (!texture) {
  43241. continue;
  43242. }
  43243. if (!this.textures.has(texture)) {
  43244. let webglTexture = new WebGLTexture(gl, texture);
  43245. this.textures.set(texture, webglTexture);
  43246. }
  43247. let webGLTexture = this.textures.get(texture);
  43248. webGLTexture.update();
  43249. }
  43250. }
  43251. }
  43252. gl.useProgram(shader.program);
  43253. let transparent = false;
  43254. if(params.transparent !== undefined){
  43255. transparent = params.transparent && material.opacity < 1;
  43256. }else {
  43257. transparent = material.opacity < 1;
  43258. }
  43259. if (transparent){
  43260. gl.enable(gl.BLEND);
  43261. gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
  43262. gl.depthMask(false);
  43263. gl.disable(gl.DEPTH_TEST);
  43264. } else {
  43265. gl.disable(gl.BLEND);
  43266. gl.depthMask(true);
  43267. gl.enable(gl.DEPTH_TEST);
  43268. }
  43269. if(params.blendFunc !== undefined){
  43270. gl.enable(gl.BLEND);
  43271. gl.blendFunc(...params.blendFunc);
  43272. }
  43273. if(params.depthTest !== undefined){
  43274. if(params.depthTest === true){
  43275. gl.enable(gl.DEPTH_TEST);
  43276. }else {
  43277. gl.disable(gl.DEPTH_TEST);
  43278. }
  43279. }
  43280. if(params.depthWrite !== undefined){
  43281. if(params.depthWrite === true){
  43282. gl.depthMask(true);
  43283. }else {
  43284. gl.depthMask(false);
  43285. }
  43286. }
  43287. { // UPDATE UNIFORMS
  43288. shader.setUniformMatrix4("projectionMatrix", proj);
  43289. shader.setUniformMatrix4("viewMatrix", view);
  43290. shader.setUniformMatrix4("uViewInv", viewInv);
  43291. shader.setUniformMatrix4("uProjInv", projInv);
  43292. let screenWidth = target ? target.width : material.screenWidth;
  43293. let screenHeight = target ? target.height : material.screenHeight;
  43294. shader.setUniform1f("uScreenWidth", screenWidth);
  43295. shader.setUniform1f("uScreenHeight", screenHeight);
  43296. shader.setUniform1f("fov", Math.PI * camera.fov / 180);
  43297. shader.setUniform1f("near", camera.near);
  43298. shader.setUniform1f("far", camera.far);
  43299. if(camera instanceof OrthographicCamera){
  43300. shader.setUniform("uUseOrthographicCamera", true);
  43301. shader.setUniform("uOrthoWidth", camera.right - camera.left);
  43302. shader.setUniform("uOrthoHeight", camera.top - camera.bottom);
  43303. }else {
  43304. shader.setUniform("uUseOrthographicCamera", false);
  43305. }
  43306. if(material.clipBoxes.length + material.clipPolygons.length === 0){
  43307. shader.setUniform1i("clipTask", ClipTask.NONE);
  43308. }else {
  43309. shader.setUniform1i("clipTask", material.clipTask);
  43310. }
  43311. shader.setUniform1i("clipMethod", material.clipMethod);
  43312. if (material.clipBoxes && material.clipBoxes.length > 0) {
  43313. //let flattenedMatrices = [].concat(...material.clipBoxes.map(c => c.inverse.elements));
  43314. //const lClipBoxes = shader.uniformLocations["clipBoxes[0]"];
  43315. //gl.uniformMatrix4fv(lClipBoxes, false, flattenedMatrices);
  43316. const lClipBoxes = shader.uniformLocations["clipBoxes[0]"];
  43317. gl.uniformMatrix4fv(lClipBoxes, false, material.uniforms.clipBoxes.value);
  43318. }
  43319. // TODO CLIPSPHERES
  43320. if(params.clipSpheres && params.clipSpheres.length > 0){
  43321. let clipSpheres = params.clipSpheres;
  43322. let matrices = [];
  43323. for(let clipSphere of clipSpheres){
  43324. //let mScale = new THREE.Matrix4().makeScale(...clipSphere.scale.toArray());
  43325. //let mTranslate = new THREE.Matrix4().makeTranslation(...clipSphere.position.toArray());
  43326. //let clipToWorld = new THREE.Matrix4().multiplyMatrices(mTranslate, mScale);
  43327. let clipToWorld = clipSphere.matrixWorld;
  43328. let viewToWorld = camera.matrixWorld;
  43329. let worldToClip = clipToWorld.clone().invert();
  43330. let viewToClip = new Matrix4().multiplyMatrices(worldToClip, viewToWorld);
  43331. matrices.push(viewToClip);
  43332. }
  43333. let flattenedMatrices = [].concat(...matrices.map(matrix => matrix.elements));
  43334. const lClipSpheres = shader.uniformLocations["uClipSpheres[0]"];
  43335. gl.uniformMatrix4fv(lClipSpheres, false, flattenedMatrices);
  43336. //const lClipSpheres = shader.uniformLocations["uClipSpheres[0]"];
  43337. //gl.uniformMatrix4fv(lClipSpheres, false, material.uniforms.clipSpheres.value);
  43338. }
  43339. shader.setUniform1f("size", material.size);
  43340. shader.setUniform1f("maxSize", material.uniforms.maxSize.value);
  43341. shader.setUniform1f("minSize", material.uniforms.minSize.value);
  43342. // uniform float uPCIndex
  43343. shader.setUniform1f("uOctreeSpacing", material.spacing);
  43344. shader.setUniform("uOctreeSize", material.uniforms.octreeSize.value);
  43345. //uniform vec3 uColor;
  43346. shader.setUniform3f("uColor", material.color.toArray());
  43347. //uniform float opacity;
  43348. shader.setUniform1f("uOpacity", material.opacity);
  43349. shader.setUniform2f("elevationRange", material.elevationRange);
  43350. shader.setUniform2f("intensityRange", material.intensityRange);
  43351. shader.setUniform3f("uIntensity_gbc", [
  43352. material.intensityGamma,
  43353. material.intensityBrightness,
  43354. material.intensityContrast
  43355. ]);
  43356. shader.setUniform3f("uRGB_gbc", [
  43357. material.rgbGamma,
  43358. material.rgbBrightness,
  43359. material.rgbContrast
  43360. ]);
  43361. shader.setUniform1f("uTransition", material.transition);
  43362. shader.setUniform1f("wRGB", material.weightRGB);
  43363. shader.setUniform1f("wIntensity", material.weightIntensity);
  43364. shader.setUniform1f("wElevation", material.weightElevation);
  43365. shader.setUniform1f("wClassification", material.weightClassification);
  43366. shader.setUniform1f("wReturnNumber", material.weightReturnNumber);
  43367. shader.setUniform1f("wSourceID", material.weightSourceID);
  43368. shader.setUniform("backfaceCulling", material.uniforms.backfaceCulling.value);
  43369. let vnWebGLTexture = this.textures.get(material.visibleNodesTexture);
  43370. if(vnWebGLTexture){
  43371. shader.setUniform1i("visibleNodesTexture", currentTextureBindingPoint);
  43372. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  43373. gl.bindTexture(vnWebGLTexture.target, vnWebGLTexture.id);
  43374. currentTextureBindingPoint++;
  43375. }
  43376. let gradientTexture = this.textures.get(material.gradientTexture);
  43377. shader.setUniform1i("gradient", currentTextureBindingPoint);
  43378. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  43379. gl.bindTexture(gradientTexture.target, gradientTexture.id);
  43380. const repeat = material.elevationGradientRepeat;
  43381. if(repeat === ElevationGradientRepeat.REPEAT){
  43382. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.REPEAT);
  43383. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.REPEAT);
  43384. }else if(repeat === ElevationGradientRepeat.MIRRORED_REPEAT){
  43385. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
  43386. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
  43387. }else {
  43388. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  43389. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  43390. }
  43391. currentTextureBindingPoint++;
  43392. let classificationTexture = this.textures.get(material.classificationTexture);
  43393. shader.setUniform1i("classificationLUT", currentTextureBindingPoint);
  43394. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  43395. gl.bindTexture(classificationTexture.target, classificationTexture.id);
  43396. currentTextureBindingPoint++;
  43397. let matcapTexture = this.textures.get(material.matcapTexture);
  43398. shader.setUniform1i("matcapTextureUniform", currentTextureBindingPoint);
  43399. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  43400. gl.bindTexture(matcapTexture.target, matcapTexture.id);
  43401. currentTextureBindingPoint++;
  43402. if (material.snapEnabled === true) {
  43403. {
  43404. const lSnapshot = shader.uniformLocations["uSnapshot[0]"];
  43405. const lSnapshotDepth = shader.uniformLocations["uSnapshotDepth[0]"];
  43406. let bindingStart = currentTextureBindingPoint;
  43407. let lSnapshotBindingPoints = new Array(5).fill(bindingStart).map((a, i) => (a + i));
  43408. let lSnapshotDepthBindingPoints = new Array(5)
  43409. .fill(1 + Math.max(...lSnapshotBindingPoints))
  43410. .map((a, i) => (a + i));
  43411. currentTextureBindingPoint = 1 + Math.max(...lSnapshotDepthBindingPoints);
  43412. gl.uniform1iv(lSnapshot, lSnapshotBindingPoints);
  43413. gl.uniform1iv(lSnapshotDepth, lSnapshotDepthBindingPoints);
  43414. for (let i = 0; i < 5; i++) {
  43415. let texture = material.uniforms[`uSnapshot`].value[i];
  43416. let textureDepth = material.uniforms[`uSnapshotDepth`].value[i];
  43417. if (!texture) {
  43418. break;
  43419. }
  43420. let snapTexture = this.threeRenderer.properties.get(texture).__webglTexture;
  43421. let snapTextureDepth = this.threeRenderer.properties.get(textureDepth).__webglTexture;
  43422. let bindingPoint = lSnapshotBindingPoints[i];
  43423. let depthBindingPoint = lSnapshotDepthBindingPoints[i];
  43424. gl.activeTexture(gl[`TEXTURE${bindingPoint}`]);
  43425. gl.bindTexture(gl.TEXTURE_2D, snapTexture);
  43426. gl.activeTexture(gl[`TEXTURE${depthBindingPoint}`]);
  43427. gl.bindTexture(gl.TEXTURE_2D, snapTextureDepth);
  43428. }
  43429. }
  43430. {
  43431. let flattenedMatrices = [].concat(...material.uniforms.uSnapView.value.map(c => c.elements));
  43432. const lSnapView = shader.uniformLocations["uSnapView[0]"];
  43433. gl.uniformMatrix4fv(lSnapView, false, flattenedMatrices);
  43434. }
  43435. {
  43436. let flattenedMatrices = [].concat(...material.uniforms.uSnapProj.value.map(c => c.elements));
  43437. const lSnapProj = shader.uniformLocations["uSnapProj[0]"];
  43438. gl.uniformMatrix4fv(lSnapProj, false, flattenedMatrices);
  43439. }
  43440. {
  43441. let flattenedMatrices = [].concat(...material.uniforms.uSnapProjInv.value.map(c => c.elements));
  43442. const lSnapProjInv = shader.uniformLocations["uSnapProjInv[0]"];
  43443. gl.uniformMatrix4fv(lSnapProjInv, false, flattenedMatrices);
  43444. }
  43445. {
  43446. let flattenedMatrices = [].concat(...material.uniforms.uSnapViewInv.value.map(c => c.elements));
  43447. const lSnapViewInv = shader.uniformLocations["uSnapViewInv[0]"];
  43448. gl.uniformMatrix4fv(lSnapViewInv, false, flattenedMatrices);
  43449. }
  43450. }
  43451. }
  43452. this.renderNodes(octree, nodes, visibilityTextureData, camera, target, shader, params);
  43453. gl.activeTexture(gl.TEXTURE2);
  43454. gl.bindTexture(gl.TEXTURE_2D, null);
  43455. gl.activeTexture(gl.TEXTURE0);
  43456. }
  43457. render(scene, camera, target = null, params = {}) {
  43458. const gl = this.gl;
  43459. // PREPARE
  43460. if (target != null) {
  43461. this.threeRenderer.setRenderTarget(target);
  43462. }
  43463. //camera.updateProjectionMatrix();
  43464. // camera.matrixWorldInverse.invert(camera.matrixWorld);
  43465. const traversalResult = this.traverse(scene);
  43466. // RENDER
  43467. for (const octree of traversalResult.octrees) {
  43468. let nodes = octree.visibleNodes;
  43469. this.renderOctree(octree, nodes, camera, target, params);
  43470. }
  43471. // CLEANUP
  43472. gl.activeTexture(gl.TEXTURE1);
  43473. gl.bindTexture(gl.TEXTURE_2D, null);
  43474. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  43475. gl.bindVertexArray(null);
  43476. this.threeRenderer.resetState();
  43477. }
  43478. };
  43479. function copyMaterial(source, target){
  43480. for(let name of Object.keys(target.uniforms)){
  43481. target.uniforms[name].value = source.uniforms[name].value;
  43482. }
  43483. target.gradientTexture = source.gradientTexture;
  43484. target.visibleNodesTexture = source.visibleNodesTexture;
  43485. target.classificationTexture = source.classificationTexture;
  43486. target.matcapTexture = source.matcapTexture;
  43487. target.activeAttributeName = source.activeAttributeName;
  43488. target.ranges = source.ranges;
  43489. //target.updateShaderSource();
  43490. }
  43491. class Batch{
  43492. constructor(geometry, material){
  43493. this.geometry = geometry;
  43494. this.material = material;
  43495. this.sceneNode = new Points(geometry, material);
  43496. this.geometryNode = {
  43497. estimatedSpacing: 1.0,
  43498. geometry: geometry,
  43499. };
  43500. }
  43501. getLevel(){
  43502. return 0;
  43503. }
  43504. }
  43505. class ProfileFakeOctree extends PointCloudTree{
  43506. constructor(octree){
  43507. super();
  43508. this.trueOctree = octree;
  43509. this.pcoGeometry = octree.pcoGeometry;
  43510. this.points = [];
  43511. this.visibleNodes = [];
  43512. //this.material = this.trueOctree.material;
  43513. this.material = new PointCloudMaterial$1();
  43514. //this.material.copy(this.trueOctree.material);
  43515. copyMaterial(this.trueOctree.material, this.material);
  43516. this.material.pointSizeType = PointSizeType.FIXED;
  43517. this.batchSize = 100 * 1000;
  43518. this.currentBatch = null;
  43519. }
  43520. getAttribute(name){
  43521. return this.trueOctree.getAttribute(name);
  43522. }
  43523. dispose(){
  43524. for(let node of this.visibleNodes){
  43525. node.geometry.dispose();
  43526. }
  43527. this.visibleNodes = [];
  43528. this.currentBatch = null;
  43529. this.points = [];
  43530. }
  43531. addPoints(data){
  43532. // since each call to addPoints can deliver very very few points,
  43533. // we're going to batch them into larger buffers for efficiency.
  43534. if(this.currentBatch === null){
  43535. this.currentBatch = this.createNewBatch(data);
  43536. }
  43537. this.points.push(data);
  43538. let updateRange = {
  43539. start: this.currentBatch.geometry.drawRange.count,
  43540. count: 0
  43541. };
  43542. let projectedBox = new Box3();
  43543. let truePos = new Vector3();
  43544. for(let i = 0; i < data.numPoints; i++){
  43545. if(updateRange.start + updateRange.count >= this.batchSize){
  43546. // current batch full, start new batch
  43547. for(let key of Object.keys(this.currentBatch.geometry.attributes)){
  43548. let attribute = this.currentBatch.geometry.attributes[key];
  43549. attribute.updateRange.offset = updateRange.start;
  43550. attribute.updateRange.count = updateRange.count;
  43551. attribute.needsUpdate = true;
  43552. }
  43553. this.currentBatch.geometry.computeBoundingBox();
  43554. this.currentBatch.geometry.computeBoundingSphere();
  43555. this.currentBatch = this.createNewBatch(data);
  43556. updateRange = {
  43557. start: 0,
  43558. count: 0
  43559. };
  43560. }
  43561. truePos.set(
  43562. data.data.position[3 * i + 0] + this.trueOctree.position.x,
  43563. data.data.position[3 * i + 1] + this.trueOctree.position.y,
  43564. data.data.position[3 * i + 2] + this.trueOctree.position.z,
  43565. );
  43566. let x = data.data.mileage[i];
  43567. let y = 0;
  43568. let z = truePos.z;
  43569. projectedBox.expandByPoint(new Vector3(x, y, z));
  43570. let index = updateRange.start + updateRange.count;
  43571. let geometry = this.currentBatch.geometry;
  43572. for(let attributeName of Object.keys(data.data)){
  43573. let source = data.data[attributeName];
  43574. let target = geometry.attributes[attributeName];
  43575. let numElements = target.itemSize;
  43576. for(let item = 0; item < numElements; item++){
  43577. target.array[numElements * index + item] = source[numElements * i + item];
  43578. }
  43579. }
  43580. {
  43581. let position = geometry.attributes.position;
  43582. position.array[3 * index + 0] = x;
  43583. position.array[3 * index + 1] = y;
  43584. position.array[3 * index + 2] = z;
  43585. }
  43586. updateRange.count++;
  43587. this.currentBatch.geometry.drawRange.count++;
  43588. }
  43589. for(let key of Object.keys(this.currentBatch.geometry.attributes)){
  43590. let attribute = this.currentBatch.geometry.attributes[key];
  43591. attribute.updateRange.offset = updateRange.start;
  43592. attribute.updateRange.count = updateRange.count;
  43593. attribute.needsUpdate = true;
  43594. }
  43595. data.projectedBox = projectedBox;
  43596. this.projectedBox = this.points.reduce( (a, i) => a.union(i.projectedBox), new Box3());
  43597. }
  43598. createNewBatch(data){
  43599. let geometry = new BufferGeometry();
  43600. // create new batches with batch_size elements of the same type as the attribute
  43601. for(let attributeName of Object.keys(data.data)){
  43602. let buffer = data.data[attributeName];
  43603. let numElements = buffer.length / data.numPoints; // 3 for pos, 4 for col, 1 for scalars
  43604. let constructor = buffer.constructor;
  43605. let normalized = false;
  43606. if(this.trueOctree.root.sceneNode){
  43607. if(this.trueOctree.root.sceneNode.geometry.attributes[attributeName]){
  43608. normalized = this.trueOctree.root.sceneNode.geometry.attributes[attributeName].normalized;
  43609. }
  43610. }
  43611. let batchBuffer = new constructor(numElements * this.batchSize);
  43612. let bufferAttribute = new BufferAttribute(batchBuffer, numElements, normalized);
  43613. bufferAttribute.potree = {
  43614. range: [0, 1],
  43615. };
  43616. geometry.setAttribute(attributeName, bufferAttribute);
  43617. }
  43618. geometry.drawRange.start = 0;
  43619. geometry.drawRange.count = 0;
  43620. let batch = new Batch(geometry, this.material);
  43621. this.visibleNodes.push(batch);
  43622. return batch;
  43623. }
  43624. computeVisibilityTextureData(){
  43625. let data = new Uint8Array(this.visibleNodes.length * 4);
  43626. let offsets = new Map();
  43627. for(let i = 0; i < this.visibleNodes.length; i++){
  43628. let node = this.visibleNodes[i];
  43629. offsets[node] = i;
  43630. }
  43631. return {
  43632. data: data,
  43633. offsets: offsets,
  43634. };
  43635. }
  43636. }
  43637. class ProfileWindow extends EventDispatcher$1 {
  43638. constructor (viewer) {
  43639. super();
  43640. this.viewer = viewer;
  43641. this.elRoot = $('#profile_window');
  43642. this.renderArea = this.elRoot.find('#profileCanvasContainer');
  43643. this.svg = d3.select('svg#profileSVG');
  43644. this.mouseIsDown = false;
  43645. this.projectedBox = new Box3();
  43646. this.pointclouds = new Map();
  43647. this.numPoints = 0;
  43648. this.lastAddPointsTimestamp = undefined;
  43649. this.mouse = new Vector2(0, 0);
  43650. this.scale = new Vector3(1, 1, 1);
  43651. this.autoFitEnabled = true; // completely disable/enable
  43652. this.autoFit = false; // internal
  43653. let cwIcon = `${exports.resourcePath}/icons/arrow_cw.svg`;
  43654. $('#potree_profile_rotate_cw').attr('src', cwIcon);
  43655. let ccwIcon = `${exports.resourcePath}/icons/arrow_ccw.svg`;
  43656. $('#potree_profile_rotate_ccw').attr('src', ccwIcon);
  43657. let forwardIcon = `${exports.resourcePath}/icons/arrow_up.svg`;
  43658. $('#potree_profile_move_forward').attr('src', forwardIcon);
  43659. let backwardIcon = `${exports.resourcePath}/icons/arrow_down.svg`;
  43660. $('#potree_profile_move_backward').attr('src', backwardIcon);
  43661. let csvIcon = `${exports.resourcePath}/icons/file_csv_2d.svg`;
  43662. $('#potree_download_csv_icon').attr('src', csvIcon);
  43663. let lasIcon = `${exports.resourcePath}/icons/file_las_3d.svg`;
  43664. $('#potree_download_las_icon').attr('src', lasIcon);
  43665. let closeIcon = `${exports.resourcePath}/icons/close.svg`;
  43666. $('#closeProfileContainer').attr("src", closeIcon);
  43667. this.initTHREE();
  43668. this.initSVG();
  43669. this.initListeners();
  43670. this.pRenderer = new Renderer(this.renderer);
  43671. this.elRoot.i18n();
  43672. }
  43673. initListeners () {
  43674. $(window).resize(() => {
  43675. if (this.enabled) {
  43676. this.render();
  43677. }
  43678. });
  43679. this.renderArea.mousedown(e => {
  43680. this.mouseIsDown = true;
  43681. });
  43682. this.renderArea.mouseup(e => {
  43683. this.mouseIsDown = false;
  43684. });
  43685. let viewerPickSphereSizeHandler = () => {
  43686. let camera = this.viewer.scene.getActiveCamera();
  43687. let domElement = this.viewer.renderer.domElement;
  43688. let distance = this.viewerPickSphere.position.distanceTo(camera.position);
  43689. let pr = Utils.projectedRadius(1, camera, distance, domElement.clientWidth, domElement.clientHeight);
  43690. let scale = (10 / pr);
  43691. this.viewerPickSphere.scale.set(scale, scale, scale);
  43692. };
  43693. this.renderArea.mousemove(e => {
  43694. if (this.pointclouds.size === 0) {
  43695. return;
  43696. }
  43697. let rect = this.renderArea[0].getBoundingClientRect();
  43698. let x = e.clientX - rect.left;
  43699. let y = e.clientY - rect.top;
  43700. let newMouse = new Vector2(x, y);
  43701. if (this.mouseIsDown) {
  43702. // DRAG
  43703. this.autoFit = false;
  43704. this.lastDrag = new Date().getTime();
  43705. let cPos = [this.scaleX.invert(this.mouse.x), this.scaleY.invert(this.mouse.y)];
  43706. let ncPos = [this.scaleX.invert(newMouse.x), this.scaleY.invert(newMouse.y)];
  43707. this.camera.position.x -= ncPos[0] - cPos[0];
  43708. this.camera.position.z -= ncPos[1] - cPos[1];
  43709. this.render();
  43710. } else if (this.pointclouds.size > 0) {
  43711. // FIND HOVERED POINT
  43712. let radius = Math.abs(this.scaleX.invert(0) - this.scaleX.invert(40));
  43713. let mileage = this.scaleX.invert(newMouse.x);
  43714. let elevation = this.scaleY.invert(newMouse.y);
  43715. let closest = this.selectPoint(mileage, elevation, radius);
  43716. if (closest) {
  43717. let point = closest.point;
  43718. let position = new Float64Array([
  43719. point.position[0] + closest.pointcloud.position.x,
  43720. point.position[1] + closest.pointcloud.position.y,
  43721. point.position[2] + closest.pointcloud.position.z
  43722. ]);
  43723. this.elRoot.find('#profileSelectionProperties').fadeIn(200);
  43724. this.pickSphere.visible = true;
  43725. this.pickSphere.scale.set(0.5 * radius, 0.5 * radius, 0.5 * radius);
  43726. this.pickSphere.position.set(point.mileage, 0, position[2]);
  43727. this.viewerPickSphere.position.set(...position);
  43728. if(!this.viewer.scene.scene.children.includes(this.viewerPickSphere)){
  43729. this.viewer.scene.scene.add(this.viewerPickSphere);
  43730. if(!this.viewer.hasEventListener("update", viewerPickSphereSizeHandler)){
  43731. this.viewer.addEventListener("update", viewerPickSphereSizeHandler);
  43732. }
  43733. }
  43734. let info = this.elRoot.find('#profileSelectionProperties');
  43735. let html = '<table>';
  43736. for (let attributeName of Object.keys(point)) {
  43737. let value = point[attributeName];
  43738. let attribute = closest.pointcloud.getAttribute(attributeName);
  43739. let transform = value => value;
  43740. if(attribute && attribute.type.size > 4){
  43741. let range = attribute.initialRange;
  43742. let scale = 1 / (range[1] - range[0]);
  43743. let offset = range[0];
  43744. transform = value => value / scale + offset;
  43745. }
  43746. if (attributeName === 'position') {
  43747. let values = [...position].map(v => Utils.addCommas(v.toFixed(3)));
  43748. html += `
  43749. <tr>
  43750. <td>x</td>
  43751. <td>${values[0]}</td>
  43752. </tr>
  43753. <tr>
  43754. <td>y</td>
  43755. <td>${values[1]}</td>
  43756. </tr>
  43757. <tr>
  43758. <td>z</td>
  43759. <td>${values[2]}</td>
  43760. </tr>`;
  43761. } else if (attributeName === 'rgba') {
  43762. html += `
  43763. <tr>
  43764. <td>${attributeName}</td>
  43765. <td>${value.join(', ')}</td>
  43766. </tr>`;
  43767. } else if (attributeName === 'normal') {
  43768. continue;
  43769. } else if (attributeName === 'mileage') {
  43770. html += `
  43771. <tr>
  43772. <td>${attributeName}</td>
  43773. <td>${value.toFixed(3)}</td>
  43774. </tr>`;
  43775. } else {
  43776. html += `
  43777. <tr>
  43778. <td>${attributeName}</td>
  43779. <td>${transform(value)}</td>
  43780. </tr>`;
  43781. }
  43782. }
  43783. html += '</table>';
  43784. info.html(html);
  43785. this.selectedPoint = point;
  43786. } else {
  43787. // this.pickSphere.visible = false;
  43788. // this.selectedPoint = null;
  43789. this.viewer.scene.scene.add(this.viewerPickSphere);
  43790. let index = this.viewer.scene.scene.children.indexOf(this.viewerPickSphere);
  43791. if(index >= 0){
  43792. this.viewer.scene.scene.children.splice(index, 1);
  43793. }
  43794. this.viewer.removeEventListener("update", viewerPickSphereSizeHandler);
  43795. }
  43796. this.render();
  43797. }
  43798. this.mouse.copy(newMouse);
  43799. });
  43800. let onWheel = e => {
  43801. this.autoFit = false;
  43802. let delta = 0;
  43803. if (e.wheelDelta !== undefined) { // WebKit / Opera / Explorer 9
  43804. delta = e.wheelDelta;
  43805. } else if (e.detail !== undefined) { // Firefox
  43806. delta = -e.detail;
  43807. }
  43808. let ndelta = Math.sign(delta);
  43809. let cPos = [this.scaleX.invert(this.mouse.x), this.scaleY.invert(this.mouse.y)];
  43810. if (ndelta > 0) {
  43811. // + 10%
  43812. this.scale.multiplyScalar(1.1);
  43813. } else {
  43814. // - 10%
  43815. this.scale.multiplyScalar(100 / 110);
  43816. }
  43817. this.updateScales();
  43818. let ncPos = [this.scaleX.invert(this.mouse.x), this.scaleY.invert(this.mouse.y)];
  43819. this.camera.position.x -= ncPos[0] - cPos[0];
  43820. this.camera.position.z -= ncPos[1] - cPos[1];
  43821. this.render();
  43822. this.updateScales();
  43823. };
  43824. $(this.renderArea)[0].addEventListener('mousewheel', onWheel, false);
  43825. $(this.renderArea)[0].addEventListener('DOMMouseScroll', onWheel, false); // Firefox
  43826. $('#closeProfileContainer').click(() => {
  43827. this.hide();
  43828. });
  43829. let getProfilePoints = () => {
  43830. let points = new Points$1();
  43831. for(let [pointcloud, entry] of this.pointclouds){
  43832. for(let pointSet of entry.points){
  43833. let originPos = pointSet.data.position;
  43834. let trueElevationPosition = new Float32Array(originPos);
  43835. for(let i = 0; i < pointSet.numPoints; i++){
  43836. trueElevationPosition[3 * i + 2] += pointcloud.position.z;
  43837. }
  43838. pointSet.data.position = trueElevationPosition;
  43839. points.add(pointSet);
  43840. pointSet.data.position = originPos;
  43841. }
  43842. }
  43843. return points;
  43844. };
  43845. $('#potree_download_csv_icon').click(() => {
  43846. let points = getProfilePoints();
  43847. let string = CSVExporter.toString(points);
  43848. let blob = new Blob([string], {type: "text/string"});
  43849. $('#potree_download_profile_ortho_link').attr('href', URL.createObjectURL(blob));
  43850. });
  43851. $('#potree_download_las_icon').click(() => {
  43852. let points = getProfilePoints();
  43853. let buffer = LASExporter.toLAS(points);
  43854. let blob = new Blob([buffer], {type: "application/octet-binary"});
  43855. $('#potree_download_profile_link').attr('href', URL.createObjectURL(blob));
  43856. });
  43857. }
  43858. selectPoint (mileage, elevation, radius) {
  43859. let closest = {
  43860. distance: Infinity,
  43861. pointcloud: null,
  43862. points: null,
  43863. index: null
  43864. };
  43865. let pointBox = new Box2(
  43866. new Vector2(mileage - radius, elevation - radius),
  43867. new Vector2(mileage + radius, elevation + radius));
  43868. let numTested = 0;
  43869. let numSkipped = 0;
  43870. let numTestedPoints = 0;
  43871. let numSkippedPoints = 0;
  43872. for (let [pointcloud, entry] of this.pointclouds) {
  43873. for(let points of entry.points){
  43874. let collisionBox = new Box2(
  43875. new Vector2(points.projectedBox.min.x, points.projectedBox.min.z),
  43876. new Vector2(points.projectedBox.max.x, points.projectedBox.max.z)
  43877. );
  43878. let intersects = collisionBox.intersectsBox(pointBox);
  43879. if(!intersects){
  43880. numSkipped++;
  43881. numSkippedPoints += points.numPoints;
  43882. continue;
  43883. }
  43884. numTested++;
  43885. numTestedPoints += points.numPoints;
  43886. for (let i = 0; i < points.numPoints; i++) {
  43887. let m = points.data.mileage[i] - mileage;
  43888. let e = points.data.position[3 * i + 2] - elevation + pointcloud.position.z;
  43889. let r = Math.sqrt(m * m + e * e);
  43890. const withinDistance = r < radius && r < closest.distance;
  43891. let unfilteredClass = true;
  43892. if(points.data.classification){
  43893. const classification = pointcloud.material.classification;
  43894. const pointClassID = points.data.classification[i];
  43895. const pointClassValue = classification[pointClassID];
  43896. if(pointClassValue && (!pointClassValue.visible || pointClassValue.color.w === 0)){
  43897. unfilteredClass = false;
  43898. }
  43899. }
  43900. if (withinDistance && unfilteredClass) {
  43901. closest = {
  43902. distance: r,
  43903. pointcloud: pointcloud,
  43904. points: points,
  43905. index: i
  43906. };
  43907. }
  43908. }
  43909. }
  43910. }
  43911. //console.log(`nodes: ${numTested}, ${numSkipped} || points: ${numTestedPoints}, ${numSkippedPoints}`);
  43912. if (closest.distance < Infinity) {
  43913. let points = closest.points;
  43914. let point = {};
  43915. let attributes = Object.keys(points.data);
  43916. for (let attribute of attributes) {
  43917. let attributeData = points.data[attribute];
  43918. let itemSize = attributeData.length / points.numPoints;
  43919. let value = attributeData.subarray(itemSize * closest.index, itemSize * closest.index + itemSize);
  43920. if (value.length === 1) {
  43921. point[attribute] = value[0];
  43922. } else {
  43923. point[attribute] = value;
  43924. }
  43925. }
  43926. closest.point = point;
  43927. return closest;
  43928. } else {
  43929. return null;
  43930. }
  43931. }
  43932. initTHREE () {
  43933. this.renderer = new WebGLRenderer({alpha: true, premultipliedAlpha: false});
  43934. this.renderer.setClearColor(0x000000, 0);
  43935. this.renderer.setSize(10, 10);
  43936. this.renderer.autoClear = false;
  43937. this.renderArea.append($(this.renderer.domElement));
  43938. this.renderer.domElement.tabIndex = '2222';
  43939. $(this.renderer.domElement).css('width', '100%');
  43940. $(this.renderer.domElement).css('height', '100%');
  43941. {
  43942. let gl = this.renderer.getContext();
  43943. if(gl.createVertexArray == null){
  43944. let extVAO = gl.getExtension('OES_vertex_array_object');
  43945. if(!extVAO){
  43946. throw new Error("OES_vertex_array_object extension not supported");
  43947. }
  43948. gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO);
  43949. gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO);
  43950. }
  43951. }
  43952. this.camera = new OrthographicCamera(-1000, 1000, 1000, -1000, -1000, 1000);
  43953. this.camera.up.set(0, 0, 1);
  43954. this.camera.rotation.order = "ZXY";
  43955. this.camera.rotation.x = Math.PI / 2.0;
  43956. this.scene = new Scene();
  43957. this.profileScene = new Scene();
  43958. let sg = new SphereGeometry(1, 16, 16);
  43959. let sm = new MeshNormalMaterial();
  43960. this.pickSphere = new Mesh(sg, sm);
  43961. this.scene.add(this.pickSphere);
  43962. this.viewerPickSphere = new Mesh(sg, sm);
  43963. }
  43964. initSVG () {
  43965. let width = this.renderArea[0].clientWidth;
  43966. let height = this.renderArea[0].clientHeight;
  43967. let marginLeft = this.renderArea[0].offsetLeft;
  43968. this.svg.selectAll('*').remove();
  43969. this.scaleX = d3.scale.linear()
  43970. .domain([this.camera.left + this.camera.position.x, this.camera.right + this.camera.position.x])
  43971. .range([0, width]);
  43972. this.scaleY = d3.scale.linear()
  43973. .domain([this.camera.bottom + this.camera.position.z, this.camera.top + this.camera.position.z])
  43974. .range([height, 0]);
  43975. this.xAxis = d3.svg.axis()
  43976. .scale(this.scaleX)
  43977. .orient('bottom')
  43978. .innerTickSize(-height)
  43979. .outerTickSize(1)
  43980. .tickPadding(10)
  43981. .ticks(width / 50);
  43982. this.yAxis = d3.svg.axis()
  43983. .scale(this.scaleY)
  43984. .orient('left')
  43985. .innerTickSize(-width)
  43986. .outerTickSize(1)
  43987. .tickPadding(10)
  43988. .ticks(height / 20);
  43989. this.elXAxis = this.svg.append('g')
  43990. .attr('class', 'x axis')
  43991. .attr('transform', `translate(${marginLeft}, ${height})`)
  43992. .call(this.xAxis);
  43993. this.elYAxis = this.svg.append('g')
  43994. .attr('class', 'y axis')
  43995. .attr('transform', `translate(${marginLeft}, 0)`)
  43996. .call(this.yAxis);
  43997. }
  43998. addPoints (pointcloud, points) {
  43999. if(points.numPoints === 0){
  44000. return;
  44001. }
  44002. let entry = this.pointclouds.get(pointcloud);
  44003. if(!entry){
  44004. entry = new ProfileFakeOctree(pointcloud);
  44005. this.pointclouds.set(pointcloud, entry);
  44006. this.profileScene.add(entry);
  44007. let materialChanged = () => {
  44008. this.render();
  44009. };
  44010. materialChanged();
  44011. pointcloud.material.addEventListener('material_property_changed', materialChanged);
  44012. this.addEventListener("on_reset_once", () => {
  44013. pointcloud.material.removeEventListener('material_property_changed', materialChanged);
  44014. });
  44015. }
  44016. entry.addPoints(points);
  44017. this.projectedBox.union(entry.projectedBox);
  44018. if (this.autoFit && this.autoFitEnabled) {
  44019. let width = this.renderArea[0].clientWidth;
  44020. let height = this.renderArea[0].clientHeight;
  44021. let size = this.projectedBox.getSize(new Vector3());
  44022. let sx = width / size.x;
  44023. let sy = height / size.z;
  44024. let scale = Math.min(sx, sy);
  44025. let center = this.projectedBox.getCenter(new Vector3());
  44026. this.scale.set(scale, scale, 1);
  44027. this.camera.position.copy(center);
  44028. //console.log("camera: ", this.camera.position.toArray().join(", "));
  44029. }
  44030. //console.log(entry);
  44031. this.render();
  44032. let numPoints = 0;
  44033. for (let [key, value] of this.pointclouds.entries()) {
  44034. numPoints += value.points.reduce( (a, i) => a + i.numPoints, 0);
  44035. }
  44036. $(`#profile_num_points`).html(Utils.addCommas(numPoints));
  44037. }
  44038. reset () {
  44039. this.lastReset = new Date().getTime();
  44040. this.dispatchEvent({type: "on_reset_once"});
  44041. this.removeEventListeners("on_reset_once");
  44042. this.autoFit = true;
  44043. this.projectedBox = new Box3();
  44044. for(let [key, entry] of this.pointclouds){
  44045. entry.dispose();
  44046. }
  44047. this.pointclouds.clear();
  44048. this.mouseIsDown = false;
  44049. this.mouse.set(0, 0);
  44050. if(this.autoFitEnabled){
  44051. this.scale.set(1, 1, 1);
  44052. }
  44053. this.pickSphere.visible = false;
  44054. this.elRoot.find('#profileSelectionProperties').hide();
  44055. this.render();
  44056. }
  44057. show () {
  44058. this.elRoot.fadeIn();
  44059. this.enabled = true;
  44060. }
  44061. hide () {
  44062. this.elRoot.fadeOut();
  44063. this.enabled = false;
  44064. }
  44065. updateScales () {
  44066. let width = this.renderArea[0].clientWidth;
  44067. let height = this.renderArea[0].clientHeight;
  44068. let left = (-width / 2) / this.scale.x;
  44069. let right = (+width / 2) / this.scale.x;
  44070. let top = (+height / 2) / this.scale.y;
  44071. let bottom = (-height / 2) / this.scale.y;
  44072. this.camera.left = left;
  44073. this.camera.right = right;
  44074. this.camera.top = top;
  44075. this.camera.bottom = bottom;
  44076. this.camera.updateProjectionMatrix();
  44077. this.scaleX.domain([this.camera.left + this.camera.position.x, this.camera.right + this.camera.position.x])
  44078. .range([0, width]);
  44079. this.scaleY.domain([this.camera.bottom + this.camera.position.z, this.camera.top + this.camera.position.z])
  44080. .range([height, 0]);
  44081. let marginLeft = this.renderArea[0].offsetLeft;
  44082. this.xAxis.scale(this.scaleX)
  44083. .orient('bottom')
  44084. .innerTickSize(-height)
  44085. .outerTickSize(1)
  44086. .tickPadding(10)
  44087. .ticks(width / 50);
  44088. this.yAxis.scale(this.scaleY)
  44089. .orient('left')
  44090. .innerTickSize(-width)
  44091. .outerTickSize(1)
  44092. .tickPadding(10)
  44093. .ticks(height / 20);
  44094. this.elXAxis
  44095. .attr('transform', `translate(${marginLeft}, ${height})`)
  44096. .call(this.xAxis);
  44097. this.elYAxis
  44098. .attr('transform', `translate(${marginLeft}, 0)`)
  44099. .call(this.yAxis);
  44100. }
  44101. requestScaleUpdate(){
  44102. let threshold = 100;
  44103. let allowUpdate = ((this.lastReset === undefined) || (this.lastScaleUpdate === undefined))
  44104. || ((new Date().getTime() - this.lastReset) > threshold && (new Date().getTime() - this.lastScaleUpdate) > threshold);
  44105. if(allowUpdate){
  44106. this.updateScales();
  44107. this.lastScaleUpdate = new Date().getTime();
  44108. this.scaleUpdatePending = false;
  44109. }else if(!this.scaleUpdatePending) {
  44110. setTimeout(this.requestScaleUpdate.bind(this), 100);
  44111. this.scaleUpdatePending = true;
  44112. }
  44113. }
  44114. render () {
  44115. let width = this.renderArea[0].clientWidth;
  44116. let height = this.renderArea[0].clientHeight;
  44117. let {renderer, pRenderer, camera, profileScene, scene} = this;
  44118. let {scaleX, pickSphere} = this;
  44119. renderer.setSize(width, height);
  44120. renderer.setClearColor(0x000000, 0);
  44121. renderer.clear(true, true, false);
  44122. for(let pointcloud of this.pointclouds.keys()){
  44123. let source = pointcloud.material;
  44124. let target = this.pointclouds.get(pointcloud).material;
  44125. copyMaterial(source, target);
  44126. target.size = 2;
  44127. }
  44128. pRenderer.render(profileScene, camera, null);
  44129. let radius = Math.abs(scaleX.invert(0) - scaleX.invert(5));
  44130. if (radius === 0) {
  44131. pickSphere.visible = false;
  44132. } else {
  44133. pickSphere.scale.set(radius, radius, radius);
  44134. pickSphere.visible = true;
  44135. }
  44136. renderer.render(scene, camera);
  44137. this.requestScaleUpdate();
  44138. }
  44139. };
  44140. class ProfileWindowController {
  44141. constructor (viewer) {
  44142. this.viewer = viewer;
  44143. this.profileWindow = viewer.profileWindow;
  44144. this.profile = null;
  44145. this.numPoints = 0;
  44146. this.threshold = 60 * 1000;
  44147. this.rotateAmount = 10;
  44148. this.scheduledRecomputeTime = null;
  44149. this.enabled = true;
  44150. this.requests = [];
  44151. this._recompute = () => { this.recompute(); };
  44152. this.viewer.addEventListener("scene_changed", e => {
  44153. e.oldScene.removeEventListener("pointcloud_added", this._recompute);
  44154. e.scene.addEventListener("pointcloud_added", this._recompute);
  44155. });
  44156. this.viewer.scene.addEventListener("pointcloud_added", this._recompute);
  44157. $("#potree_profile_rotate_amount").val(parseInt(this.rotateAmount));
  44158. $("#potree_profile_rotate_amount").on("input", (e) => {
  44159. const str = $("#potree_profile_rotate_amount").val();
  44160. if(!isNaN(str)){
  44161. const value = parseFloat(str);
  44162. this.rotateAmount = value;
  44163. $("#potree_profile_rotate_amount").css("background-color", "");
  44164. }else {
  44165. $("#potree_profile_rotate_amount").css("background-color", "#ff9999");
  44166. }
  44167. });
  44168. const rotate = (radians) => {
  44169. const profile = this.profile;
  44170. const points = profile.points;
  44171. const start = points[0];
  44172. const end = points[points.length - 1];
  44173. const center = start.clone().add(end).multiplyScalar(0.5);
  44174. const mMoveOrigin = new Matrix4().makeTranslation(-center.x, -center.y, -center.z);
  44175. const mRotate = new Matrix4().makeRotationZ(radians);
  44176. const mMoveBack = new Matrix4().makeTranslation(center.x, center.y, center.z);
  44177. //const transform = mMoveOrigin.multiply(mRotate).multiply(mMoveBack);
  44178. const transform = mMoveBack.multiply(mRotate).multiply(mMoveOrigin);
  44179. const rotatedPoints = points.map( point => point.clone().applyMatrix4(transform) );
  44180. this.profileWindow.autoFitEnabled = false;
  44181. for(let i = 0; i < points.length; i++){
  44182. profile.setPosition(i, rotatedPoints[i]);
  44183. }
  44184. };
  44185. $("#potree_profile_rotate_cw").click( () => {
  44186. const radians = MathUtils$1.degToRad(this.rotateAmount);
  44187. rotate(-radians);
  44188. });
  44189. $("#potree_profile_rotate_ccw").click( () => {
  44190. const radians = MathUtils$1.degToRad(this.rotateAmount);
  44191. rotate(radians);
  44192. });
  44193. $("#potree_profile_move_forward").click( () => {
  44194. const profile = this.profile;
  44195. const points = profile.points;
  44196. const start = points[0];
  44197. const end = points[points.length - 1];
  44198. const dir = end.clone().sub(start).normalize();
  44199. const up = new Vector3(0, 0, 1);
  44200. const forward = up.cross(dir);
  44201. const move = forward.clone().multiplyScalar(profile.width / 2);
  44202. this.profileWindow.autoFitEnabled = false;
  44203. for(let i = 0; i < points.length; i++){
  44204. profile.setPosition(i, points[i].clone().add(move));
  44205. }
  44206. });
  44207. $("#potree_profile_move_backward").click( () => {
  44208. const profile = this.profile;
  44209. const points = profile.points;
  44210. const start = points[0];
  44211. const end = points[points.length - 1];
  44212. const dir = end.clone().sub(start).normalize();
  44213. const up = new Vector3(0, 0, 1);
  44214. const forward = up.cross(dir);
  44215. const move = forward.clone().multiplyScalar(-profile.width / 2);
  44216. this.profileWindow.autoFitEnabled = false;
  44217. for(let i = 0; i < points.length; i++){
  44218. profile.setPosition(i, points[i].clone().add(move));
  44219. }
  44220. });
  44221. }
  44222. setProfile (profile) {
  44223. if (this.profile !== null && this.profile !== profile) {
  44224. this.profile.removeEventListener('marker_moved', this._recompute);
  44225. this.profile.removeEventListener('marker_added', this._recompute);
  44226. this.profile.removeEventListener('marker_removed', this._recompute);
  44227. this.profile.removeEventListener('width_changed', this._recompute);
  44228. }
  44229. this.profile = profile;
  44230. {
  44231. this.profile.addEventListener('marker_moved', this._recompute);
  44232. this.profile.addEventListener('marker_added', this._recompute);
  44233. this.profile.addEventListener('marker_removed', this._recompute);
  44234. this.profile.addEventListener('width_changed', this._recompute);
  44235. }
  44236. this.recompute();
  44237. }
  44238. reset () {
  44239. this.profileWindow.reset();
  44240. this.numPoints = 0;
  44241. if (this.profile) {
  44242. for (let request of this.requests) {
  44243. request.cancel();
  44244. }
  44245. }
  44246. }
  44247. progressHandler (pointcloud, progress) {
  44248. for (let segment of progress.segments) {
  44249. this.profileWindow.addPoints(pointcloud, segment.points);
  44250. this.numPoints += segment.points.numPoints;
  44251. }
  44252. }
  44253. cancel () {
  44254. for (let request of this.requests) {
  44255. request.cancel();
  44256. // request.finishLevelThenCancel();
  44257. }
  44258. this.requests = [];
  44259. };
  44260. finishLevelThenCancel(){
  44261. for (let request of this.requests) {
  44262. request.finishLevelThenCancel();
  44263. }
  44264. this.requests = [];
  44265. }
  44266. recompute () {
  44267. if (!this.profile) {
  44268. return;
  44269. }
  44270. if (this.scheduledRecomputeTime !== null && this.scheduledRecomputeTime > new Date().getTime()) {
  44271. return;
  44272. } else {
  44273. this.scheduledRecomputeTime = new Date().getTime() + 100;
  44274. }
  44275. this.scheduledRecomputeTime = null;
  44276. this.reset();
  44277. for (let pointcloud of this.viewer.scene.pointclouds.filter(p => p.visible)) {
  44278. let request = pointcloud.getPointsInProfile(this.profile, null, {
  44279. 'onProgress': (event) => {
  44280. if (!this.enabled) {
  44281. return;
  44282. }
  44283. this.progressHandler(pointcloud, event.points);
  44284. if (this.numPoints > this.threshold) {
  44285. this.finishLevelThenCancel();
  44286. }
  44287. },
  44288. 'onFinish': (event) => {
  44289. if (!this.enabled) {
  44290. }
  44291. },
  44292. 'onCancel': () => {
  44293. if (!this.enabled) {
  44294. }
  44295. }
  44296. });
  44297. this.requests.push(request);
  44298. }
  44299. }
  44300. };
  44301. //import { EventDispatcher } from "../EventDispatcher.js";
  44302. class VolumeTool extends EventDispatcher{
  44303. constructor (viewer) {
  44304. super();
  44305. this.viewer = viewer;
  44306. this.renderer = viewer.renderer;
  44307. this.addEventListener('start_inserting_volume', e => {
  44308. this.viewer.dispatchEvent({
  44309. type: 'cancel_insertions'
  44310. });
  44311. });
  44312. this.scene = new Scene();
  44313. this.scene.name = 'scene_volume';
  44314. this.viewer.inputHandler.registerInteractiveScene(this.scene);
  44315. this.onRemove = e => {
  44316. this.scene.remove(e.volume);
  44317. };
  44318. this.onAdd = e => {
  44319. this.scene.add(e.volume);
  44320. };
  44321. for(let volume of viewer.scene.volumes){
  44322. this.onAdd({volume: volume});
  44323. }
  44324. this.viewer.inputHandler.addEventListener('delete', e => {
  44325. let volumes = e.selection.filter(e => (e instanceof Volume));
  44326. volumes.forEach(e => this.viewer.scene.removeVolume(e));
  44327. });
  44328. viewer.addEventListener("update", this.update.bind(this));
  44329. viewer.addEventListener("render.pass.scene", e => this.render(e));
  44330. viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
  44331. viewer.scene.addEventListener('volume_added', this.onAdd);
  44332. viewer.scene.addEventListener('volume_removed', this.onRemove);
  44333. }
  44334. onSceneChange(e){
  44335. if(e.oldScene){
  44336. e.oldScene.removeEventListeners('volume_added', this.onAdd);
  44337. e.oldScene.removeEventListeners('volume_removed', this.onRemove);
  44338. }
  44339. e.scene.addEventListener('volume_added', this.onAdd);
  44340. e.scene.addEventListener('volume_removed', this.onRemove);
  44341. }
  44342. startInsertion (args = {}) {
  44343. let volume;
  44344. if(args.type){
  44345. volume = new args.type();
  44346. }else {
  44347. volume = new BoxVolume();
  44348. }
  44349. volume.clip = args.clip || false;
  44350. volume.name = args.name || 'Volume';
  44351. this.dispatchEvent({
  44352. type: 'start_inserting_volume',
  44353. volume: volume
  44354. });
  44355. this.viewer.scene.addVolume(volume);
  44356. this.scene.add(volume);
  44357. let cancel = {
  44358. callback: null
  44359. };
  44360. let drag = e => {
  44361. let camera = this.viewer.scene.getActiveCamera();
  44362. let I = Utils.getMousePointCloudIntersection(
  44363. e.drag.end,
  44364. this.viewer.scene.getActiveCamera(),
  44365. this.viewer,
  44366. this.viewer.scene.pointclouds,
  44367. {pickClipped: false});
  44368. if (I) {
  44369. volume.position.copy(I.location);
  44370. let wp = volume.getWorldPosition(new Vector3()).applyMatrix4(camera.matrixWorldInverse);
  44371. // let pp = new THREE.Vector4(wp.x, wp.y, wp.z).applyMatrix4(camera.projectionMatrix);
  44372. let w = Math.abs((wp.z / 5));
  44373. volume.scale.set(w, w, w);
  44374. }
  44375. };
  44376. let drop = e => {
  44377. volume.removeEventListener('drag', drag);
  44378. volume.removeEventListener('drop', drop);
  44379. cancel.callback();
  44380. };
  44381. cancel.callback = e => {
  44382. volume.removeEventListener('drag', drag);
  44383. volume.removeEventListener('drop', drop);
  44384. this.viewer.removeEventListener('cancel_insertions', cancel.callback);
  44385. };
  44386. volume.addEventListener('drag', drag);
  44387. volume.addEventListener('drop', drop);
  44388. this.viewer.addEventListener('cancel_insertions', cancel.callback);
  44389. this.viewer.inputHandler.startDragging(volume);
  44390. return volume;
  44391. }
  44392. update(){
  44393. if (!this.viewer.scene) {
  44394. return;
  44395. }
  44396. let camera = this.viewer.scene.getActiveCamera();
  44397. let renderAreaSize = this.viewer.renderer.getSize(new Vector2());
  44398. let clientWidth = renderAreaSize.width;
  44399. let clientHeight = renderAreaSize.height;
  44400. let volumes = this.viewer.scene.volumes;
  44401. for (let volume of volumes) {
  44402. let label = volume.label;
  44403. {
  44404. let distance = label.position.distanceTo(camera.position);
  44405. let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
  44406. let scale = (70 / pr);
  44407. label.scale.set(scale, scale, scale);
  44408. }
  44409. let calculatedVolume = volume.getVolume();
  44410. calculatedVolume = calculatedVolume / Math.pow(this.viewer.lengthUnit.unitspermeter, 3) * Math.pow(this.viewer.lengthUnitDisplay.unitspermeter, 3); //convert to cubic meters then to the cubic display unit
  44411. let text = Utils.addCommas(calculatedVolume.toFixed(3)) + ' ' + this.viewer.lengthUnitDisplay.code + '\u00B3';
  44412. label.setText(text);
  44413. }
  44414. }
  44415. render(params){
  44416. const renderer = this.viewer.renderer;
  44417. const oldTarget = renderer.getRenderTarget();
  44418. if(params.renderTarget){
  44419. renderer.setRenderTarget(params.renderTarget);
  44420. }
  44421. renderer.render(this.scene, this.viewer.scene.getActiveCamera());
  44422. renderer.setRenderTarget(oldTarget);
  44423. }
  44424. }
  44425. /**
  44426. *
  44427. * code adapted from three.js BoxHelper.js
  44428. * https://github.com/mrdoob/three.js/blob/dev/src/helpers/BoxHelper.js
  44429. *
  44430. * @author mrdoob / http://mrdoob.com/
  44431. * @author Mugen87 / http://github.com/Mugen87
  44432. * @author mschuetz / http://potree.org
  44433. */
  44434. class Box3Helper$1 extends LineSegments {
  44435. constructor (box, color, depthTest = true) {
  44436. if (color === undefined) color = 0xffff00;
  44437. let 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 ]);
  44438. let positions = new Float32Array([
  44439. box.min.x, box.min.y, box.min.z,
  44440. box.max.x, box.min.y, box.min.z,
  44441. box.max.x, box.min.y, box.max.z,
  44442. box.min.x, box.min.y, box.max.z,
  44443. box.min.x, box.max.y, box.min.z,
  44444. box.max.x, box.max.y, box.min.z,
  44445. box.max.x, box.max.y, box.max.z,
  44446. box.min.x, box.max.y, box.max.z
  44447. ]);
  44448. let geometry = new BufferGeometry();
  44449. geometry.setIndex(new BufferAttribute(indices, 1));
  44450. geometry.setAttribute('position', new BufferAttribute(positions, 3));
  44451. let material = new LineBasicMaterial({ color: color , depthTest});
  44452. super(geometry, material);
  44453. }
  44454. }
  44455. const KeyCodes = {
  44456. LEFT: 37,
  44457. UP: 38,
  44458. RIGHT: 39,
  44459. BOTTOM: 40,
  44460. DELETE: 46,
  44461. A: 'A'.charCodeAt(0),
  44462. S: 'S'.charCodeAt(0),
  44463. D: 'D'.charCodeAt(0),
  44464. W: 'W'.charCodeAt(0),
  44465. Q: 'Q'.charCodeAt(0),
  44466. E: 'E'.charCodeAt(0),
  44467. R: 'R'.charCodeAt(0),
  44468. F: 'F'.charCodeAt(0)
  44469. };
  44470. class NormalizationMaterial extends RawShaderMaterial{
  44471. constructor(parameters = {}){
  44472. super();
  44473. let uniforms = {
  44474. uDepthMap: { type: 't', value: null },
  44475. uWeightMap: { type: 't', value: null },
  44476. };
  44477. this.setValues({
  44478. uniforms: uniforms,
  44479. vertexShader: this.getDefines() + Shaders['normalize.vs'],
  44480. fragmentShader: this.getDefines() + Shaders['normalize.fs'],
  44481. });
  44482. }
  44483. getDefines() {
  44484. let defines = '';
  44485. return defines;
  44486. }
  44487. updateShaderSource() {
  44488. let vs = this.getDefines() + Shaders['normalize.vs'];
  44489. let fs = this.getDefines() + Shaders['normalize.fs'];
  44490. this.setValues({
  44491. vertexShader: vs,
  44492. fragmentShader: fs
  44493. });
  44494. this.needsUpdate = true;
  44495. }
  44496. }
  44497. class NormalizationEDLMaterial extends RawShaderMaterial{
  44498. constructor(parameters = {}){
  44499. super();
  44500. let uniforms = {
  44501. screenWidth: { type: 'f', value: 0 },
  44502. screenHeight: { type: 'f', value: 0 },
  44503. edlStrength: { type: 'f', value: 1.0 },
  44504. radius: { type: 'f', value: 1.0 },
  44505. neighbours: { type: '2fv', value: [] },
  44506. uEDLMap: { type: 't', value: null },
  44507. uDepthMap: { type: 't', value: null },
  44508. uWeightMap: { type: 't', value: null },
  44509. };
  44510. this.setValues({
  44511. uniforms: uniforms,
  44512. vertexShader: this.getDefines() + Shaders['normalize.vs'],
  44513. fragmentShader: this.getDefines() + Shaders['normalize_and_edl.fs'],
  44514. });
  44515. this.neighbourCount = 8;
  44516. }
  44517. getDefines() {
  44518. let defines = '';
  44519. defines += '#define NEIGHBOUR_COUNT ' + this.neighbourCount + '\n';
  44520. return defines;
  44521. }
  44522. updateShaderSource() {
  44523. let vs = this.getDefines() + Shaders['normalize.vs'];
  44524. let fs = this.getDefines() + Shaders['normalize_and_edl.fs'];
  44525. this.setValues({
  44526. vertexShader: vs,
  44527. fragmentShader: fs
  44528. });
  44529. this.uniforms.neighbours.value = this.neighbours;
  44530. this.needsUpdate = true;
  44531. }
  44532. get neighbourCount(){
  44533. return this._neighbourCount;
  44534. }
  44535. set neighbourCount(value){
  44536. if (this._neighbourCount !== value) {
  44537. this._neighbourCount = value;
  44538. this.neighbours = new Float32Array(this._neighbourCount * 2);
  44539. for (let c = 0; c < this._neighbourCount; c++) {
  44540. this.neighbours[2 * c + 0] = Math.cos(2 * c * Math.PI / this._neighbourCount);
  44541. this.neighbours[2 * c + 1] = Math.sin(2 * c * Math.PI / this._neighbourCount);
  44542. }
  44543. this.updateShaderSource();
  44544. }
  44545. }
  44546. }
  44547. //在potree.shim中修改。 。official中用不到且有bug
  44548. class HQSplatRenderer{
  44549. constructor(viewer){
  44550. this.viewer = viewer;
  44551. this.depthMaterials = new Map();
  44552. this.attributeMaterials = new Map();
  44553. this.normalizationMaterial = null;
  44554. this.rtDepth = null;
  44555. this.rtAttribute = null;
  44556. this.gl = viewer.renderer.getContext();
  44557. this.initialized = false;
  44558. }
  44559. init(){
  44560. if (this.initialized) {
  44561. return;
  44562. }
  44563. this.normalizationMaterial = new NormalizationMaterial();
  44564. this.normalizationMaterial.depthTest = true;
  44565. this.normalizationMaterial.depthWrite = true;
  44566. this.normalizationMaterial.transparent = true;
  44567. this.normalizationEDLMaterial = new NormalizationEDLMaterial();
  44568. this.normalizationEDLMaterial.depthTest = true;
  44569. this.normalizationEDLMaterial.depthWrite = true;
  44570. this.normalizationEDLMaterial.transparent = true;
  44571. this.rtDepth = new WebGLRenderTarget(1024, 1024, {
  44572. minFilter: NearestFilter,
  44573. magFilter: NearestFilter,
  44574. format: RGBAFormat,
  44575. type: FloatType,
  44576. depthTexture: new DepthTexture(undefined, undefined, UnsignedIntType)
  44577. });
  44578. this.rtAttribute = new WebGLRenderTarget(1024, 1024, {
  44579. minFilter: NearestFilter,
  44580. magFilter: NearestFilter,
  44581. format: RGBAFormat,
  44582. type: FloatType,
  44583. depthTexture: this.rtDepth.depthTexture,
  44584. });
  44585. this.initialized = true;
  44586. };
  44587. resize(width, height){
  44588. this.rtDepth.setSize(width, height);
  44589. this.rtAttribute.setSize(width, height);
  44590. }
  44591. clearTargets(){
  44592. const viewer = this.viewer;
  44593. const {renderer} = viewer;
  44594. const oldTarget = renderer.getRenderTarget();
  44595. renderer.setClearColor(0x000000, 0);
  44596. renderer.setRenderTarget( this.rtDepth );
  44597. renderer.clear( true, true, true );
  44598. renderer.setRenderTarget( this.rtAttribute );
  44599. renderer.clear( true, true, true );
  44600. renderer.setRenderTarget(oldTarget);
  44601. }
  44602. clear(){
  44603. this.init();
  44604. const {renderer, background} = this.viewer;
  44605. if(background === "skybox"){
  44606. renderer.setClearColor(0x000000, 0);
  44607. } else if (background === 'gradient') {
  44608. renderer.setClearColor(0x000000, 0);
  44609. } else if (background === 'black') {
  44610. renderer.setClearColor(0x000000, 1);
  44611. } else if (background === 'white') {
  44612. renderer.setClearColor(0xFFFFFF, 1);
  44613. } else {
  44614. renderer.setClearColor(0x000000, 0);
  44615. }
  44616. renderer.clear();
  44617. this.clearTargets();
  44618. }
  44619. render (params) {
  44620. this.init();
  44621. const viewer = this.viewer;
  44622. const camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  44623. const {width, height} = this.viewer.renderer.getSize(new Vector2());
  44624. viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
  44625. this.resize(width, height);
  44626. const visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible);
  44627. const originalMaterials = new Map();
  44628. for(let pointcloud of visiblePointClouds){
  44629. originalMaterials.set(pointcloud, pointcloud.material);
  44630. if(!this.attributeMaterials.has(pointcloud)){
  44631. let attributeMaterial = new PointCloudMaterial$1();
  44632. this.attributeMaterials.set(pointcloud, attributeMaterial);
  44633. }
  44634. if(!this.depthMaterials.has(pointcloud)){
  44635. let depthMaterial = new PointCloudMaterial$1();
  44636. depthMaterial.setDefine("depth_pass", "#define hq_depth_pass");
  44637. depthMaterial.setDefine("use_edl", "#define use_edl");
  44638. this.depthMaterials.set(pointcloud, depthMaterial);
  44639. }
  44640. }
  44641. { // DEPTH PASS
  44642. for (let pointcloud of visiblePointClouds) {
  44643. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  44644. let material = originalMaterials.get(pointcloud);
  44645. let depthMaterial = this.depthMaterials.get(pointcloud);
  44646. depthMaterial.size = material.size;
  44647. depthMaterial.minSize = material.minSize;
  44648. depthMaterial.maxSize = material.maxSize;
  44649. depthMaterial.pointSizeType = material.pointSizeType;
  44650. depthMaterial.visibleNodesTexture = material.visibleNodesTexture;
  44651. depthMaterial.weighted = false;
  44652. depthMaterial.screenWidth = width;
  44653. depthMaterial.shape = PointShape$1.CIRCLE;
  44654. depthMaterial.screenHeight = height;
  44655. depthMaterial.uniforms.visibleNodes.value = material.visibleNodesTexture;
  44656. depthMaterial.uniforms.octreeSize.value = octreeSize;
  44657. depthMaterial.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(...pointcloud.scale.toArray());
  44658. depthMaterial.classification = material.classification;
  44659. depthMaterial.uniforms.classificationLUT.value.image.data = material.uniforms.classificationLUT.value.image.data;
  44660. depthMaterial.classificationTexture.needsUpdate = true;
  44661. depthMaterial.uniforms.uFilterReturnNumberRange.value = material.uniforms.uFilterReturnNumberRange.value;
  44662. depthMaterial.uniforms.uFilterNumberOfReturnsRange.value = material.uniforms.uFilterNumberOfReturnsRange.value;
  44663. depthMaterial.uniforms.uFilterGPSTimeClipRange.value = material.uniforms.uFilterGPSTimeClipRange.value;
  44664. depthMaterial.uniforms.uFilterPointSourceIDClipRange.value = material.uniforms.uFilterPointSourceIDClipRange.value;
  44665. depthMaterial.clipTask = material.clipTask;
  44666. depthMaterial.clipMethod = material.clipMethod;
  44667. depthMaterial.setClipBoxes(material.clipBoxes);
  44668. depthMaterial.setClipPolygons(material.clipPolygons);
  44669. pointcloud.material = depthMaterial;
  44670. }
  44671. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtDepth, {
  44672. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume$1)),
  44673. });
  44674. }
  44675. { // ATTRIBUTE PASS
  44676. for (let pointcloud of visiblePointClouds) {
  44677. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  44678. let material = originalMaterials.get(pointcloud);
  44679. let attributeMaterial = this.attributeMaterials.get(pointcloud);
  44680. attributeMaterial.size = material.size;
  44681. attributeMaterial.minSize = material.minSize;
  44682. attributeMaterial.maxSize = material.maxSize;
  44683. attributeMaterial.pointSizeType = material.pointSizeType;
  44684. attributeMaterial.activeAttributeName = material.activeAttributeName;
  44685. attributeMaterial.visibleNodesTexture = material.visibleNodesTexture;
  44686. attributeMaterial.weighted = true;
  44687. attributeMaterial.screenWidth = width;
  44688. attributeMaterial.screenHeight = height;
  44689. attributeMaterial.shape = PointShape$1.CIRCLE;
  44690. attributeMaterial.uniforms.visibleNodes.value = material.visibleNodesTexture;
  44691. attributeMaterial.uniforms.octreeSize.value = octreeSize;
  44692. attributeMaterial.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(...pointcloud.scale.toArray());
  44693. attributeMaterial.classification = material.classification;
  44694. attributeMaterial.uniforms.classificationLUT.value.image.data = material.uniforms.classificationLUT.value.image.data;
  44695. attributeMaterial.classificationTexture.needsUpdate = true;
  44696. attributeMaterial.uniforms.uFilterReturnNumberRange.value = material.uniforms.uFilterReturnNumberRange.value;
  44697. attributeMaterial.uniforms.uFilterNumberOfReturnsRange.value = material.uniforms.uFilterNumberOfReturnsRange.value;
  44698. attributeMaterial.uniforms.uFilterGPSTimeClipRange.value = material.uniforms.uFilterGPSTimeClipRange.value;
  44699. attributeMaterial.uniforms.uFilterPointSourceIDClipRange.value = material.uniforms.uFilterPointSourceIDClipRange.value;
  44700. attributeMaterial.elevationGradientRepeat = material.elevationGradientRepeat;
  44701. attributeMaterial.elevationRange = material.elevationRange;
  44702. attributeMaterial.gradient = material.gradient;
  44703. attributeMaterial.matcap = material.matcap;
  44704. attributeMaterial.intensityRange = material.intensityRange;
  44705. attributeMaterial.intensityGamma = material.intensityGamma;
  44706. attributeMaterial.intensityContrast = material.intensityContrast;
  44707. attributeMaterial.intensityBrightness = material.intensityBrightness;
  44708. attributeMaterial.rgbGamma = material.rgbGamma;
  44709. attributeMaterial.rgbContrast = material.rgbContrast;
  44710. attributeMaterial.rgbBrightness = material.rgbBrightness;
  44711. attributeMaterial.weightRGB = material.weightRGB;
  44712. attributeMaterial.weightIntensity = material.weightIntensity;
  44713. attributeMaterial.weightElevation = material.weightElevation;
  44714. attributeMaterial.weightRGB = material.weightRGB;
  44715. attributeMaterial.weightClassification = material.weightClassification;
  44716. attributeMaterial.weightReturnNumber = material.weightReturnNumber;
  44717. attributeMaterial.weightSourceID = material.weightSourceID;
  44718. attributeMaterial.color = material.color;
  44719. attributeMaterial.clipTask = material.clipTask;
  44720. attributeMaterial.clipMethod = material.clipMethod;
  44721. attributeMaterial.setClipBoxes(material.clipBoxes);
  44722. attributeMaterial.setClipPolygons(material.clipPolygons);
  44723. pointcloud.material = attributeMaterial;
  44724. }
  44725. let gl = this.gl;
  44726. viewer.renderer.setRenderTarget(null);
  44727. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtAttribute, {
  44728. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume$1)),
  44729. //material: this.attributeMaterial,
  44730. blendFunc: [gl.SRC_ALPHA, gl.ONE],
  44731. //depthTest: false,
  44732. depthWrite: false
  44733. });
  44734. }
  44735. for(let [pointcloud, material] of originalMaterials){
  44736. pointcloud.material = material;
  44737. }
  44738. viewer.renderer.setRenderTarget(null);
  44739. if(viewer.background === "skybox"){
  44740. viewer.renderer.setClearColor(0x000000, 0);
  44741. viewer.renderer.clear();
  44742. viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
  44743. viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
  44744. viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
  44745. viewer.skybox.parent.rotation.x = 0;
  44746. viewer.skybox.parent.updateMatrixWorld();
  44747. viewer.skybox.camera.updateProjectionMatrix();
  44748. viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
  44749. } else if (viewer.background === 'gradient') {
  44750. viewer.renderer.setClearColor(0x000000, 0);
  44751. viewer.renderer.clear();
  44752. viewer.renderer.render(viewer.scene.sceneBG, viewer.scene.cameraBG);
  44753. } else if (viewer.background === 'black') {
  44754. viewer.renderer.setClearColor(0x000000, 1);
  44755. viewer.renderer.clear();
  44756. } else if (viewer.background === 'white') {
  44757. viewer.renderer.setClearColor(0xFFFFFF, 1);
  44758. viewer.renderer.clear();
  44759. } else {
  44760. viewer.renderer.setClearColor(0x000000, 0);
  44761. viewer.renderer.clear();
  44762. }
  44763. { // NORMALIZATION PASS
  44764. let normalizationMaterial = this.useEDL ? this.normalizationEDLMaterial : this.normalizationMaterial;
  44765. if(this.useEDL){
  44766. normalizationMaterial.uniforms.edlStrength.value = viewer.edlStrength;
  44767. normalizationMaterial.uniforms.radius.value = viewer.edlRadius;
  44768. normalizationMaterial.uniforms.screenWidth.value = width;
  44769. normalizationMaterial.uniforms.screenHeight.value = height;
  44770. normalizationMaterial.uniforms.uEDLMap.value = this.rtDepth.texture;
  44771. }
  44772. normalizationMaterial.uniforms.uWeightMap.value = this.rtAttribute.texture;
  44773. normalizationMaterial.uniforms.uDepthMap.value = this.rtAttribute.depthTexture;
  44774. Utils.screenPass.render(viewer.renderer, normalizationMaterial);
  44775. }
  44776. viewer.renderer.render(viewer.scene.scene, camera);
  44777. viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer});
  44778. viewer.renderer.clearDepth();
  44779. viewer.transformationTool.update();
  44780. viewer.dispatchEvent({type: "render.pass.perspective_overlay",viewer: viewer});
  44781. viewer.renderer.render(viewer.controls.sceneControls, camera);
  44782. viewer.renderer.render(viewer.clippingTool.sceneVolume, camera);
  44783. viewer.renderer.render(viewer.transformationTool.scene, camera);
  44784. viewer.renderer.setViewport(width - viewer.navigationCube.width,
  44785. height - viewer.navigationCube.width,
  44786. viewer.navigationCube.width, viewer.navigationCube.width);
  44787. viewer.renderer.render(viewer.navigationCube, viewer.navigationCube.camera);
  44788. viewer.renderer.setViewport(0, 0, width, height);
  44789. viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
  44790. }
  44791. }
  44792. class LRUItem{
  44793. constructor(node){
  44794. this.previous = null;
  44795. this.next = null;
  44796. this.node = node;
  44797. }
  44798. }
  44799. /**
  44800. *
  44801. * @class A doubly-linked-list of the least recently used elements.
  44802. */
  44803. class LRU{
  44804. constructor(){ //类似链表存储
  44805. // the least recently used item
  44806. this.first = null;
  44807. // the most recently used item
  44808. this.last = null;
  44809. // a list of all items in the lru list
  44810. this.items = {}; //按node的id存储。(id为0的就是root,name='r')
  44811. this.elements = 0;
  44812. this.numPoints = 0;
  44813. }
  44814. size(){
  44815. return this.elements;
  44816. }
  44817. contains(node){
  44818. return this.items[node.id] == null;
  44819. }
  44820. touch(node){//链接node,并且永远放在最后. (每次updatePointClouds都要刷新一次链表)
  44821. if (!node.loaded) {
  44822. return;
  44823. }
  44824. let item;
  44825. if (this.items[node.id] == null) {
  44826. // add to list
  44827. item = new LRUItem(node);
  44828. item.previous = this.last;
  44829. this.last = item;
  44830. if (item.previous !== null) {
  44831. item.previous.next = item;
  44832. }
  44833. this.items[node.id] = item;
  44834. this.elements++;
  44835. if (this.first === null) {
  44836. this.first = item;
  44837. }
  44838. this.numPoints += node.numPoints;
  44839. } else {
  44840. // update in list
  44841. item = this.items[node.id];
  44842. if (item.previous === null) {
  44843. // handle touch on first element
  44844. if (item.next !== null) {
  44845. this.first = item.next;
  44846. this.first.previous = null;
  44847. item.previous = this.last;
  44848. item.next = null;
  44849. this.last = item;
  44850. item.previous.next = item;
  44851. }
  44852. } else if (item.next === null) {
  44853. // handle touch on last element
  44854. } else {//从原来的位置挑出放最后
  44855. // handle touch on any other element
  44856. item.previous.next = item.next;
  44857. item.next.previous = item.previous;
  44858. item.previous = this.last;
  44859. item.next = null;
  44860. this.last = item;
  44861. item.previous.next = item;
  44862. }
  44863. }
  44864. }
  44865. //因为需要显示的都放末尾,所以不显示的部分都在前面,删除时从头删除。(但并不代表开头的一定是不显示的,所以如果第一个仍是显示的,它很可能是root,也就是name='r'的nodeGeo,删除它也就会删除全部)
  44866. remove(node){
  44867. let lruItem = this.items[node.id];
  44868. if (lruItem) {
  44869. if (this.elements === 1) {
  44870. this.first = null;
  44871. this.last = null;
  44872. } else {
  44873. if (!lruItem.previous) {
  44874. this.first = lruItem.next;
  44875. this.first.previous = null;
  44876. }
  44877. if (!lruItem.next) {
  44878. this.last = lruItem.previous;
  44879. this.last.next = null;
  44880. }
  44881. if (lruItem.previous && lruItem.next) {
  44882. lruItem.previous.next = lruItem.next;
  44883. lruItem.next.previous = lruItem.previous;
  44884. }
  44885. }
  44886. delete this.items[node.id];
  44887. this.elements--;
  44888. this.numPoints -= node.numPoints;
  44889. }
  44890. }
  44891. getLRUItem(){
  44892. if (this.first === null) {
  44893. return null;
  44894. }
  44895. let lru = this.first;
  44896. return lru.node;
  44897. }
  44898. toString(){
  44899. let string = '{ ';
  44900. let curr = this.first;
  44901. while (curr !== null) {
  44902. string += curr.node.id;
  44903. if (curr.next !== null) {
  44904. string += ', ';
  44905. }
  44906. curr = curr.next;
  44907. }
  44908. string += '}';
  44909. string += '(' + this.size() + ')';
  44910. return string;
  44911. }
  44912. freeMemory(){
  44913. if (this.elements <= 1) {
  44914. return;
  44915. }
  44916. while (this.numPoints > Potree.pointLoadLimit) {
  44917. let element = this.first;
  44918. let node = element.node;
  44919. this.disposeDescendants(node);
  44920. }
  44921. }
  44922. disposeDescendants(node){
  44923. let stack = [];
  44924. stack.push(node);
  44925. while (stack.length > 0) {
  44926. let current = stack.pop();
  44927. // console.log(current);
  44928. current.dispose(); //真正删除geometry等
  44929. this.remove(current);
  44930. for (let key in current.children) {
  44931. if (current.children.hasOwnProperty(key)) {
  44932. let child = current.children[key];
  44933. if (child.loaded) {
  44934. stack.push(current.children[key]);
  44935. }
  44936. }
  44937. }
  44938. }
  44939. }
  44940. }
  44941. //
  44942. // how to calculate the radius of a projected sphere in screen space
  44943. // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
  44944. // http://stackoverflow.com/questions/3717226/radius-of-projected-sphere
  44945. //
  44946. class ExtendPointCloudMaterial extends PointCloudMaterial$1 {
  44947. constructor (parameters = {}) {
  44948. super(parameters);
  44949. let getValid = (a, b) => {
  44950. if(a !== undefined){
  44951. return a;
  44952. }else {
  44953. return b;
  44954. }
  44955. };
  44956. let maxSize = getValid(parameters.maxSize, 1550.0);
  44957. this._gradient = Gradients.RAINBOW;//Gradients.SPECTRAL;//海拔贴图种类
  44958. this.gradientTexture = ExtendPointCloudMaterial.generateGradientTexture(this._gradient);
  44959. //this.matcapTexture = ExtendPointCloudMaterial.generateMatcapTexture(this._matcap);
  44960. delete this.uniforms.screenWidth;
  44961. delete this.uniforms.screenHeight;
  44962. delete this.uniforms.clipBoxes;
  44963. delete this.uniforms.clipPolygons;
  44964. delete this.uniforms.clipPolygonVCount;
  44965. delete this.uniforms.clipPolygonVP;
  44966. delete this.uniforms.clipBoxCount;
  44967. //注意:这里修改了uniforms后,还需要在PotreeRender中手动传递到shader, like: gl.uniformMatrix4fv(....
  44968. Object.assign(this.uniforms,{
  44969. resolution: { type: 'v2', value: new Vector2() },
  44970. maxSize: { type: "f", value: maxSize },
  44971. gradient: { type: "t", value: this.gradientTexture },
  44972. clipBoxes_in: { type: "Matrix4fv", value: [] },
  44973. clipBoxes_out: { type: "Matrix4fv", value: [] },
  44974. clipBoxBig_in: { type: "Matrix4fv", value: [] },
  44975. boxes_highlight: { type: "Matrix4fv", value: [] },
  44976. progress: {
  44977. type: "f",
  44978. value: 0
  44979. },
  44980. easeInOutRatio:{
  44981. type: "f",
  44982. value: 0.3
  44983. },
  44984. pano0Map: {
  44985. type: "t",
  44986. value: null
  44987. },
  44988. pano0Position: {
  44989. type: "v3",
  44990. value: new Vector3
  44991. },
  44992. pano0Matrix: {
  44993. type: "m4",
  44994. value: new Matrix4
  44995. },
  44996. pano1Map: {
  44997. type: "t",
  44998. value: null
  44999. },
  45000. pano1Position: {
  45001. type: "v3",
  45002. value: new Vector3
  45003. },
  45004. pano1Matrix: {
  45005. type: "m4",
  45006. value: new Matrix4
  45007. },
  45008. });
  45009. delete this.clipBoxes;
  45010. this.clipBoxes_in = [];
  45011. this.clipBoxes_out = [];
  45012. this.highlightBoxes = [];
  45013. this.updateShaderSource();
  45014. }
  45015. updateShaderSource () {
  45016. let vs = Shaders['pointcloud_new.vs']; //改
  45017. let fs = Shaders['pointcloud_new.fs']; //改
  45018. let definesString = this.getDefines();
  45019. let vsVersionIndex = vs.indexOf("#version ");
  45020. let fsVersionIndex = fs.indexOf("#version ");
  45021. if(vsVersionIndex >= 0){
  45022. vs = vs.replace(/(#version .*)/, `$1\n${definesString}`);
  45023. }else {
  45024. vs = `${definesString}\n${vs}`;
  45025. }
  45026. if(fsVersionIndex >= 0){
  45027. fs = fs.replace(/(#version .*)/, `$1\n${definesString}`);
  45028. }else {
  45029. fs = `${definesString}\n${fs}`;
  45030. }
  45031. this.vertexShader = vs;
  45032. this.fragmentShader = fs;
  45033. if (this.opacity === 1.0 && !this.useFilterByNormal) {//add useFilterByNormal
  45034. this.blending = NoBlending;
  45035. this.transparent = false;
  45036. this.depthTest = true;
  45037. this.depthWrite = true;
  45038. this.depthFunc = LessEqualDepth;
  45039. } else if ( (this.opacity < 1.0 ||this.useFilterByNormal) && !this.useEDL) {//add useFilterByNormal
  45040. this.blending = AdditiveBlending;
  45041. this.transparent = true;
  45042. this.depthTest = false;
  45043. this.depthWrite = true;
  45044. this.depthFunc = AlwaysDepth;
  45045. }
  45046. if (this.weighted) {
  45047. this.blending = AdditiveBlending;
  45048. this.transparent = true;
  45049. this.depthTest = true;
  45050. this.depthWrite = false;
  45051. }
  45052. this.shaderNeedsUpdate = true;
  45053. }
  45054. getDefines () {
  45055. let defines = [];
  45056. if (this.pointSizeType === PointSizeType.FIXED) {
  45057. defines.push('#define fixed_point_size');
  45058. } else if (this.pointSizeType === PointSizeType.ATTENUATED) {
  45059. defines.push('#define attenuated_point_size');
  45060. } else if (this.pointSizeType === PointSizeType.ADAPTIVE) {
  45061. defines.push('#define adaptive_point_size');
  45062. }
  45063. if(!Features.EXT_DEPTH.isSupported() && this.shape === PointShape$1.PARABOLOID){
  45064. this.shape = PointShape$1.SQUARE ;//强行替换
  45065. }
  45066. if (this.shape === PointShape$1.SQUARE) {
  45067. defines.push('#define square_point_shape');
  45068. } else if (this.shape === PointShape$1.CIRCLE) {
  45069. defines.push('#define circle_point_shape');
  45070. } else if (this.shape === PointShape$1.PARABOLOID) {
  45071. defines.push('#define paraboloid_point_shape');
  45072. }
  45073. //console.log('this.shape PARABOLOID', this.shape, this.shape === PointShape.PARABOLOID)
  45074. if (this._useEDL || this.fakeEDL) {
  45075. defines.push('#define use_edl');
  45076. }
  45077. if(this.activeAttributeName){
  45078. let attributeName = this.activeAttributeName.replace(/[^a-zA-Z0-9]/g, '_');
  45079. defines.push(`#define color_type_${attributeName}`);
  45080. }
  45081. if(this._treeType === TreeType.OCTREE){
  45082. defines.push('#define tree_type_octree');
  45083. }else if(this._treeType === TreeType.KDTREE){
  45084. defines.push('#define tree_type_kdtree');
  45085. }
  45086. if (this.weighted) {
  45087. defines.push('#define weighted_splats');
  45088. }
  45089. for(let [key, value] of this.defines){
  45090. defines.push(value);
  45091. }
  45092. return defines.join("\n");
  45093. }
  45094. get pointSizeType () {
  45095. return this._pointSizeType;
  45096. }
  45097. set pointSizeType (value) {
  45098. if(typeof value == 'string' )value = PointSizeType[value];
  45099. super.pointSizeType = value;
  45100. /* if (this._pointSizeType !== value) {
  45101. this._pointSizeType = value;
  45102. this.updateShaderSource(); //这句表明这个属性频繁更改会卡顿
  45103. this.dispatchEvent({
  45104. type: 'point_size_type_changed',
  45105. target: this
  45106. });
  45107. this.dispatchEvent({
  45108. type: 'material_property_changed',
  45109. target: this
  45110. });
  45111. } */
  45112. }
  45113. get color () {
  45114. return this.uniforms.uColor.value;
  45115. }
  45116. set color (value) {//改
  45117. if(value == this.color_)return
  45118. let color = value;
  45119. //if (!this.uniforms.uColor.value.equals(value)) {
  45120. if(typeof value == 'string') {
  45121. var colorArr = Potree.config.colors[value];
  45122. if(!colorArr){
  45123. //console.warn('没找到该颜色值'+ value)
  45124. }else {
  45125. color = new Color().fromArray(colorArr).multiplyScalar(1/255);
  45126. }
  45127. }
  45128. this.uniforms.uColor.value.set(color);
  45129. //this.uniforms.uColor.value.copy(value);
  45130. this.dispatchEvent({
  45131. type: 'color_changed',
  45132. target: this
  45133. });
  45134. this.dispatchEvent({
  45135. type: 'material_property_changed',
  45136. target: this
  45137. });
  45138. //}
  45139. this.color_ = value; //记录下str
  45140. }
  45141. ////////////////////////add
  45142. setProjectedPanos(pano0, pano1, progressValue, easeInOutRatio){
  45143. //this.uniforms.usePanoMap.value = 1
  45144. this.usePanoMap = true;
  45145. progressValue!=void 0 && (this.uniforms.progress.value = progressValue);
  45146. //pano0.ensureSkyboxReadyForRender();
  45147. this.uniforms.pano0Map.value = pano0.getSkyboxTexture();
  45148. this.uniforms.pano0Position.value.copy(pano0.position);
  45149. this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix );
  45150. //pano1.ensureSkyboxReadyForRender();
  45151. this.uniforms.easeInOutRatio.value = easeInOutRatio || 0; //之前做点云和全景混合时加的,为了让点云颜色柔和切换到全景颜色。如不混合就0
  45152. this.uniforms.pano1Map.value = pano1.getSkyboxTexture();
  45153. this.uniforms.pano1Position.value.copy(pano1.position);
  45154. this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix );
  45155. //this.updateShaderSource()
  45156. //this.needsUpdate = true;
  45157. }
  45158. stopProjectedPanos(){
  45159. //this.uniforms.usePanoMap.value = 0
  45160. this.usePanoMap = false;
  45161. }
  45162. setClipBoxes (bigClipInBox, clipBoxes_in,clipBoxes_out, highlightBoxes) {
  45163. if (!clipBoxes_in || !clipBoxes_out) {
  45164. return;
  45165. }
  45166. let doUpdate = (this.clipBoxes_in.length !== clipBoxes_in.length) || (this.clipBoxes_out.length != clipBoxes_out.length)
  45167. || this.highlightBoxes.length !== highlightBoxes.length || this.bigClipInBox != bigClipInBox;
  45168. //this.clipBoxes = clipBoxes;
  45169. if (doUpdate) {
  45170. this.shaderNeedsUpdate = true;//this.updateShaderSource();
  45171. viewer.dispatchEvent('content_changed');
  45172. }
  45173. this.bigClipInBox = bigClipInBox;
  45174. this.clipBoxes_in = clipBoxes_in;
  45175. this.clipBoxes_out = clipBoxes_out;
  45176. this.highlightBoxes = highlightBoxes;
  45177. this.uniforms.clipBoxBig_in.value = bigClipInBox && bigClipInBox.inverse;
  45178. this.uniforms.clipBoxes_in.value = new Float32Array(this.clipBoxes_in.length * 16);
  45179. this.uniforms.clipBoxes_out.value = new Float32Array(this.clipBoxes_out.length * 16);
  45180. this.uniforms.boxes_highlight.value = new Float32Array(this.highlightBoxes.length * 16);
  45181. for (let i = 0; i < this.clipBoxes_in.length; i++) {
  45182. let box = clipBoxes_in[i];
  45183. this.uniforms.clipBoxes_in.value.set(box.inverse.elements, 16 * i);
  45184. }
  45185. for (let i = 0; i < this.clipBoxes_out.length; i++) {
  45186. let box = clipBoxes_out[i];
  45187. this.uniforms.clipBoxes_out.value.set(box.inverse.elements, 16 * i);
  45188. }
  45189. for (let i = 0; i < this.highlightBoxes.length; i++) {
  45190. let box = highlightBoxes[i];
  45191. this.uniforms.boxes_highlight.value.set(box.inverse.elements, 16 * i);
  45192. }
  45193. /* for (let i = 0; i < this.uniforms.clipBoxes.value.length; i++) {??
  45194. if (Number.isNaN(this.uniforms.clipBoxes.value[i])) {
  45195. this.uniforms.clipBoxes.value[i] = Infinity;
  45196. }
  45197. } */
  45198. }
  45199. }
  45200. var defaultColor = new Color(1,1,1);//config.applicationName == "zhiHouse" ? Colors.zhiBlue : Colors.lightGreen;
  45201. function dealPosArr(points){//识别是否每个点都不一样,把连续点变为不连续的片段连接
  45202. if(points.length > 2 && !points[2].equals(points[1])){
  45203. let points2 = [] , len = points.length;
  45204. for(let i=0;i<len-1;i++){
  45205. points2.push(points[i], points[i+1]);
  45206. }
  45207. return points2
  45208. }else return points
  45209. }
  45210. var LineDraw = {
  45211. createLine: function (posArr, o={}) {
  45212. //多段普通线 (第二个点和第三个点之间是没有线段的, 所以不用在意线段顺序)
  45213. var mat;
  45214. if(o.mat){
  45215. mat = o.mat;
  45216. }else {
  45217. let prop = Object.assign({
  45218. lineWidth: o.lineWidth || 1,
  45219. //windows无效。 似乎mac/ios上粗细有效 ?
  45220. color: o.color || defaultColor,
  45221. //depthTest : false,
  45222. },o);
  45223. if(o.deshed ){
  45224. prop.dashSize = o.dashSize || 0.1,
  45225. prop.gapSize = o.gapSize || 0.1;
  45226. }
  45227. mat = new THREE$1[o.deshed ? "LineDashedMaterial" : "LineBasicMaterial"](prop);
  45228. }
  45229. var line = new LineSegments(new BufferGeometry, mat);
  45230. line.renderOrder = o.renderOrder || 4;
  45231. this.moveLine(line, posArr);
  45232. return line;
  45233. },
  45234. moveLine: function (line, posArr) {
  45235. if(posArr.length == 0)return
  45236. posArr = dealPosArr(posArr);
  45237. let position = [];
  45238. posArr.forEach(e=>position.push(e.x,e.y,e.z));
  45239. line.geometry.setAttribute('position', new Float32BufferAttribute(/* new Float32Array( */position/* ) */, 3));
  45240. line.geometry.attributes.position.needsUpdate = true;
  45241. line.geometry.computeBoundingSphere();
  45242. if(line.material instanceof LineDashedMaterial){
  45243. line.computeLineDistances();
  45244. //line.geometry.attributes.lineDistance.needsUpdate = true;
  45245. line.geometry.verticesNeedUpdate = true; //没用
  45246. }
  45247. }
  45248. ,
  45249. createFatLineMat : function(o){
  45250. var supportExtDepth = !!Features.EXT_DEPTH.isSupported();
  45251. let params = $.extend({}, {
  45252. //默认
  45253. lineWidth : 5,
  45254. color:0xffffff,
  45255. transparent : true, depthWrite:false, depthTest:false,
  45256. dashSize : 0.1, gapSize:0.1,
  45257. }, o, {
  45258. //修正覆盖:
  45259. dashed: o.dashWithDepth ? supportExtDepth && !!o.dashed : !!o.dashed ,
  45260. dashWithDepth:!!o.dashWithDepth,//只在被遮住的部分显示虚线
  45261. useDepth: !!o.useDepth,
  45262. supportExtDepth,
  45263. });
  45264. var mat = new LineMaterial(params);
  45265. //if(o.dashed)(mat.defines.USE_DASH = "")
  45266. return mat;
  45267. },
  45268. /*
  45269. 创建可以改变粗细的线。
  45270. */
  45271. createFatLine : function(posArr, o){
  45272. var geometry = new LineGeometry();
  45273. geometry.setColors( o.color || [1,1,1]);
  45274. var matLine = o.material || this.createFatLineMat(o);
  45275. var line = new Line2( geometry, matLine );
  45276. //line.computeLineDistances();
  45277. line.scale.set( 1, 1, 1 );
  45278. line.renderOrder = 2;
  45279. this.moveFatLine(line, posArr);
  45280. return line;
  45281. },
  45282. moveFatLine: function(line, posArr){
  45283. var geometry = line.geometry;
  45284. var positions = [];
  45285. posArr = dealPosArr(posArr);
  45286. posArr.forEach(e=>{positions.push(...e.toArray());});
  45287. if(!geometry){
  45288. geometry = line.geometry = new LineGeometry();
  45289. }
  45290. if(geometry.attributes.instanceEnd && geometry.attributes.instanceEnd.data.array.length != positions.length){//positions个数改变会有部分显示不出来,所以重建
  45291. geometry.dispose();
  45292. geometry = new LineGeometry();
  45293. line.geometry = geometry;
  45294. }
  45295. geometry.setPositions( positions );
  45296. if(line.material.defines.USE_DASH != void 0){
  45297. //line.geometry.verticesNeedUpdate = true; //没用
  45298. line.geometry.computeBoundingSphere(); //for raycaster
  45299. line.computeLineDistances();
  45300. }
  45301. },
  45302. updateLine: function(line, posArr){
  45303. if(line instanceof Line2){
  45304. LineDraw.moveFatLine(line,posArr);
  45305. }else {
  45306. LineDraw.moveLine(line,posArr);
  45307. }
  45308. },
  45309. /*
  45310. 为line创建用于检测鼠标的透明mesh,实际是个1-2段圆台。
  45311. 由于近大远小的原因,假设没有透视畸变、创建的是等粗的圆柱的话, 所看到的线上每个位置的粗细应该和距离成反比。所以将圆柱改为根据距离线性渐变其截面半径的圆台,在最近点(相机到线的垂足)最细。如果最近点在线段上,则分成两段圆台,否则一段。
  45312. */
  45313. createBoldLine:function(points, o){
  45314. o = o || {};
  45315. var cylinder = o && o.cylinder;
  45316. var CD = points[1].clone().sub(points[0]);
  45317. var rotate = function(){//根据端点旋转好模型
  45318. cylinder.lastVector = CD;//记录本次的端点向量
  45319. var AB = new Vector3(0,-1,0);
  45320. var axisVec = AB.clone().cross(CD).normalize(); //得到垂直于它们的向量,也就是旋转轴
  45321. var rotationAngle = AB.angleTo(CD);
  45322. cylinder.quaternion.setFromAxisAngle( axisVec, rotationAngle );
  45323. };
  45324. if(o && o.type == "init"){
  45325. cylinder = new Mesh();
  45326. cylinder.material = o.mat;
  45327. if(CD.length() == 0)return cylinder;
  45328. rotate();
  45329. }
  45330. if(CD.length() == 0)return cylinder;
  45331. if(o.type != "update"){
  45332. var CDcenter = points[0].clone().add(points[1]).multiplyScalar(.5);
  45333. cylinder.position.copy(CDcenter);
  45334. if(!cylinder.lastVector || o.type == "moveAndRotate")rotate();
  45335. else if(cylinder.lastVector && CD.angleTo(cylinder.lastVector)>0) rotate();//线方向改了or线反向了 重新旋转一下模型
  45336. if(config.isEdit && !objects.mainDesign.editing )return cylinder;//节省初始加载时间?
  45337. }
  45338. //为了保证线段任何地方的可检测点击范围看起来一样大,更新圆台的结构(但是在镜头边缘会比中心看起来大)
  45339. var height = points[0].distanceTo(points[1]);
  45340. var standPos = o && o.standPos || objects.player.position;
  45341. var k = config.isMobile ? 20 : 40;
  45342. var dis1 = points[0].distanceTo(standPos);
  45343. var dis2 = points[1].distanceTo(standPos);
  45344. var foot = math.getFootPoint(standPos, points[0], points[1]);//垂足
  45345. if(o.constantBold || objects.player.mode != "panorama"){
  45346. var width = 0.1;//0.08;
  45347. var pts = [new Vector2(width ,height/2),new Vector2(width ,-height/2)];
  45348. }else if(foot.clone().sub(points[0]).dot( foot.clone().sub(points[1]) ) > 0){//foot不在线段上
  45349. var pts = [new Vector2(dis1 / k,height/2),new Vector2(dis2 / k,-height/2)];
  45350. }else {//在线段上的话,要在垂足这加一个节点,因它距离站位最近,而两端较远
  45351. var dis3 = foot.distanceTo(standPos);
  45352. var len = foot.distanceTo(points[0]);
  45353. var pts = [new Vector2(dis1 / k,height/2), new Vector2(dis3 / k,height/2-len), new Vector2(dis2 / k,-height/2)];
  45354. }
  45355. cylinder.geometry && cylinder.geometry.dispose();//若不删除会占用内存
  45356. cylinder.geometry = new LatheBufferGeometry( pts, 4/* Math.min(dis1,dis2)<10?4:3 */ );
  45357. cylinder.renderOrder = 2;
  45358. return cylinder;
  45359. },
  45360. updateBoldLine:function(cylinder, points, type, standPos, constantBold){
  45361. this.createBoldLine(points,{type:type, cylinder : cylinder, standPos:standPos, constantBold}); //type:move:平移 会改长短 , type:update根据距离和角度更新 不改长短
  45362. },
  45363. };
  45364. var MeshDraw = {
  45365. getShape:function(points, holes){
  45366. var shape = new Shape();
  45367. shape.moveTo( points[0].x, points[0].y );
  45368. for(var i=1,len=points.length; i<len; i++){
  45369. shape.lineTo(points[i].x, points[i].y );
  45370. }
  45371. /* var holePath = new THREE.Path()
  45372. .moveTo( 20, 10 )
  45373. .absarc( 10, 10, 10, 0, Math.PI * 2, true )
  45374. arcShape.holes.push( holePath );
  45375. */
  45376. if(holes){//挖空
  45377. holes.forEach((points)=>{
  45378. var holePath = new Path();
  45379. holePath.moveTo( points[0].x, points[0].y );
  45380. for(var i=1,len=points.length; i<len; i++){
  45381. holePath.lineTo(points[i].x, points[i].y );
  45382. }
  45383. shape.holes.push( holePath );
  45384. });
  45385. }
  45386. return shape
  45387. },
  45388. getShapeGeo: function(points, holes){//获取任意形状(多边形或弧形)的形状面 //quadraticCurveTo() 这是弧形的含函数
  45389. var geometry = new ShapeBufferGeometry( this.getShape(points, holes) ); //ShapeGeometry
  45390. /* var matrix = new THREE.Matrix4();//将竖直的面变为水平
  45391. matrix.set(//z = y
  45392. 1, 0, 0, 0,
  45393. 0, 0, 0, 0,
  45394. 0, 1, 0, 0,
  45395. 0, 0, 0, 1
  45396. )
  45397. geometry.applyMatrix(matrix) */
  45398. //geometry.computeVertexNormals();//对于光照需要的是点法线
  45399. return geometry;
  45400. },
  45401. getExtrudeGeo: function(points, holes, options={}){//获得挤出棱柱,可以选择传递height,或者extrudePath
  45402. var shape = this.getShape(points, holes); //points是横截面 [vector2,...]
  45403. if(options.extrudePath ){// 路径 :[vector3,...]
  45404. var length = extrudePath.reduce((total, currentValue, currentIndex, arr)=>{
  45405. if(currentIndex == 0)return 0
  45406. return total + currentValue.distanceTo(arr[currentIndex-1]);
  45407. },0);
  45408. options.extrudePath = new CatmullRomCurve3(extrudePath, options.closed , 'catmullrom' /* 'centripetal' */ , options.tension);
  45409. }
  45410. var extrudeSettings = $.extend(options,{
  45411. steps: options.steps != void 0 ? options.steps : ( options.extrudePath ? Math.round(length/0.3) : 1),
  45412. bevelEnabled: false, //不加的话,height为0时会有圆弧高度
  45413. //depth
  45414. });
  45415. var geometry = new ExtrudeBufferGeometry( shape, extrudeSettings );
  45416. return geometry;
  45417. },
  45418. getUnPosPlaneGeo : function(){//获取还没有赋值位置的plane geometry
  45419. var e = new Uint16Array([0, 1, 2, 0, 2, 3])
  45420. // , t = new Float32Array([-.5, -.5, 0, .5, -.5, 0, .5, .5, 0, -.5, .5, 0])
  45421. , i = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1])
  45422. , g = new BufferGeometry;
  45423. g.setIndex(new BufferAttribute(e, 1)),
  45424. //g.addAttribute("position", new n.BufferAttribute(t, 3)),
  45425. g.setAttribute("uv", new BufferAttribute(i, 2));
  45426. return function(){
  45427. return g
  45428. }
  45429. }(),
  45430. getPlaneGeo : function(A,B,C,D){
  45431. var geo = this.getUnPosPlaneGeo().clone();
  45432. var pos = [
  45433. A.x, A.y, A.z,
  45434. B.x, B.y, B.z,
  45435. C.x, C.y, C.z,
  45436. D.x, D.y, D.z
  45437. ];
  45438. //geo.addAttribute("position", new THREE.BufferAttribute(pos, 3))
  45439. geo.setAttribute('position', new Float32BufferAttribute(pos, 3));
  45440. geo.computeVertexNormals();
  45441. geo.computeBoundingSphere(); //for raycaster
  45442. return geo;
  45443. },
  45444. drawPlane : function(A,B,C,D, material){
  45445. var wall = new Mesh(this.getPlaneGeo(A,B,C,D), material);
  45446. return wall;
  45447. },
  45448. movePlane: function(mesh, A,B,C,D){
  45449. var pos = new Float32Array([
  45450. A.x, A.y, A.z,
  45451. B.x, B.y, B.z,
  45452. C.x, C.y, C.z,
  45453. D.x, D.y, D.z
  45454. ]);
  45455. mesh.geometry.addAttribute("position", new BufferAttribute(pos, 3));
  45456. mesh.geometry.computeBoundingSphere();//for checkIntersect
  45457. }
  45458. ,
  45459. createGeometry:function(posArr, faceArr, uvArr, normalArr ){//创建复杂mesh. faceArr:[[0,1,2],[0,2,3]]
  45460. let geo = new BufferGeometry;
  45461. let positions = [];
  45462. posArr.forEach(p=>positions.push(p.x,p.y,p.z));
  45463. geo.setAttribute('position', new Float32BufferAttribute(positions, 3));
  45464. if(faceArr){
  45465. let indice = [];
  45466. faceArr.forEach(f=>indice.push(...f));
  45467. geo.setIndex(indice); // auto set Uint16BufferAttribute or Uint32BufferAttribute
  45468. }
  45469. if(uvArr){
  45470. let uvs = [];
  45471. uvArr.forEach(uv=>uvs.push(uv.x,uv.y));
  45472. geo.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
  45473. }
  45474. if(normalArr){
  45475. let normals = [];
  45476. normalArr.forEach(n=>normals.push(n.x,n.y,n.z));
  45477. geo.setAttribute("normal", new Float32BufferAttribute(normals, 3));
  45478. }
  45479. /*
  45480. geo.computeVertexNormals()
  45481. geo.computeBoundingSphere() //for raycaster
  45482. */
  45483. return geo
  45484. },
  45485. updateGeometry:function(geo, posArr, faceArr, uvArr, normalArr ){//创建复杂mesh. faceArr:[[0,1,2],[0,2,3]]
  45486. let positions = [];
  45487. posArr.forEach(p=>positions.push(p.x,p.y,p.z));
  45488. geo.setAttribute('position', new Float32BufferAttribute(positions, 3));
  45489. geo.attributes.position.needsUpdate = true;
  45490. if(faceArr){
  45491. let indice = [];
  45492. faceArr.forEach(f=>indice.push(...f));
  45493. geo.setIndex(indice); // auto set Uint16BufferAttribute or Uint32BufferAttribute
  45494. }
  45495. if(uvArr){
  45496. let uvs = [];
  45497. uvArr.forEach(uv=>uvs.push(uv.x,uv.y));
  45498. geo.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
  45499. }
  45500. if(normalArr){
  45501. let normals = [];
  45502. normalArr.forEach(n=>normals.push(n.x,n.y,n.z));
  45503. geo.setAttribute("normal", new Float32BufferAttribute(normals, 3));
  45504. }
  45505. /*
  45506. geo.computeVertexNormals()
  45507. */
  45508. geo.computeBoundingSphere(); //for raycaster and visi
  45509. return geo
  45510. }
  45511. };
  45512. class DepthBasicMaterial extends ShaderMaterial{
  45513. constructor(o={}){
  45514. let {width, height} = viewer.renderer.getSize(new Vector2());
  45515. let uniforms = {
  45516. resolution: { type: 'v2', value: new Vector2(width, height ) },
  45517. viewportOffset: { type: 'v2', value: new Vector2(0, 0 ) }, //left, top
  45518. uUseOrthographicCamera:{ type: "b", value: false },
  45519. nearPlane: { type: 'f', value: 0.1 },
  45520. farPlane: { type: 'f', value: 10000 },
  45521. depthTexture: { type: 't', value: null },
  45522. opacity: { type: 'f', value: 1 },
  45523. map: { type: 't', value: o.map },
  45524. baseColor: {type:'v3', value: o.color ? new Color(o.color) : new Color("#ffffff")},
  45525. backColor: {type:'v3', value: o.backColor ? new Color(o.backColor) : new Color("#ddd")},
  45526. clipDistance : { type: 'f', value: o.clipDistance || 4 }, //消失距离
  45527. occlusionDistance : { type: 'f', value: o.occlusionDistance || 1 }, //变为backColor距离
  45528. maxClipFactor : { type: 'f', value: o.maxClipFactor || 1 }, //0-1
  45529. maxOcclusionFactor : { type: 'f', value: o.maxOcclusionFactor || 1 }, //0-1
  45530. //-------add:-----
  45531. replaceColor : {type:'v3', value: o.replaceColor ? new Color(o.replaceColor) : null},
  45532. beReplacedRed : {type:'f', value: o.beReplacedRed},
  45533. };
  45534. super({
  45535. uniforms,
  45536. vertexShader: Shaders['depthBasic.vs'],
  45537. fragmentShader: Shaders['depthBasic.fs'],
  45538. depthWrite: false,
  45539. depthTest: false,
  45540. transparent: o.transparent == void 0 ? true : o.transparent,
  45541. side: o.side || 0 /* THREE.DoubleSide */,
  45542. });
  45543. this.events = {
  45544. setSize:(e)=>{//如果出现横条状的异常,往往是viewportOffset出错 //地图不需要
  45545. if(!this.useDepth /* || !e.viewport.camera.isPerspectiveCamera */|| !e.viewport)return
  45546. let viewport = e.viewport;
  45547. let viewportOffset = viewport.offset || new Vector2();
  45548. this.uniforms.resolution.value.copy(viewport.resolution2); //2023.6.12突然发现ratio>1的用resolution不对,得用2才对。但是之前明明记得不是这样
  45549. this.uniforms.viewportOffset.value.copy(viewportOffset);
  45550. },
  45551. render:(e)=>{//before render 如果有大于两个viewport的话,不同viewport用不同的depthTex
  45552. this.updateDepthParams(e);
  45553. },
  45554. cameraChange:(e)=>{
  45555. if(e.changeInfo.projectionChanged){//resize时也会触发。虽然保守起见的话加上resize比较好//所以当时为何不用resize
  45556. //console.log('projectionChanged')
  45557. this.events.setSize(e);
  45558. }
  45559. }
  45560. };
  45561. if(o.mapColorReplace){
  45562. this.defines.mapColorReplace = '';
  45563. }
  45564. //-----其他----
  45565. this.autoDepthTest = o.autoDepthTest;
  45566. if(o.opacity != void 0){
  45567. this.opacity = o.opacity;
  45568. }
  45569. this.useDepth = o.useDepth;
  45570. this.map = o.map;
  45571. }
  45572. get useDepth(){
  45573. return this.useDepth_
  45574. }
  45575. set useDepth(value){
  45576. value = value && Features.EXT_DEPTH.isSupported(); //如果不支持 EXT_DEPTH 的话会失效
  45577. if(this.useDepth_ != value){
  45578. this.setRealDepth(value);
  45579. this.useDepth_ = value;
  45580. if(value){
  45581. viewer.addEventListener("render.begin", this.events.render);
  45582. viewer.addEventListener('camera_changed', this.events.cameraChange);
  45583. this.events.setSize( {viewport:viewer.mainViewport} );
  45584. this.updateDepthParams();
  45585. }else {
  45586. viewer.removeEventListener("render.begin", this.events.render);
  45587. viewer.removeEventListener('camera_changed', this.events.cameraChange);
  45588. }
  45589. }
  45590. }
  45591. setRealDepth(useDepth){//确实使用到depthTex
  45592. if(this.realUseDepth != useDepth){
  45593. if(useDepth ){
  45594. this.defines.useDepth = '';
  45595. }else {
  45596. delete this.defines.useDepth;
  45597. }
  45598. this.realUseDepth = useDepth;
  45599. if(this.autoDepthTest)this.depthWrite = this.depthTest = !useDepth; //如果useDepth = false,使用原始的depthTest
  45600. this.needsUpdate = true;
  45601. }
  45602. }
  45603. get map(){
  45604. return this.uniforms.map.value
  45605. }
  45606. set map(map){
  45607. this.uniforms.map.value = map;
  45608. if(map){
  45609. this.defines.use_map = '';
  45610. }else {
  45611. delete this.defines.use_map;
  45612. }
  45613. }
  45614. get opacity(){
  45615. return this.uniforms.opacity.value
  45616. }
  45617. set opacity(o){
  45618. this.uniforms && (this.uniforms.opacity.value = o);
  45619. }
  45620. get color(){
  45621. return this.uniforms.baseColor.value
  45622. }
  45623. set color(c){
  45624. this.uniforms && (this.uniforms.baseColor.value.set(c));
  45625. }
  45626. /* dispose(){
  45627. super.dispose()
  45628. viewer.depthBasic
  45629. } */
  45630. copy(source){
  45631. super.copy(source);
  45632. this.useDepth = source.useDepth;
  45633. this.map = source.map;
  45634. return this
  45635. }
  45636. updateDepthParams(e={}){//主要用于点云遮住mesh
  45637. var viewport = e.viewport || viewer.mainViewport;
  45638. var camera = viewport.camera;
  45639. let hasDepth = this.useDepth /* && camera.isPerspectiveCamera */ &&
  45640. (Potree.settings.pointEnableRT || Potree.settings.displayMode == 'showPanos' || viewer.useEDL);
  45641. this.setRealDepth(hasDepth);
  45642. if(hasDepth){
  45643. this.uniforms.depthTexture.value = viewer.getPRenderer().getRtEDL(viewport).depthTexture; //其实只赋值一次就行
  45644. this.uniforms.nearPlane.value = camera.near;
  45645. this.uniforms.farPlane.value = camera.far;
  45646. }
  45647. this.uniforms.uUseOrthographicCamera.value = !camera.isPerspectiveCamera;
  45648. }
  45649. }
  45650. const geo = new PlaneBufferGeometry(1,1);
  45651. class Sprite$2 extends Mesh{
  45652. constructor(options={}){
  45653. super(geo, options.mat || new DepthBasicMaterial(options));/* ({map:options.map, useDepth:options.useDepth})) */
  45654. this.root = options.root || this;
  45655. this.renderOrder = options.renderOrder != void 0 ? options.renderOrder : 4;
  45656. this.pickOrder = options.pickOrder || 0;
  45657. this.sizeInfo = options.sizeInfo;
  45658. this.dontFixOrient = options.dontFixOrient;
  45659. this.options = options;
  45660. this.lineDir = options.lineDir;
  45661. this.root.matrixAutoUpdate = false;
  45662. this.matrixMap = new Map();
  45663. this.name = options.name || 'sprite';
  45664. this.useViewport = null;
  45665. this.viewports = options.viewports;//指定更新的viewports
  45666. this.visible_ = true;
  45667. let update = (e)=>{
  45668. //this.update(e)
  45669. this.needsUpdate = true;
  45670. };
  45671. viewer.mapViewer && viewer.mapViewer.addEventListener("camera_changed", update);
  45672. viewer.addEventListener("camera_changed", update);
  45673. /* if(viewer.viewports.length == 1){//直接更新。如果有多个不在这更新,在"render.begin"
  45674. this.update(e)
  45675. } */
  45676. let applyMatrix = (e)=>{
  45677. if(this.needsUpdate) this.update(e);
  45678. else this.applyMatrix(e);
  45679. };
  45680. viewer.addEventListener("raycaster", applyMatrix); //before render
  45681. viewer.addEventListener("render.begin", applyMatrix); //before render //magnifier时要禁止吗
  45682. this.addEventListener('dispose', ()=>{
  45683. viewer.mapViewer && viewer.mapViewer.removeEventListener("camera_changed", update);
  45684. viewer.removeEventListener("camera_changed", update);
  45685. viewer.removeEventListener("raycaster", applyMatrix); //before render
  45686. viewer.removeEventListener("render.begin", applyMatrix);
  45687. this.dispose();
  45688. });
  45689. }
  45690. set visible(v){
  45691. this.visible_ = v;
  45692. if(v){
  45693. this.update();
  45694. }
  45695. }
  45696. get visible(){
  45697. return this.visible_
  45698. }
  45699. realVisible(){
  45700. if(!this.visible && this.unvisibleReasons && this.unvisibleReasons.some(e=>e.reason != 'unableCompute')){
  45701. return false
  45702. }
  45703. let v = true;
  45704. let parent = this.parent;
  45705. let lastParent = this;
  45706. while(parent){
  45707. if(parent.visible === false ){
  45708. v = false;
  45709. break;
  45710. }
  45711. lastParent = parent;
  45712. parent = parent.parent;
  45713. }
  45714. if(v && !(lastParent instanceof Scene)){//已被删除
  45715. v = false;
  45716. }
  45717. /* if(!this.latestRealVisi && v){//变为可见后先update
  45718. this.latestRealVisi = true
  45719. setTimeout(()=>{
  45720. this.update() -----删掉是因为更新时返回false导致无法立即更新
  45721. },1)//延迟 防止无限调用
  45722. return false
  45723. }
  45724. this.latestRealVisi = v*/
  45725. return v;
  45726. }
  45727. update(e={}){
  45728. if(!e.viewport){
  45729. let viewports = this.viewports || viewer.viewports;
  45730. if(!viewports)return
  45731. viewports.forEach(view=>{
  45732. this.update({viewport:view});
  45733. });
  45734. return;
  45735. }
  45736. if(!this.root || ! this.realVisible() /* this.visible */ )return
  45737. if(this.viewports && !this.viewports.includes(e.viewport) )return
  45738. if(e.viewport.name == 'magnifier')return
  45739. let camera = e.viewport.camera;
  45740. //rotation
  45741. if(!this.dontFixOrient){ //orthoCamera一般要加dontFixOrient
  45742. let orient2d;
  45743. if(this.lineDir){
  45744. this.root.updateMatrix();//先更新,getWorldPosition才能得到正确的
  45745. this.root.updateMatrixWorld(true);
  45746. let center = this.root.getWorldPosition(new Vector3());
  45747. //由于两个端点容易在屏幕外,所以使用center和center加dir
  45748. let lineDir = this.lineDir.clone();
  45749. let r1 = Potree.Utils.getPos2d(center, camera, viewer.renderArea, e.viewport);
  45750. if(!r1.trueSide)return Potree.Utils.updateVisible(this, 'unableCompute', false);// 但这句会使realVisible为false从而无法更新//console.error('!r1.trueSide') //中心点如果在背面直接不渲染了
  45751. let r2, point2;
  45752. let p2State = '', len=1, p2StateHistory = [];
  45753. while(p2State != 'got' && p2StateHistory.length<10){
  45754. point2 = center.clone().add(lineDir.multiplyScalar(len));
  45755. r2 = Potree.Utils.getPos2d(point2, camera, viewer.renderArea, e.viewport);
  45756. if(!r2.trueSide){ //很少遇到点2在背面的
  45757. if(!p2StateHistory.includes('tooLong-reverse')){
  45758. p2State = 'tooLong-reverse'; //先尝试反向
  45759. len = -len;
  45760. }else {
  45761. p2State = 'tooLong';
  45762. len = len / 2;
  45763. }
  45764. }else {
  45765. let dis = r2.pos.distanceTo(r1.pos);
  45766. if(math.closeTo(dis,0)){
  45767. //console.log('dis == 0')
  45768. Potree.Utils.updateVisible(this, 'unableCompute', false);
  45769. return
  45770. break
  45771. }
  45772. if(dis<10 && !p2StateHistory.includes('tooLong')){//和r1的屏幕距离太近,要加长,否则精度过低
  45773. p2State = 'tooShort';
  45774. len = 100/dis * len;
  45775. }else {
  45776. p2State = 'got'; break;
  45777. }
  45778. }
  45779. p2StateHistory.push(p2State);
  45780. }
  45781. //console.log(p2StateHistory,len)
  45782. if(!r2.trueSide){
  45783. return Potree.Utils.updateVisible(this, 'unableCompute', false)//, console.log(' !r2.trueSide', )
  45784. }
  45785. Potree.Utils.updateVisible(this, 'unableCompute', true);
  45786. let p1 = r1.pos, p2 = r2.pos;
  45787. let vec = new Vector2().subVectors(p1,p2);
  45788. let angle = -vec.angle(); //根据测量线在屏幕上的角度在旋转label,使之和屏幕上的二维线平行。
  45789. if(p1.x < p2.x) angle += Math.PI; //避免字是倒着的情况
  45790. orient2d = new Quaternion().setFromAxisAngle(new Vector3(0,0,1), angle);
  45791. //console.log(this.parent.text, THREE.Math.radToDeg(angle), p1.x < p2.x )
  45792. }
  45793. let parentQua = this.root.parent.getWorldQuaternion(new Quaternion);
  45794. this.root.quaternion.multiplyQuaternions(parentQua.invert(),camera.quaternion); //乘上parentQua.invert()是为了中和掉父结点的qua,使只剩下camera.quaternion
  45795. if(this.lineDir){
  45796. this.root.quaternion.multiply(orient2d);
  45797. }
  45798. }
  45799. //scale
  45800. var info = this.sizeInfo;
  45801. if(info){
  45802. this.root.updateMatrix();//先更新,getWorldPosition才能得到正确的
  45803. this.root.updateMatrixWorld(true);
  45804. var scale;
  45805. if(info.nearBound == void 0 && info.farBound != void 0 || info.nearBound != void 0 && info.farBound == void 0){//仅限制最大或最小的话,不判断像素大小,直接限制mesh的scale
  45806. //这个判断也可以写到getScaleForConstantSize里,可以更严谨控制像素宽度,这里只简单计算大小
  45807. var dis = camera.position.distanceTo(this.root.getWorldPosition(new Vector3()));
  45808. if(info.farBound == void 0 && dis < info.nearBound){
  45809. scale = info.scale * dis / info.nearBound;
  45810. }else if(info.nearBound == void 0 && dis > info.farBound){
  45811. scale = info.scale * dis / info.farBound;
  45812. }else {
  45813. scale = info.scale;
  45814. }
  45815. }else {
  45816. scale = math.getScaleForConstantSize($.extend(info,{//规定下最小最大像素
  45817. camera , position:this.root.getWorldPosition(new Vector3()) ,
  45818. resolution: e.viewport.resolution//2
  45819. }));
  45820. }
  45821. if(!isNaN(scale)){
  45822. this.root.scale.set(scale, scale, scale);
  45823. }
  45824. }
  45825. this.root.updateMatrix();
  45826. this.root.updateMatrixWorld(true);
  45827. this.matrixMap.set(e.viewport, this.root.matrix.clone());
  45828. this.useViewport = e.viewport;
  45829. }
  45830. applyMatrix(e){
  45831. if(!e)e = {viewport:viewer.mainViewport};//随便写一个viewport
  45832. if(e.viewport.name == 'magnifier')return
  45833. /* if(this.name == 'measure_point'){
  45834. console.log(1)
  45835. } */
  45836. if(this.viewports && !this.viewports.includes(e.viewport) )return
  45837. if( !this.root || !this.realVisible() )return
  45838. var matrix = this.matrixMap.get(e.viewport);
  45839. if(!matrix){
  45840. this.update(e);
  45841. matrix = this.matrixMap.get(e.viewport);
  45842. if(!matrix)return
  45843. }
  45844. if(e.viewport == this.useViewport){
  45845. return
  45846. }
  45847. this.useViewport = e.viewport;
  45848. this.root.matrix.copy(matrix);
  45849. this.root.updateMatrixWorld(true);
  45850. //console.log(this.root.name + e.viewport.name + " : "+this.root.matrixWorld.elements)
  45851. }
  45852. setUniforms(name,value){
  45853. this.material.setUniforms(name,value);
  45854. }
  45855. dispose(){
  45856. this.removeAllListeners();
  45857. this.parent && this.parent.remove(this);
  45858. }
  45859. }
  45860. //可能还是要用html写,因为要加按钮和图片
  45861. class TextSprite$2 extends Object3D{
  45862. //注:为了分两层控制scale,不直接extend Sprite
  45863. constructor( options={}){
  45864. super();
  45865. let map = new Texture();
  45866. this.sprite = new Sprite$2( Object.assign({
  45867. root:this
  45868. }
  45869. ,options,
  45870. {
  45871. map,
  45872. })
  45873. );
  45874. this.add(this.sprite);
  45875. this.fontWeight = options.fontWeight == void 0 ? 'Bold' : options.fontWeight;
  45876. this.rectBorderThick = options.rectBorderThick || 0;
  45877. this.textBorderThick = options.textBorderThick || 0;
  45878. this.fontface = 'Arial';
  45879. this.fontsize = options.fontsize || 16;
  45880. this.textBorderColor = options.textBorderColor || { r: 0, g: 0, b: 0, a: 0.0 };
  45881. this.backgroundColor = options.backgroundColor || { r: 255, g: 255, b: 255, a: 1.0 };
  45882. this.textColor = options.textColor || {r: 0, g: 0, b: 0, a: 1.0};
  45883. this.borderColor = options.borderColor || { r: 0, g: 0, b: 0, a: 0.0 };
  45884. this.borderRadius = options.borderRadius || 6;
  45885. this.margin = options.margin;
  45886. if(options.text != void 0)this.setText(options.text);
  45887. this.name = options.name;
  45888. //this.setText(text);
  45889. this.addEventListener('dispose', this.dispose.bind(this));
  45890. }
  45891. setText(text){
  45892. if (this.text !== text){
  45893. this.text = text + '';
  45894. this.updateTexture();
  45895. }
  45896. }
  45897. setTextColor(color){
  45898. this.textColor = color;
  45899. this.updateTexture();
  45900. }
  45901. setBorderColor(color){
  45902. this.borderColor = color;
  45903. this.updateTexture();
  45904. }
  45905. setBackgroundColor(color){
  45906. this.backgroundColor = color;
  45907. this.updateTexture();
  45908. }
  45909. setPos(pos){
  45910. this.position.copy(pos);
  45911. this.sprite.update();
  45912. }
  45913. update(){
  45914. this.sprite.update();
  45915. }
  45916. setVisible(v){
  45917. Potree.Utils.updateVisible(this, 'setVisible', v);
  45918. }
  45919. setUniforms(name,value){
  45920. this.sprite.setUniforms(name,value);
  45921. }
  45922. updateTexture(){
  45923. let canvas = document.createElement('canvas');
  45924. let context = canvas.getContext('2d');
  45925. context.font = this.fontWeight + ' ' + this.fontsize + 'px ' + this.fontface;
  45926. //context["font-weight"] = 100; //语法与 CSS font 属性相同。
  45927. // get size data (height depends only on font size)
  45928. //this.text = 'f 啊啊啊 jg'
  45929. let metrics = context.measureText(this.text );
  45930. let textWidth = metrics.width;
  45931. let margin = this.margin || new Vector2(this.fontsize, Math.max( this.fontsize*0.4, 10) );
  45932. let spriteWidth = 2 * margin.x + textWidth + 2 * this.rectBorderThick;
  45933. let spriteHeight = 2 * margin.y + this.fontsize + 2 * this.rectBorderThick;
  45934. context.canvas.width = spriteWidth;
  45935. context.canvas.height = spriteHeight;
  45936. context.font = this.fontWeight + ' ' + this.fontsize + 'px ' + this.fontface;
  45937. let expand = Math.max(1, Math.pow(this.fontsize / 16, 1.3)); // 针对英文大部分在baseLine之上所以降低一点,或者可以识别当不包含jgqp时才加这个值
  45938. //canvas原点在左上角
  45939. context.textBaseline = 'alphabetic'; // "middle" //设置文字基线。当起点y设置为0时,只有该线以下的部分被绘制出来。middle时文字显示一半(但是对该字体所有字的一半,有的字是不一定显示一半的,尤其汉字),alphabetic时是英文字母的那条基线。
  45940. let actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent; // 当前文本字符串在这个字体下用的实际高度
  45941. //文字y向距离从textBaseline向上算
  45942. let y = metrics.actualBoundingBoxAscent + margin.y + expand;
  45943. //console.log(this.text, 'y' , y, 'actualBoundingBoxAscent', metrics.actualBoundingBoxAscent,'expand',expand )
  45944. // border color
  45945. context.strokeStyle = 'rgba(' + this.borderColor.r + ',' + this.borderColor.g + ',' +
  45946. this.borderColor.b + ',' + this.borderColor.a + ')';
  45947. context.lineWidth = this.rectBorderThick;
  45948. // background color
  45949. context.fillStyle = 'rgba(' + this.backgroundColor.r + ',' + this.backgroundColor.g + ',' +
  45950. this.backgroundColor.b + ',' + this.backgroundColor.a + ')';
  45951. this.roundRect(context, this.rectBorderThick / 2, this.rectBorderThick / 2,
  45952. spriteWidth - this.rectBorderThick, spriteHeight - this.rectBorderThick, this.borderRadius);
  45953. // text color
  45954. if(this.textBorderThick){
  45955. context.strokeStyle = 'rgba(' + this.textBorderColor.r + ',' + this.textBorderColor.g + ',' +
  45956. this.textBorderColor.b + ',' + this.textBorderColor.a + ')';
  45957. context.lineWidth = this.textBorderThick;
  45958. context.strokeText(this.text , this.rectBorderThick + margin.x, y /* spriteHeight/2 + expand */ );
  45959. }
  45960. context.fillStyle = 'rgba(' + this.textColor.r + ',' + this.textColor.g + ',' +
  45961. this.textColor.b + ',' + this.textColor.a + ')';
  45962. context.fillText(this.text , this.rectBorderThick + margin.x, y /* spriteHeight/2 + expand */);//x,y
  45963. let texture = new Texture(canvas);
  45964. texture.minFilter = LinearFilter; //LinearMipMapLinearFilter会缩放到power of 2
  45965. texture.magFilter = LinearFilter;
  45966. texture.needsUpdate = true;
  45967. if(this.sprite.material.map){
  45968. this.sprite.material.map.dispose();
  45969. }
  45970. this.sprite.material.map = texture;
  45971. this.sprite.scale.set(spriteWidth * 0.01, spriteHeight * 0.01, 1.0);
  45972. }
  45973. roundRect(ctx, x, y, w, h, r){
  45974. ctx.beginPath();
  45975. ctx.moveTo(x + r, y);
  45976. ctx.lineTo(x + w - r, y);
  45977. ctx.arcTo(x + w, y, x + w, y + r, r );//圆弧。前四个参数同quadraticCurveTo
  45978. //ctx.quadraticCurveTo(x + w, y, x + w, y + r); //二次贝塞尔曲线需要两个点。第一个点是用于二次贝塞尔计算中的控制点,第二个点是曲线的结束点。
  45979. ctx.lineTo(x + w, y + h - r);
  45980. ctx.arcTo(x + w, y + h, x + w - r, y + h, r );
  45981. ctx.lineTo(x + r, y + h);
  45982. ctx.arcTo(x, y + h, x, y + h - r, r );
  45983. ctx.lineTo(x, y + r);
  45984. ctx.arcTo(x, y, x + r, y, r );
  45985. ctx.closePath();
  45986. ctx.fill();
  45987. ctx.stroke();
  45988. }
  45989. dispose(){
  45990. this.sprite.material.uniforms.map.value.dispose();
  45991. this.parent && this.parent.remove(this);
  45992. this.sprite.dispatchEvent({type:'dispose'});
  45993. this.removeAllListeners();
  45994. }
  45995. }
  45996. /*
  45997. z
  45998. |
  45999. |
  46000. |
  46001. |
  46002. x <-------| 中心为点云position加boudingbox中心
  46003. /
  46004. /
  46005. y
  46006. */
  46007. var lineLen$1 = 2, stemLen = 4, arrowLen = 2, lineDisToStem = 5;
  46008. var opacity = 0.5;
  46009. class Axis extends Object3D {// 坐标轴
  46010. constructor () {
  46011. super();
  46012. this.getArrow();
  46013. this.createArrows();
  46014. //this.position.copy(position) 点云的中心点就是在(0,0,0)
  46015. //this.scale.set(2,2,2)
  46016. /* viewer.addEventListener('camera_changed', e => {
  46017. if(e.viewport.name != 'MainView')return //只调整mainView,否则需要每次渲染前调整。缺点:地图上的大小变来变去
  46018. let s = Potree.math.getScaleForConstantSize( {//规定下最小最大像素
  46019. width2d:50, camera:e.camera , position:this.position,
  46020. resolution: e.viewport.resolution//2
  46021. })
  46022. this.scale.set(s,s,s)
  46023. }) */
  46024. }
  46025. getArrow(){
  46026. var arrowGroup = new Object3D();
  46027. var line = LineDraw.createLine([new Vector3, new Vector3(0,0,lineLen$1)]);
  46028. var stem = new Mesh(new BoxGeometry(0.3, 0.3, stemLen));
  46029. stem.position.set(0,0,lineLen$1+lineDisToStem+stemLen/2);
  46030. var arrow = new Mesh(new CylinderBufferGeometry( 0, 0.6, arrowLen, 12, 1, false ));//radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2
  46031. arrow.position.set(0,0,lineLen$1+lineDisToStem+stemLen + arrowLen/2);
  46032. arrow.rotation.set(Math.PI/2,0,0);
  46033. arrowGroup.add(stem);
  46034. arrowGroup.add(line);
  46035. arrowGroup.add(arrow);
  46036. this.arrowGroup = arrowGroup;
  46037. }
  46038. createArrows(){
  46039. var material = new MeshBasicMaterial({color:"#00d7df",side:2,transparent:true,opacity:0.8, depthWrite:false});
  46040. ['x','y','z'].forEach((axisText)=>{
  46041. let color = new Color().set(Potree.config.axis[axisText].color);
  46042. var group = this.arrowGroup.clone();
  46043. group.children.forEach(e=>{
  46044. e.material = e.material.clone();
  46045. /* e.material.opacity = opacity
  46046. e.material.transparent = true */
  46047. e.material.color.copy(color);
  46048. });
  46049. var label = this.createLabel(axisText, color);
  46050. label.position.set(0, 0, lineLen$1 + stemLen + arrowLen + lineDisToStem + 3);
  46051. group.add(label);
  46052. if(axisText == 'y'){
  46053. group.rotation.x = -Math.PI / 2;
  46054. }else if(axisText == 'x'){
  46055. group.rotation.y = Math.PI / 2;
  46056. }
  46057. this.add(group);
  46058. });
  46059. }
  46060. createLabel(text,color){
  46061. let label = new TextSprite$2({ //无法解决 因其祖先有设定quaternion, 无法对着镜头
  46062. backgroundColor: {r: 0, g: 0, b: 0, a:0},
  46063. textColor: {r: color.r * 255, g: color.g*255, b: color.b*255, a:1},
  46064. fontsize:120,
  46065. //useDepth : true ,
  46066. renderOrder : 5,// pickOrder:5,
  46067. text, name:'axis'
  46068. });
  46069. label.scale.set(3,3,3);
  46070. return label
  46071. }
  46072. /* createLabel(text,color){
  46073. var canvas = document.createElement("canvas")
  46074. var context = canvas.getContext("2d");
  46075. canvas.width = 256,
  46076. canvas.height = 256;
  46077. var fontSize = 120
  46078. context.fillStyle = color //"#00ffee";
  46079. context.font = "normal " + fontSize + "px 微软雅黑"
  46080. var textWidth = context.measureText(text).width;
  46081. context.clearRect(0,0,canvas.width,canvas.height);
  46082. context.fillText(text, (canvas.width - textWidth) / 2 , (canvas.height + fontSize) / 2);
  46083. var tex = new THREE.Texture(canvas);
  46084. tex.needsUpdate = true
  46085. tex.minFilter = THREE.NearestFilter//防止边缘发黑
  46086. tex.magFilter = THREE.NearestFilter//防止边缘发黑
  46087. var sprite = new THREE.Sprite(new THREE.SpriteMaterial({
  46088. map: tex , // depthWrite:false,
  46089. }))
  46090. sprite.renderOrder = 1//防止在透明后还是出现白矩形挡住其他mesh
  46091. sprite.scale.set(3,3,3)
  46092. return sprite
  46093. } */
  46094. }
  46095. class Action extends EventDispatcher$1 {
  46096. constructor (args = {}) {
  46097. super();
  46098. this.icon = args.icon || '';
  46099. this.tooltip = args.tooltip;
  46100. if (args.onclick !== undefined) {
  46101. this.onclick = args.onclick;
  46102. }
  46103. }
  46104. onclick (event) {
  46105. }
  46106. pairWith (object) {
  46107. }
  46108. setIcon (newIcon) {
  46109. let oldIcon = this.icon;
  46110. if (newIcon === oldIcon) {
  46111. return;
  46112. }
  46113. this.icon = newIcon;
  46114. this.dispatchEvent({
  46115. type: 'icon_changed',
  46116. action: this,
  46117. icon: newIcon,
  46118. oldIcon: oldIcon
  46119. });
  46120. }
  46121. };
  46122. //Potree.Actions = {};
  46123. //
  46124. //Potree.Actions.ToggleAnnotationVisibility = class ToggleAnnotationVisibility extends Potree.Action {
  46125. // constructor (args = {}) {
  46126. // super(args);
  46127. //
  46128. // this.icon = Potree.resourcePath + '/icons/eye.svg';
  46129. // this.showIn = 'sidebar';
  46130. // this.tooltip = 'toggle visibility';
  46131. // }
  46132. //
  46133. // pairWith (annotation) {
  46134. // if (annotation.visible) {
  46135. // this.setIcon(Potree.resourcePath + '/icons/eye.svg');
  46136. // } else {
  46137. // this.setIcon(Potree.resourcePath + '/icons/eye_crossed.svg');
  46138. // }
  46139. //
  46140. // annotation.addEventListener('visibility_changed', e => {
  46141. // let annotation = e.annotation;
  46142. //
  46143. // if (annotation.visible) {
  46144. // this.setIcon(Potree.resourcePath + '/icons/eye.svg');
  46145. // } else {
  46146. // this.setIcon(Potree.resourcePath + '/icons/eye_crossed.svg');
  46147. // }
  46148. // });
  46149. // }
  46150. //
  46151. // onclick (event) {
  46152. // let annotation = event.annotation;
  46153. //
  46154. // annotation.visible = !annotation.visible;
  46155. //
  46156. // if (annotation.visible) {
  46157. // this.setIcon(Potree.resourcePath + '/icons/eye.svg');
  46158. // } else {
  46159. // this.setIcon(Potree.resourcePath + '/icons/eye_crossed.svg');
  46160. // }
  46161. // }
  46162. //};
  46163. class Annotation extends EventDispatcher$1 {
  46164. constructor (args = {}) {
  46165. super();
  46166. this.scene = null;
  46167. this._title = args.title || 'No Title';
  46168. this._description = args.description || '';
  46169. this.offset = new Vector3();
  46170. this.uuid = MathUtils$1.generateUUID();
  46171. if (!args.position) {
  46172. this.position = null;
  46173. } else if (args.position.x != null) {
  46174. this.position = args.position;
  46175. } else {
  46176. this.position = new Vector3(...args.position);
  46177. }
  46178. this.cameraPosition = (args.cameraPosition instanceof Array)
  46179. ? new Vector3().fromArray(args.cameraPosition) : args.cameraPosition;
  46180. this.cameraTarget = (args.cameraTarget instanceof Array)
  46181. ? new Vector3().fromArray(args.cameraTarget) : args.cameraTarget;
  46182. this.radius = args.radius;
  46183. this.view = args.view || null;
  46184. this.keepOpen = false;
  46185. this.descriptionVisible = false;
  46186. this.showDescription = true;
  46187. this.actions = args.actions || [];
  46188. this.isHighlighted = false;
  46189. this._visible = true;
  46190. this.__visible = true;
  46191. this._display = true;
  46192. this._expand = false;
  46193. this.collapseThreshold = [args.collapseThreshold, 100].find(e => e !== undefined);
  46194. this.children = [];
  46195. this.parent = null;
  46196. this.boundingBox = new Box3();
  46197. let iconClose = exports.resourcePath + '/icons/close.svg';
  46198. this.domElement = $(`
  46199. <div class="annotation" oncontextmenu="return false;">
  46200. <div class="annotation-titlebar">
  46201. <span class="annotation-label"></span>
  46202. </div>
  46203. <div class="annotation-description">
  46204. <span class="annotation-description-close">
  46205. <img src="${iconClose}" width="16px">
  46206. </span>
  46207. <span class="annotation-description-content">${this._description}</span>
  46208. </div>
  46209. </div>
  46210. `);
  46211. this.elTitlebar = this.domElement.find('.annotation-titlebar');
  46212. this.elTitle = this.elTitlebar.find('.annotation-label');
  46213. this.elTitle.append(this._title);
  46214. this.elDescription = this.domElement.find('.annotation-description');
  46215. this.elDescriptionClose = this.elDescription.find('.annotation-description-close');
  46216. // this.elDescriptionContent = this.elDescription.find(".annotation-description-content");
  46217. this.clickTitle = () => {
  46218. if(this.hasView()){
  46219. this.moveHere(this.scene.getActiveCamera());
  46220. }
  46221. this.dispatchEvent({type: 'click', target: this});
  46222. };
  46223. this.elTitle.click(this.clickTitle);
  46224. this.actions = this.actions.map(a => {
  46225. if (a instanceof Action) {
  46226. return a;
  46227. } else {
  46228. return new Action(a);
  46229. }
  46230. });
  46231. for (let action of this.actions) {
  46232. action.pairWith(this);
  46233. }
  46234. let actions = this.actions.filter(
  46235. a => a.showIn === undefined || a.showIn.includes('scene'));
  46236. for (let action of actions) {
  46237. let elButton = $(`<img src="${action.icon}" class="annotation-action-icon">`);
  46238. this.elTitlebar.append(elButton);
  46239. elButton.click(() => action.onclick({annotation: this}));
  46240. }
  46241. this.elDescriptionClose.hover(
  46242. e => this.elDescriptionClose.css('opacity', '1'),
  46243. e => this.elDescriptionClose.css('opacity', '0.5')
  46244. );
  46245. this.elDescriptionClose.click(e => this.setHighlighted(false));
  46246. // this.elDescriptionContent.html(this._description);
  46247. this.domElement.mouseenter(e => this.setHighlighted(true));
  46248. this.domElement.mouseleave(e => this.setHighlighted(false));
  46249. this.domElement.on('touchstart', e => {
  46250. this.setHighlighted(!this.isHighlighted);
  46251. });
  46252. this.display = false;
  46253. //this.display = true;
  46254. }
  46255. installHandles(viewer){
  46256. if(this.handles !== undefined){
  46257. return;
  46258. }
  46259. let domElement = $(`
  46260. <div style="position: absolute; left: 300; top: 200; pointer-events: none">
  46261. <svg width="300" height="600">
  46262. <line x1="0" y1="0" x2="1200" y2="200" style="stroke: black; stroke-width:2" />
  46263. <circle cx="50" cy="50" r="4" stroke="black" stroke-width="2" fill="gray" />
  46264. <circle cx="150" cy="50" r="4" stroke="black" stroke-width="2" fill="gray" />
  46265. </svg>
  46266. </div>
  46267. `);
  46268. let svg = domElement.find("svg")[0];
  46269. let elLine = domElement.find("line")[0];
  46270. let elStart = domElement.find("circle")[0];
  46271. let elEnd = domElement.find("circle")[1];
  46272. let setCoordinates = (start, end) => {
  46273. elStart.setAttribute("cx", `${start.x}`);
  46274. elStart.setAttribute("cy", `${start.y}`);
  46275. elEnd.setAttribute("cx", `${end.x}`);
  46276. elEnd.setAttribute("cy", `${end.y}`);
  46277. elLine.setAttribute("x1", start.x);
  46278. elLine.setAttribute("y1", start.y);
  46279. elLine.setAttribute("x2", end.x);
  46280. elLine.setAttribute("y2", end.y);
  46281. let box = svg.getBBox();
  46282. svg.setAttribute("width", `${box.width}`);
  46283. svg.setAttribute("height", `${box.height}`);
  46284. svg.setAttribute("viewBox", `${box.x} ${box.y} ${box.width} ${box.height}`);
  46285. let ya = start.y - end.y;
  46286. let xa = start.x - end.x;
  46287. if(ya > 0){
  46288. start.y = start.y - ya;
  46289. }
  46290. if(xa > 0){
  46291. start.x = start.x - xa;
  46292. }
  46293. domElement.css("left", `${start.x}px`);
  46294. domElement.css("top", `${start.y}px`);
  46295. };
  46296. $(viewer.renderArea).append(domElement);
  46297. let annotationStartPos = this.position.clone();
  46298. let annotationStartOffset = this.offset.clone();
  46299. $(this.domElement).draggable({
  46300. start: (event, ui) => {
  46301. annotationStartPos = this.position.clone();
  46302. annotationStartOffset = this.offset.clone();
  46303. $(this.domElement).find(".annotation-titlebar").css("pointer-events", "none");
  46304. console.log($(this.domElement).find(".annotation-titlebar"));
  46305. },
  46306. stop: () => {
  46307. $(this.domElement).find(".annotation-titlebar").css("pointer-events", "");
  46308. },
  46309. drag: (event, ui ) => {
  46310. let renderAreaWidth = viewer.renderer.getSize(new Vector2()).width;
  46311. //let renderAreaHeight = viewer.renderer.getSize().height;
  46312. let diff = {
  46313. x: ui.originalPosition.left - ui.position.left,
  46314. y: ui.originalPosition.top - ui.position.top
  46315. };
  46316. let nDiff = {
  46317. x: -(diff.x / renderAreaWidth) * 2,
  46318. y: (diff.y / renderAreaWidth) * 2
  46319. };
  46320. let camera = viewer.scene.getActiveCamera();
  46321. let oldScreenPos = new Vector3()
  46322. .addVectors(annotationStartPos, annotationStartOffset)
  46323. .project(camera);
  46324. let newScreenPos = oldScreenPos.clone();
  46325. newScreenPos.x += nDiff.x;
  46326. newScreenPos.y += nDiff.y;
  46327. let newPos = newScreenPos.clone();
  46328. newPos.unproject(camera);
  46329. let newOffset = new Vector3().subVectors(newPos, this.position);
  46330. this.offset.copy(newOffset);
  46331. }
  46332. });
  46333. let updateCallback = () => {
  46334. let position = this.position;
  46335. let scene = viewer.scene;
  46336. const renderAreaSize = viewer.renderer.getSize(new Vector2());
  46337. let renderAreaWidth = renderAreaSize.width;
  46338. let renderAreaHeight = renderAreaSize.height;
  46339. let start = this.position.clone();
  46340. let end = new Vector3().addVectors(this.position, this.offset);
  46341. let toScreen = (position) => {
  46342. let camera = scene.getActiveCamera();
  46343. let screenPos = new Vector3();
  46344. let worldView = new Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
  46345. let ndc = new Vector4(position.x, position.y, position.z, 1.0).applyMatrix4(worldView);
  46346. // limit w to small positive value, in case position is behind the camera
  46347. ndc.w = Math.max(ndc.w, 0.1);
  46348. ndc.divideScalar(ndc.w);
  46349. screenPos.copy(ndc);
  46350. screenPos.x = renderAreaWidth * (screenPos.x + 1) / 2;
  46351. screenPos.y = renderAreaHeight * (1 - (screenPos.y + 1) / 2);
  46352. return screenPos;
  46353. };
  46354. start = toScreen(start);
  46355. end = toScreen(end);
  46356. setCoordinates(start, end);
  46357. };
  46358. viewer.addEventListener("update", updateCallback);
  46359. this.handles = {
  46360. domElement: domElement,
  46361. setCoordinates: setCoordinates,
  46362. updateCallback: updateCallback
  46363. };
  46364. }
  46365. removeHandles(viewer){
  46366. if(this.handles === undefined){
  46367. return;
  46368. }
  46369. //$(viewer.renderArea).remove(this.handles.domElement);
  46370. this.handles.domElement.remove();
  46371. viewer.removeEventListener("update", this.handles.updateCallback);
  46372. delete this.handles;
  46373. }
  46374. get visible () {
  46375. return this._visible;
  46376. }
  46377. set visible (value) {
  46378. if (this._visible === value) {
  46379. return;
  46380. }
  46381. this._visible = value;
  46382. //this.traverse(node => {
  46383. // node.display = value;
  46384. //});
  46385. this.dispatchEvent({
  46386. type: 'visibility_changed',
  46387. annotation: this
  46388. });
  46389. }
  46390. get display () {
  46391. return this._display;
  46392. }
  46393. set display (display) {
  46394. if (this._display === display) {
  46395. return;
  46396. }
  46397. this._display = display;
  46398. if (display) {
  46399. // this.domElement.fadeIn(200);
  46400. this.domElement.show();
  46401. } else {
  46402. // this.domElement.fadeOut(200);
  46403. this.domElement.hide();
  46404. }
  46405. }
  46406. get expand () {
  46407. return this._expand;
  46408. }
  46409. set expand (expand) {
  46410. if (this._expand === expand) {
  46411. return;
  46412. }
  46413. if (expand) {
  46414. this.display = false;
  46415. } else {
  46416. this.display = true;
  46417. this.traverseDescendants(node => {
  46418. node.display = false;
  46419. });
  46420. }
  46421. this._expand = expand;
  46422. }
  46423. get title () {
  46424. return this._title;
  46425. }
  46426. set title (title) {
  46427. if (this._title === title) {
  46428. return;
  46429. }
  46430. this._title = title;
  46431. this.elTitle.empty();
  46432. this.elTitle.append(this._title);
  46433. this.dispatchEvent({
  46434. type: "annotation_changed",
  46435. annotation: this,
  46436. });
  46437. }
  46438. get description () {
  46439. return this._description;
  46440. }
  46441. set description (description) {
  46442. if (this._description === description) {
  46443. return;
  46444. }
  46445. this._description = description;
  46446. const elDescriptionContent = this.elDescription.find(".annotation-description-content");
  46447. elDescriptionContent.empty();
  46448. elDescriptionContent.append(this._description);
  46449. this.dispatchEvent({
  46450. type: "annotation_changed",
  46451. annotation: this,
  46452. });
  46453. }
  46454. add (annotation) {
  46455. if (!this.children.includes(annotation)) {
  46456. this.children.push(annotation);
  46457. annotation.parent = this;
  46458. let descendants = [];
  46459. annotation.traverse(a => { descendants.push(a); });
  46460. for (let descendant of descendants) {
  46461. let c = this;
  46462. while (c !== null) {
  46463. c.dispatchEvent({
  46464. 'type': 'annotation_added',
  46465. 'annotation': descendant
  46466. });
  46467. c = c.parent;
  46468. }
  46469. }
  46470. }
  46471. }
  46472. level () {
  46473. if (this.parent === null) {
  46474. return 0;
  46475. } else {
  46476. return this.parent.level() + 1;
  46477. }
  46478. }
  46479. hasChild(annotation) {
  46480. return this.children.includes(annotation);
  46481. }
  46482. remove (annotation) {
  46483. if (this.hasChild(annotation)) {
  46484. annotation.removeAllChildren();
  46485. annotation.dispose();
  46486. this.children = this.children.filter(e => e !== annotation);
  46487. annotation.parent = null;
  46488. }
  46489. }
  46490. removeAllChildren() {
  46491. this.children.forEach((child) => {
  46492. if (child.children.length > 0) {
  46493. child.removeAllChildren();
  46494. }
  46495. this.remove(child);
  46496. });
  46497. }
  46498. updateBounds () {
  46499. let box = new Box3();
  46500. if (this.position) {
  46501. box.expandByPoint(this.position);
  46502. }
  46503. for (let child of this.children) {
  46504. child.updateBounds();
  46505. box.union(child.boundingBox);
  46506. }
  46507. this.boundingBox.copy(box);
  46508. }
  46509. traverse (handler) {
  46510. let expand = handler(this);
  46511. if (expand === undefined || expand === true) {
  46512. for (let child of this.children) {
  46513. child.traverse(handler);
  46514. }
  46515. }
  46516. }
  46517. traverseDescendants (handler) {
  46518. for (let child of this.children) {
  46519. child.traverse(handler);
  46520. }
  46521. }
  46522. flatten () {
  46523. let annotations = [];
  46524. this.traverse(annotation => {
  46525. annotations.push(annotation);
  46526. });
  46527. return annotations;
  46528. }
  46529. descendants () {
  46530. let annotations = [];
  46531. this.traverse(annotation => {
  46532. if (annotation !== this) {
  46533. annotations.push(annotation);
  46534. }
  46535. });
  46536. return annotations;
  46537. }
  46538. setHighlighted (highlighted) {
  46539. if (highlighted) {
  46540. this.domElement.css('opacity', '0.8');
  46541. this.elTitlebar.css('box-shadow', '0 0 5px #fff');
  46542. this.domElement.css('z-index', '1000');
  46543. if (this._description) {
  46544. this.descriptionVisible = true;
  46545. this.elDescription.fadeIn(200);
  46546. this.elDescription.css('position', 'relative');
  46547. }
  46548. } else {
  46549. this.domElement.css('opacity', '0.5');
  46550. this.elTitlebar.css('box-shadow', '');
  46551. this.domElement.css('z-index', '100');
  46552. this.descriptionVisible = false;
  46553. this.elDescription.css('display', 'none');
  46554. }
  46555. this.isHighlighted = highlighted;
  46556. }
  46557. hasView () {
  46558. let hasPosTargetView = this.cameraTarget.x != null;
  46559. hasPosTargetView = hasPosTargetView && this.cameraPosition.x != null;
  46560. let hasRadiusView = this.radius !== undefined;
  46561. let hasView = hasPosTargetView || hasRadiusView;
  46562. return hasView;
  46563. };
  46564. moveHere (camera) {
  46565. if (!this.hasView()) {
  46566. return;
  46567. }
  46568. let view = this.scene.view;
  46569. let animationDuration = 500;
  46570. let easing = TWEEN.Easing.Quartic.Out;
  46571. let endTarget;
  46572. if (this.cameraTarget) {
  46573. endTarget = this.cameraTarget;
  46574. } else if (this.position) {
  46575. endTarget = this.position;
  46576. } else {
  46577. endTarget = this.boundingBox.getCenter(new Vector3());
  46578. }
  46579. if (this.cameraPosition) {
  46580. let endPosition = this.cameraPosition;
  46581. Utils.moveTo(this.scene, endPosition, endTarget);
  46582. } else if (this.radius) {
  46583. let direction = view.direction;
  46584. let endPosition = endTarget.clone().add(direction.multiplyScalar(-this.radius));
  46585. let startRadius = view.radius;
  46586. let endRadius = this.radius;
  46587. { // animate camera position
  46588. let tween = new TWEEN.Tween(view.position).to(endPosition, animationDuration);
  46589. tween.easing(easing);
  46590. tween.start();
  46591. }
  46592. { // animate radius
  46593. let t = {x: 0};
  46594. let tween = new TWEEN.Tween(t)
  46595. .to({x: 1}, animationDuration)
  46596. .onUpdate(function () {
  46597. view.radius = this.x * endRadius + (1 - this.x) * startRadius;
  46598. });
  46599. tween.easing(easing);
  46600. tween.start();
  46601. }
  46602. }
  46603. };
  46604. dispose () {
  46605. if (this.domElement.parentElement) {
  46606. this.domElement.parentElement.removeChild(this.domElement);
  46607. }
  46608. };
  46609. toString () {
  46610. return 'Annotation: ' + this._title;
  46611. }
  46612. };
  46613. class Scene$1 extends EventDispatcher$1{//base
  46614. constructor(){
  46615. super();
  46616. this.annotations = new Annotation();
  46617. this.scene = new Scene();
  46618. this.sceneBG = new Scene();
  46619. this.scenePointCloud = new Scene();
  46620. this.cameraP = new PerspectiveCamera(this.fov, 1, 0.1, 1000*1000);
  46621. this.cameraO = new OrthographicCamera(-1, 1, 1, -1, 0.1, 1000*1000);
  46622. this.cameraVR = new PerspectiveCamera();
  46623. this.cameraBG = new Camera();
  46624. this.cameraScreenSpace = new OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
  46625. this.cameraMode = CameraMode.PERSPECTIVE;
  46626. this.overrideCamera = null;
  46627. this.pointclouds = [];
  46628. this.measurements = [];
  46629. this.profiles = [];
  46630. this.volumes = [];
  46631. this.polygonClipVolumes = [];
  46632. this.cameraAnimations = [];
  46633. this.orientedImages = [];
  46634. this.images360 = [];
  46635. this.geopackages = [];
  46636. this.fpControls = null;
  46637. this.orbitControls = null;
  46638. this.earthControls = null;
  46639. this.geoControls = null;
  46640. this.deviceControls = null;
  46641. this.inputHandler = null;
  46642. this.view = new ExtendView();
  46643. this.directionalLight = null;
  46644. this.initialize();
  46645. }
  46646. estimateHeightAt (position) {
  46647. let height = null;
  46648. let fromSpacing = Infinity;
  46649. for (let pointcloud of this.pointclouds) {
  46650. if (pointcloud.root.geometryNode === undefined) {
  46651. continue;
  46652. }
  46653. let pHeight = null;
  46654. let pFromSpacing = Infinity;
  46655. let lpos = position.clone().sub(pointcloud.position);
  46656. lpos.z = 0;
  46657. let ray = new Ray(lpos, new Vector3(0, 0, 1));
  46658. let stack = [pointcloud.root];
  46659. while (stack.length > 0) {
  46660. let node = stack.pop();
  46661. let box = node.getBoundingBox();
  46662. let inside = ray.intersectBox(box);
  46663. if (!inside) {
  46664. continue;
  46665. }
  46666. let h = node.geometryNode.mean.z +
  46667. pointcloud.position.z +
  46668. node.geometryNode.boundingBox.min.z;
  46669. if (node.geometryNode.spacing <= pFromSpacing) {
  46670. pHeight = h;
  46671. pFromSpacing = node.geometryNode.spacing;
  46672. }
  46673. for (let index of Object.keys(node.children)) {
  46674. let child = node.children[index];
  46675. if (child.geometryNode) {
  46676. stack.push(node.children[index]);
  46677. }
  46678. }
  46679. }
  46680. if (height === null || pFromSpacing < fromSpacing) {
  46681. height = pHeight;
  46682. fromSpacing = pFromSpacing;
  46683. }
  46684. }
  46685. return height;
  46686. }
  46687. getBoundingBox(pointclouds = this.pointclouds){
  46688. let box = new Box3();
  46689. this.scenePointCloud.updateMatrixWorld(true);
  46690. this.referenceFrame.updateMatrixWorld(true);
  46691. for (let pointcloud of pointclouds) {
  46692. pointcloud.updateMatrixWorld(true);
  46693. let pointcloudBox = pointcloud.pcoGeometry.tightBoundingBox ? pointcloud.pcoGeometry.tightBoundingBox : pointcloud.boundingBox;
  46694. let boxWorld = Utils.computeTransformedBoundingBox(pointcloudBox, pointcloud.matrixWorld);
  46695. box.union(boxWorld);
  46696. }
  46697. return box;
  46698. }
  46699. addPointCloud (pointcloud) {
  46700. this.pointclouds.push(pointcloud);
  46701. this.scenePointCloud.add(pointcloud);
  46702. this.dispatchEvent({
  46703. type: 'pointcloud_added',
  46704. pointcloud: pointcloud
  46705. });
  46706. }
  46707. addVolume (volume) {
  46708. this.volumes.push(volume);
  46709. this.dispatchEvent({
  46710. 'type': 'volume_added',
  46711. 'scene': this,
  46712. 'volume': volume
  46713. });
  46714. viewer.dispatchEvent('content_changed');
  46715. }
  46716. addOrientedImages(images){
  46717. this.orientedImages.push(images);
  46718. this.scene.add(images.node);
  46719. this.dispatchEvent({
  46720. 'type': 'oriented_images_added',
  46721. 'scene': this,
  46722. 'images': images
  46723. });
  46724. };
  46725. removeOrientedImages(images){
  46726. let index = this.orientedImages.indexOf(images);
  46727. if (index > -1) {
  46728. this.orientedImages.splice(index, 1);
  46729. this.dispatchEvent({
  46730. 'type': 'oriented_images_removed',
  46731. 'scene': this,
  46732. 'images': images
  46733. });
  46734. }
  46735. };
  46736. add360Images(images){
  46737. this.images360.push(images);
  46738. this.scene.add(images.node);
  46739. this.dispatchEvent({
  46740. 'type': '360_images_added',
  46741. 'scene': this,
  46742. 'images': images
  46743. });
  46744. }
  46745. remove360Images(images){
  46746. let index = this.images360.indexOf(images);
  46747. if (index > -1) {
  46748. this.images360.splice(index, 1);
  46749. this.dispatchEvent({
  46750. 'type': '360_images_removed',
  46751. 'scene': this,
  46752. 'images': images
  46753. });
  46754. }
  46755. }
  46756. addGeopackage(geopackage){
  46757. this.geopackages.push(geopackage);
  46758. this.scene.add(geopackage.node);
  46759. this.dispatchEvent({
  46760. 'type': 'geopackage_added',
  46761. 'scene': this,
  46762. 'geopackage': geopackage
  46763. });
  46764. };
  46765. removeGeopackage(geopackage){
  46766. let index = this.geopackages.indexOf(geopackage);
  46767. if (index > -1) {
  46768. this.geopackages.splice(index, 1);
  46769. this.dispatchEvent({
  46770. 'type': 'geopackage_removed',
  46771. 'scene': this,
  46772. 'geopackage': geopackage
  46773. });
  46774. }
  46775. };
  46776. removeVolume (volume) {
  46777. let index = this.volumes.indexOf(volume);
  46778. if (index > -1) {
  46779. this.volumes.splice(index, 1);
  46780. this.dispatchEvent({
  46781. 'type': 'volume_removed',
  46782. 'scene': this,
  46783. 'volume': volume
  46784. });
  46785. }
  46786. viewer.dispatchEvent('content_changed');
  46787. };
  46788. addCameraAnimation(animation) {
  46789. this.cameraAnimations.push(animation);
  46790. this.dispatchEvent({
  46791. 'type': 'camera_animation_added',
  46792. 'scene': this,
  46793. 'animation': animation
  46794. });
  46795. };
  46796. removeCameraAnimation(animation){
  46797. let index = this.cameraAnimations.indexOf(volume);
  46798. if (index > -1) {
  46799. this.cameraAnimations.splice(index, 1);
  46800. this.dispatchEvent({
  46801. 'type': 'camera_animation_removed',
  46802. 'scene': this,
  46803. 'animation': animation
  46804. });
  46805. }
  46806. };
  46807. addPolygonClipVolume(volume){
  46808. this.polygonClipVolumes.push(volume);
  46809. this.dispatchEvent({
  46810. "type": "polygon_clip_volume_added",
  46811. "scene": this,
  46812. "volume": volume
  46813. });
  46814. };
  46815. removePolygonClipVolume(volume){
  46816. let index = this.polygonClipVolumes.indexOf(volume);
  46817. if (index > -1) {
  46818. this.polygonClipVolumes.splice(index, 1);
  46819. this.dispatchEvent({
  46820. "type": "polygon_clip_volume_removed",
  46821. "scene": this,
  46822. "volume": volume
  46823. });
  46824. }
  46825. };
  46826. addMeasurement(measurement){
  46827. measurement.lengthUnit = this.lengthUnit;
  46828. measurement.lengthUnitDisplay = this.lengthUnitDisplay;
  46829. this.measurements.push(measurement);
  46830. this.dispatchEvent({
  46831. 'type': 'measurement_added',
  46832. 'scene': this,
  46833. 'measurement': measurement
  46834. });
  46835. viewer.dispatchEvent('content_changed');
  46836. };
  46837. removeMeasurement (measurement) {
  46838. let index = this.measurements.indexOf(measurement);
  46839. if (index > -1) {
  46840. this.measurements.splice(index, 1);
  46841. this.dispatchEvent({
  46842. 'type': 'measurement_removed',
  46843. 'scene': this,
  46844. 'measurement': measurement
  46845. });
  46846. viewer.dispatchEvent('content_changed');
  46847. }
  46848. }
  46849. addProfile (profile) {
  46850. this.profiles.push(profile);
  46851. this.dispatchEvent({
  46852. 'type': 'profile_added',
  46853. 'scene': this,
  46854. 'profile': profile
  46855. });
  46856. }
  46857. removeProfile (profile) {
  46858. let index = this.profiles.indexOf(profile);
  46859. if (index > -1) {
  46860. this.profiles.splice(index, 1);
  46861. this.dispatchEvent({
  46862. 'type': 'profile_removed',
  46863. 'scene': this,
  46864. 'profile': profile
  46865. });
  46866. }
  46867. }
  46868. removeAllMeasurements () {
  46869. while (this.measurements.length > 0) {
  46870. this.removeMeasurement(this.measurements[0]);
  46871. }
  46872. while (this.profiles.length > 0) {
  46873. this.removeProfile(this.profiles[0]);
  46874. }
  46875. while (this.volumes.length > 0) {
  46876. this.removeVolume(this.volumes[0]);
  46877. }
  46878. }
  46879. removeAllClipVolumes(){
  46880. let clipVolumes = this.volumes.filter(volume => volume.clip === true);
  46881. for(let clipVolume of clipVolumes){
  46882. this.removeVolume(clipVolume);
  46883. }
  46884. while(this.polygonClipVolumes.length > 0){
  46885. this.removePolygonClipVolume(this.polygonClipVolumes[0]);
  46886. }
  46887. }
  46888. getActiveCamera() {
  46889. if(this.overrideCamera){
  46890. return this.overrideCamera;
  46891. }
  46892. if(this.cameraMode === CameraMode.PERSPECTIVE){
  46893. return this.cameraP;
  46894. }else if(this.cameraMode === CameraMode.ORTHOGRAPHIC){
  46895. return this.cameraO;
  46896. }else if(this.cameraMode === CameraMode.VR){
  46897. return this.cameraVR;
  46898. }
  46899. return null;
  46900. }
  46901. initialize(){
  46902. this.referenceFrame = new Object3D();
  46903. this.referenceFrame.matrixAutoUpdate = false;
  46904. this.scenePointCloud.add(this.referenceFrame);
  46905. this.cameraP.up.set(0, 0, 1);
  46906. this.cameraP.position.set(1000, 1000, 1000);
  46907. this.cameraO.up.set(0, 0, 1);
  46908. this.cameraO.position.set(1000, 1000, 1000);
  46909. //this.camera.rotation.y = -Math.PI / 4;
  46910. //this.camera.rotation.x = -Math.PI / 6;
  46911. this.cameraScreenSpace.lookAt(new Vector3(0, 0, 0), new Vector3(0, 0, -1), new Vector3(0, 1, 0));
  46912. this.directionalLight = new DirectionalLight( 0xffffff, 0.5 );
  46913. this.directionalLight.position.set( 10, 10, 10 );
  46914. this.directionalLight.lookAt( new Vector3(0, 0, 0));
  46915. this.scenePointCloud.add( this.directionalLight );
  46916. let light = new AmbientLight( 0x555555 ); // soft white light
  46917. this.scenePointCloud.add( light );
  46918. { // background
  46919. let texture = Utils.createBackgroundTexture(512, 512);
  46920. texture.minFilter = texture.magFilter = NearestFilter;
  46921. texture.minFilter = texture.magFilter = LinearFilter;
  46922. let bg = new Mesh(
  46923. new PlaneBufferGeometry(2, 2, 1),
  46924. new MeshBasicMaterial({
  46925. map: texture
  46926. })
  46927. );
  46928. bg.material.depthTest = false;
  46929. bg.material.depthWrite = false;
  46930. this.sceneBG.add(bg);
  46931. }
  46932. // { // lights
  46933. // {
  46934. // let light = new THREE.DirectionalLight(0xffffff);
  46935. // light.position.set(10, 10, 1);
  46936. // light.target.position.set(0, 0, 0);
  46937. // this.scene.add(light);
  46938. // }
  46939. // {
  46940. // let light = new THREE.DirectionalLight(0xffffff);
  46941. // light.position.set(-10, 10, 1);
  46942. // light.target.position.set(0, 0, 0);
  46943. // this.scene.add(light);
  46944. // }
  46945. // {
  46946. // let light = new THREE.DirectionalLight(0xffffff);
  46947. // light.position.set(0, -10, 20);
  46948. // light.target.position.set(0, 0, 0);
  46949. // this.scene.add(light);
  46950. // }
  46951. // }
  46952. }
  46953. addAnnotation(position, args = {}){
  46954. if(position instanceof Array){
  46955. args.position = new Vector3().fromArray(position);
  46956. } else if (position.x != null) {
  46957. args.position = position;
  46958. }
  46959. let annotation = new Annotation(args);
  46960. this.annotations.add(annotation);
  46961. return annotation;
  46962. }
  46963. getAnnotations () {
  46964. return this.annotations;
  46965. };
  46966. removeAnnotation(annotationToRemove) {
  46967. this.annotations.remove(annotationToRemove);
  46968. }
  46969. };
  46970. class ExtendScene extends Scene$1{
  46971. constructor(){
  46972. super();
  46973. delete this.sceneBG;
  46974. this.cameraP = new PerspectiveCamera(this.fov, 1, Potree.config.view.near, Potree.config.view.near);
  46975. this.cameraO = new OrthographicCamera(-1, 1, 1, -1, Potree.config.view.near, Potree.settings.cameraFar);
  46976. this.cameraP.limitFar = true;//add
  46977. this.cameraBasic = new PerspectiveCamera();//add 不自动计算的渐变相机
  46978. this.cameraBasic.name = 'tranCamera';
  46979. //this.cameraBasic.matrixAutoUpdate = false
  46980. this.initializeExtend();
  46981. //-------------
  46982. this.axisArrow = new Axis();
  46983. this.scene.add(this.axisArrow);
  46984. if(!Potree.settings.isDebug && !Potree.settings.showAxis)this.axisArrow.visible = false;
  46985. Potree.Utils.setObjectLayers(this.axisArrow, 'bothMapAndScene' );
  46986. this.tags = new Object3D;
  46987. this.scene.add(this.tags);
  46988. }
  46989. estimateHeightAt (position) {
  46990. let height = null;
  46991. let fromSpacing = Infinity;
  46992. for (let pointcloud of this.pointclouds) {
  46993. if (pointcloud.root.geometryNode === undefined) {
  46994. continue;
  46995. }
  46996. let pHeight = null;
  46997. let pFromSpacing = Infinity;
  46998. let lpos = position.clone().sub(pointcloud.position);
  46999. lpos.z = 0;
  47000. let ray = new Ray(lpos, new Vector3(0, 0, 1));
  47001. let stack = [pointcloud.root];
  47002. while (stack.length > 0) {
  47003. let node = stack.pop();
  47004. let box = node.getBoundingBox();
  47005. let inside = ray.intersectBox(box);
  47006. if (!inside) {
  47007. continue;
  47008. }
  47009. let h = node.geometryNode.mean.z +
  47010. pointcloud.position.z +
  47011. node.geometryNode.boundingBox.min.z;
  47012. if (node.geometryNode.spacing <= pFromSpacing) {
  47013. pHeight = h;
  47014. pFromSpacing = node.geometryNode.spacing;
  47015. }
  47016. for (let index of Object.keys(node.children)) {
  47017. let child = node.children[index];
  47018. if (child.geometryNode) {
  47019. stack.push(node.children[index]);
  47020. }
  47021. }
  47022. }
  47023. if (height === null || pFromSpacing < fromSpacing) {
  47024. height = pHeight;
  47025. fromSpacing = pFromSpacing;
  47026. }
  47027. }
  47028. return height;
  47029. }
  47030. //add:
  47031. removePointCloud (pointcloud) {
  47032. let index = this.pointclouds.indexOf(pointcloud);
  47033. if(index == -1)return
  47034. this.pointclouds.splice(index, 1);
  47035. this.scenePointCloud.remove(pointcloud);
  47036. pointcloud.panos.forEach(pano=>{
  47037. pano.dispose();
  47038. });
  47039. }
  47040. removeCameraAnimation(animation){
  47041. let index = this.cameraAnimations.indexOf(animation);
  47042. if (index > -1) {
  47043. this.cameraAnimations.splice(index, 1);
  47044. this.dispatchEvent({
  47045. 'type': 'camera_animation_removed',
  47046. 'scene': this,
  47047. 'animation': animation
  47048. });
  47049. }
  47050. };
  47051. getActiveCamera() {
  47052. return viewer.mainViewport.camera
  47053. }
  47054. initialize(){//不用旧的 因为还没创建完变量
  47055. }
  47056. initializeExtend(){//add 新的initialize
  47057. this.referenceFrame = new Object3D();
  47058. this.referenceFrame.matrixAutoUpdate = false;
  47059. this.scenePointCloud.add(this.referenceFrame);
  47060. if(window.axisYup){
  47061. }else {
  47062. this.cameraP.up.set(0, 0, 1);
  47063. this.cameraO.up.set(0, 0, 1);
  47064. }
  47065. this.cameraP.position.set(1000, 1000, 1000);
  47066. this.cameraO.position.set(1000, 1000, 1000);
  47067. //this.camera.rotation.y = -Math.PI / 4;
  47068. //this.camera.rotation.x = -Math.PI / 6;
  47069. this.cameraScreenSpace.lookAt(new Vector3(0, 0, 0), new Vector3(0, 0, -1), new Vector3(0, 1, 0));
  47070. this.directionalLight = new DirectionalLight( 0xffffff, 0.5 );
  47071. this.directionalLight.position.set( 10, 10, 10 );
  47072. this.directionalLight.lookAt( new Vector3(0, 0, 0));
  47073. this.scenePointCloud.add( this.directionalLight );
  47074. let light = new AmbientLight( 0x555555 ); // soft white light
  47075. this.scenePointCloud.add( light );
  47076. //add:------给空间模型的box 或其他obj------
  47077. let light2 = new AmbientLight( 16777215, 1 );
  47078. Potree.Utils.setObjectLayers(light2, 'light'/* 'bothMapAndScene' */);
  47079. this.scene.add(light2);
  47080. let light3 = new DirectionalLight( 16777215, 1);
  47081. light3.position.set( 10, 10, 10 );
  47082. light3.lookAt( new Vector3(0, 0, 0));
  47083. Potree.Utils.setObjectLayers(light3, 'light');
  47084. this.scene.add(light3);
  47085. //--------------------------------------------
  47086. { // background
  47087. let texture = Utils.createBackgroundTexture(512, 512);
  47088. texture.minFilter = texture.magFilter = NearestFilter;
  47089. texture.minFilter = texture.magFilter = LinearFilter;
  47090. let bg = new Mesh(
  47091. new PlaneBufferGeometry(2, 2, 1),
  47092. new MeshBasicMaterial({
  47093. map: texture
  47094. })
  47095. );
  47096. bg.material.depthTest = false;
  47097. bg.material.depthWrite = false;
  47098. bg.name = 'bg';
  47099. //this.sceneBG.add(bg);
  47100. this.scene.add(bg);
  47101. bg.layers.set(Potree.config.renderLayers.bg);
  47102. }
  47103. { // background color
  47104. let bg2 = new Mesh(
  47105. new PlaneBufferGeometry(2, 2, 1),
  47106. new MeshBasicMaterial({
  47107. transparent : true
  47108. })
  47109. );
  47110. bg2.material.depthTest = false;
  47111. bg2.material.depthWrite = false;
  47112. bg2.name = 'bg2';
  47113. this.scene.add(bg2);
  47114. bg2.layers.set(Potree.config.renderLayers.bg2);
  47115. this.bg2 = bg2;
  47116. }
  47117. // { // lights
  47118. // {
  47119. // let light = new THREE.DirectionalLight(0xffffff);
  47120. // light.position.set(10, 10, 1);
  47121. // light.target.position.set(0, 0, 0);
  47122. // this.scene.add(light);
  47123. // }
  47124. // {
  47125. // let light = new THREE.DirectionalLight(0xffffff);
  47126. // light.position.set(-10, 10, 1);
  47127. // light.target.position.set(0, 0, 0);
  47128. // this.scene.add(light);
  47129. // }
  47130. // {
  47131. // let light = new THREE.DirectionalLight(0xffffff);
  47132. // light.position.set(0, -10, 20);
  47133. // light.target.position.set(0, 0, 0);
  47134. // this.scene.add(light);
  47135. // }
  47136. // }
  47137. }
  47138. };
  47139. KeyCodes.BACKSPACE = 8;
  47140. //注意,这时候Potree.js中export的内容还不在Potree变量中
  47141. var texLoader$1 = new TextureLoader();
  47142. {//defines:
  47143. Potree.defines = {};
  47144. Potree.defines.Buttons = {// MouseEvent.buttons
  47145. //buttons,设置按下了鼠标哪些键,是一个3个比特位的二进制值,默认为0。1表示按下主键(通常是左键),2表示按下次要键(通常是右键),4表示按下辅助键(通常是中间的键)。
  47146. NONE:0,//add
  47147. LEFT: 0b0001,
  47148. RIGHT: 0b0010,
  47149. MIDDLE: 0b0100
  47150. };
  47151. /* 如果访问的是button, 用THREE.MOUSE来判断:
  47152. button,设置按下了哪一个鼠标按键,默认为0。-1表示没有按键,0表示按下主键(通常是左键),1表示按下辅助键(通常是中间的键),2表示按下次要键(通常是右键)
  47153. */
  47154. Potree.browser = browser;
  47155. /////////// add //////////////////////////////////
  47156. /* Potree.defines.GLCubeFaces = {
  47157. GL_TEXTURE_CUBE_MAP_POSITIVE_X: 0,
  47158. GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1,
  47159. GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2,
  47160. GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 3,
  47161. GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 4,
  47162. GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 5
  47163. };
  47164. Potree.defines.PanoSizeClass = {
  47165. BASE: 1,
  47166. STANDARD: 2,
  47167. HIGH: 3,
  47168. ULTRAHIGH: 4
  47169. };
  47170. Potree.defines.TileDownloaderEvents = {
  47171. TileDownloadSuccess: "tiledownloader.download.success",
  47172. TileDownloadFailure: "tiledownloader.download.failure",
  47173. PanoDownloadComplete: "tiledownloader.pano.download.complete"
  47174. };*/
  47175. Potree.defines.PanoRendererEvents = {
  47176. PanoRenderComplete: "panorama.render.complete",
  47177. TileRenderFailure: "panorama.tile.render.failed",
  47178. TileRenderSuccess: "panorama.tile.render.success",
  47179. TileUploadAttempted: "panorama.tile.upload.attempted",
  47180. UploadAttemptedForAllTiles: "panorama.upload.attempted.all.tiles",
  47181. ZoomLevelRenderStarted: "panorama.zoom.render.started"
  47182. };
  47183. Potree.defines.SceneRendererEvents = {
  47184. ContextCreated: "scene-renderer-context-created",
  47185. AfterRender: "after-render",
  47186. MemoryUsageUpdated: "scene-renderer-memory-usage-updated"
  47187. };
  47188. Potree.defines.Vectors = {
  47189. UP: new Vector3(0,1,0),
  47190. DOWN: new Vector3(0,-1,0),
  47191. LEFT: new Vector3(-1,0,0),
  47192. RIGHT: new Vector3(1,0,0),
  47193. FORWARD: new Vector3(0,0,-1),
  47194. BACK: new Vector3(0,0,1)
  47195. };
  47196. /* var Vectors2 = {}
  47197. for(var i in Vectors){
  47198. Vectors2[i] = math.convertVector.YupToZup(Vectors[i])
  47199. }
  47200. */
  47201. Potree.defines.DownloadStatus = Object.freeze({
  47202. None: 0,
  47203. Queued: 1,
  47204. ForceQueued: 2,
  47205. Downloading: 3,
  47206. Downloaded: 4,
  47207. DownloadFailed: 5
  47208. });
  47209. Potree.defines.ModelManagerEvents = {
  47210. ModelAdded: "model-added",
  47211. ActiveModelChanged: "active-model-changed"
  47212. };
  47213. Potree.defines.PanoramaEvents = {
  47214. Enter: 'panorama.enter',
  47215. Exit: 'panorama.exit',
  47216. LoadComplete: "panorama.load.complete",
  47217. LoadFailed: "panorama.load.failed",
  47218. TileLoaded: "panorama.tile.loaded",
  47219. VideoRendered: "panorama.video.rendered"
  47220. };
  47221. ClipTask.SHOW_INSIDE_Big = 4;
  47222. }
  47223. {//Features
  47224. let gl_;
  47225. Features.EXT_DEPTH = {
  47226. isSupported: function (gl) {
  47227. gl = gl || gl_;
  47228. gl_ = gl;
  47229. if(browser.detectIOS()){
  47230. let {major,minor,patch} = browser.iosVersion();
  47231. if(major == 15 && minor == 4 && patch == 1){
  47232. console.warn('检测到是ios15.4.1, 关闭EXT_frag_depth');//该版本ext_depth有问题,导致clear错乱。没有解决办法先关闭。
  47233. return false
  47234. }
  47235. }
  47236. return (typeof WebGL2RenderingContext != 'undefined' && gl instanceof WebGL2RenderingContext) || gl.getExtension('EXT_frag_depth'); //shader中的GL_EXT_frag_depth需要判断一下detectIOS吗。。
  47237. }
  47238. };
  47239. }
  47240. Utils.loadSkybox = function(path, oldSky ) {
  47241. let camera, scene, parent , cameraOrtho;
  47242. if(!oldSky){
  47243. parent = new Object3D("skybox_root");
  47244. camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 100000);
  47245. cameraOrtho = new OrthographicCamera(-1, 1, 1, -1, Potree.config.view.near, Potree.settings.cameraFar);
  47246. if(!window.axisYup) camera.up.set(0, 0, 1);//add
  47247. scene = new Scene();
  47248. let skyboxBgWidth = Potree.config.skyboxBgWidth;
  47249. let skyGeometry = new BoxBufferGeometry(skyboxBgWidth,skyboxBgWidth,skyboxBgWidth);
  47250. let skybox = new Mesh(skyGeometry, new ShaderMaterial({
  47251. vertexShader: Shaders['skybox.vs'],
  47252. fragmentShader: Shaders['skybox.fs'],
  47253. side: BackSide,
  47254. uniforms:{
  47255. tDiffuse: {
  47256. type: "t",
  47257. value: null
  47258. },
  47259. matrix:{
  47260. type: "m4",
  47261. value: new Matrix4
  47262. }
  47263. },
  47264. depthTest:false,
  47265. depthWrite:false
  47266. }) );
  47267. scene.add(skybox);
  47268. scene.traverse(n => n.frustumCulled = false);
  47269. // z up
  47270. //scene.rotation.x = Math.PI / 2;
  47271. parent.children.push(camera);
  47272. camera.parent = parent;
  47273. }else {
  47274. camera = oldSky.camera,
  47275. scene = oldSky.scene;
  47276. parent = oldSky.parent;
  47277. cameraOrtho = oldSky.cameraOrtho;
  47278. }
  47279. let texture = texLoader$1.load( path, ()=>{
  47280. console.log('loadSkybox成功',path);
  47281. texture.wrapS = RepeatWrapping;
  47282. texture.flipY = false;
  47283. texture.magFilter = LinearFilter;
  47284. texture.minFilter = LinearFilter;
  47285. scene.children[0].material.uniforms.tDiffuse.value = texture;
  47286. viewer.dispatchEvent('content_changed');
  47287. },null,(e)=>{//error
  47288. console.error('loadSkybox失败',path);
  47289. });
  47290. return {camera, scene, parent, cameraOrtho};
  47291. };
  47292. Utils.getMousePointCloudIntersection = function(viewport, mouse, pointer, camera, viewer, pointclouds, pickParams = {} ) {
  47293. //getIntersectByDepthTex
  47294. /* let result = viewer.edlRenderer.depthTexSampler.sample(viewport, mouse)//add
  47295. if(result != 'unsupport')return result
  47296. */
  47297. if(!pointclouds || pointclouds.length == 0)return
  47298. //console.log('getMousePointCloudIntersection')
  47299. let renderer = viewer.renderer;
  47300. if(viewport){ //转换到类似整个画面时
  47301. /*let mouseInViewport = Utils.convertNDCToScreenPosition(pointer, null, viewport.resolution.x, viewport.resolution.y)
  47302. pickParams.x = mouseInViewport.x //mouse.x / viewport.width;
  47303. pickParams.y = mouseInViewport.y //renderer.domElement.clientHeight - mouse.y / viewport.height; */
  47304. pickParams.x = mouse.x;
  47305. pickParams.y = viewport.resolution.y - mouse.y;
  47306. }else {
  47307. pickParams.x = mouse.x;
  47308. pickParams.y = renderer.domElement.clientHeight - mouse.y;
  47309. }
  47310. //console.log('getMousePointCloudIntersection')
  47311. /* if(!raycaster){
  47312. raycaster = new THREE.Raycaster();
  47313. raycaster.setFromCamera(pointer, camera);
  47314. } */
  47315. let raycaster = new Raycaster();
  47316. raycaster.setFromCamera(pointer, camera);
  47317. let ray = raycaster.ray;
  47318. let selectedPointcloud = null;
  47319. let closestDistance = Infinity;
  47320. let closestIntersection = null;
  47321. let closestPoint = null;
  47322. //-----------add--------------------
  47323. let old_clipBoxes_in = new Map();
  47324. let old_clipBoxes_out = new Map();
  47325. let old_bigClipInBox = new Map();
  47326. let old_highlightBoxes = new Map();
  47327. //bigClipInBox 最好也写下
  47328. let density;
  47329. let sizeType;
  47330. let size = new Map();
  47331. let visiMap = new Map();
  47332. let needsUpdate = false;
  47333. if(pickParams.isMeasuring || Potree.settings.displayMode == 'showPanos') { //(无深度图) 测量或全景模式提高精准度,因为漫游的
  47334. density = Potree.settings.pointDensity;
  47335. Potree.settings.pointDensity = 'magnifier';
  47336. pointclouds.forEach(e=>{//因为全景模式的pointSizeType是fixed所以要还原下
  47337. visiMap.set(e,e.visible);
  47338. e.visible = Potree.Utils.getObjVisiByReason(e, 'datasetSelection'); //先将隐藏的点云显示
  47339. if(!e.visible)return
  47340. size.set(e, e.temp.pointSize);
  47341. sizeType = e.material.pointSizeType;
  47342. e.material.pointSizeType = Potree.config.material.pointSizeType;
  47343. e.changePointSize(Potree.config.material.realPointSize*2, true);//更改点云大小到能铺满为止,否则容易识别不到
  47344. });
  47345. needsUpdate = true;
  47346. }else {
  47347. if(viewer.viewports.filter(e=>!e.noPointcloud && e.active).length>1 || pickParams.cameraChanged){//在pick时相机和渲染时不一样的话
  47348. viewport.beforeRender && viewport.beforeRender();
  47349. needsUpdate = true; //不updatePointClouds的话hover久了会不准 因node是错的
  47350. //但依旧需要camera真的移动到那个位置才能加载出点云
  47351. }
  47352. }
  47353. if(!pickParams.pickClipped){// 无视clipBoxes
  47354. for(let pointcloud of pointclouds){
  47355. old_clipBoxes_in.set(pointcloud, pointcloud.clipBoxes_in);
  47356. old_clipBoxes_out.set(pointcloud, pointcloud.clipBoxes_in);
  47357. old_bigClipInBox.set(pointcloud, pointcloud.bigClipInBox);
  47358. old_highlightBoxes.set(pointcloud, pointcloud.highlightBoxes);
  47359. pointcloud.material.setClipBoxes(null, [],[],[]);
  47360. }
  47361. needsUpdate = true;
  47362. }
  47363. if(needsUpdate){
  47364. Potree.updatePointClouds(pointclouds, camera, viewport.resolution ); //最好只更新pick的范围的resolution
  47365. }
  47366. //------------------------------------------------
  47367. let allPointclouds = [];
  47368. for(let pointcloud of pointclouds){
  47369. let point = pointcloud.pick(viewer, viewport, camera, ray, pickParams );
  47370. if(!point){
  47371. continue;
  47372. }
  47373. allPointclouds.push(pointcloud);
  47374. let distance = camera.position.distanceTo(point.position);
  47375. if (distance < closestDistance) {
  47376. closestDistance = distance;
  47377. selectedPointcloud = pointcloud;
  47378. closestIntersection = point.position;
  47379. closestPoint = point;
  47380. }
  47381. }
  47382. //恢复
  47383. if(pickParams.isMeasuring || Potree.settings.displayMode == 'showPanos'){
  47384. Potree.settings.pointDensity = density;
  47385. pointclouds.forEach(e=>{
  47386. if(e.visible){
  47387. e.material.pointSizeType = sizeType;
  47388. e.changePointSize(size.get(e));
  47389. }
  47390. e.visible = visiMap.get(e);
  47391. });
  47392. }else {
  47393. /* if(viewer.viewports.filter(e=>!e.noPointcloud).length>1){
  47394. viewport.afterRender && viewport.afterRender()
  47395. } */
  47396. }
  47397. if(!pickParams.pickClipped){//add
  47398. for(let pointcloud of pointclouds){
  47399. pointcloud.material.setClipBoxes(old_bigClipInBox.get(pointcloud), old_clipBoxes_in.get(pointcloud), old_clipBoxes_out.get(pointcloud), old_highlightBoxes.get(pointcloud));
  47400. }
  47401. }
  47402. if (selectedPointcloud) {
  47403. return {
  47404. location: closestIntersection,
  47405. distance: closestDistance,
  47406. pointcloud: selectedPointcloud,
  47407. point: closestPoint,
  47408. pointclouds: allPointclouds, //add
  47409. normal: new Vector3().fromArray(closestPoint.normal )//add
  47410. };
  47411. } else {
  47412. return null;
  47413. }
  47414. };
  47415. Utils.pixelsArrayToDataUrl = function(pixels, width, height, compressRatio = 0.7) {
  47416. let canvas = document.createElement('canvas');
  47417. canvas.width = width;
  47418. canvas.height = height;
  47419. let context = canvas.getContext('2d');
  47420. pixels = new pixels.constructor(pixels);
  47421. /* for (let i = 0; i < pixels.length; i++) {
  47422. pixels[i * 4 + 3] = 255;
  47423. } */
  47424. // flip vertically
  47425. let bytesPerLine = width * 4;
  47426. for(let i = 0; i < parseInt(height / 2); i++){
  47427. let j = height - i - 1;
  47428. let lineI = pixels.slice(i * bytesPerLine, i * bytesPerLine + bytesPerLine);
  47429. let lineJ = pixels.slice(j * bytesPerLine, j * bytesPerLine + bytesPerLine);
  47430. pixels.set(lineJ, i * bytesPerLine);
  47431. pixels.set(lineI, j * bytesPerLine);
  47432. }
  47433. let imageData = context.createImageData(width, height);
  47434. imageData.data.set(pixels);
  47435. context.putImageData(imageData, 0, 0);
  47436. let dataURL = canvas.toDataURL(compressRatio);
  47437. return dataURL;
  47438. };
  47439. Utils.renderTargetToDataUrl = function(renderTarget, width, height, renderer, compressRatio = 0.7){
  47440. let pixelCount = width * height;
  47441. let buffer = new Uint8Array(4 * pixelCount);
  47442. renderer.readRenderTargetPixels(renderTarget, 0, 0, width, height, buffer);
  47443. var dataUrl = Utils.pixelsArrayToDataUrl(buffer, width, height, compressRatio);
  47444. return dataUrl
  47445. };
  47446. Utils.mouseToRay = function(pointer, camera ){
  47447. let vector = new Vector3(pointer.x, pointer.y, 1);
  47448. let origin = new Vector3(pointer.x, pointer.y, -1); //不能用camera.position,在orbitCamera时不准
  47449. vector.unproject(camera);
  47450. origin.unproject(camera);
  47451. let direction = new Vector3().subVectors(vector, origin).normalize();
  47452. let ray = new Ray(origin, direction);
  47453. return ray;
  47454. };
  47455. Utils.getPos2d = function(point, camera, dom, viewport){//获取一个三维坐标对应屏幕中的二维坐标
  47456. var pos;
  47457. if(math.closeTo(camera.position, point, 1e-5) ){ //和相机位置重合时显示会四处飘,看是要改成一直显示中间还是隐藏?
  47458. pos = new Vector3(0,0,1.5); //1.5是为了不可见
  47459. }else {
  47460. pos = point.clone().project(camera); //比之前hotspot的计算方式写得简单 project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
  47461. }
  47462. var x,y,left,top;
  47463. x = (pos.x + 1) / 2 * dom.clientWidth * viewport.width;
  47464. y = (1 - (pos.y + 1) / 2) * dom.clientHeight * viewport.height;
  47465. left = viewport.left * dom.clientWidth;
  47466. top = (1- viewport.bottom - viewport.height) * dom.clientHeight;
  47467. var inSight = pos.x <= 1 && pos.x >= -1 //是否在屏幕中
  47468. && pos.x <= 1 && pos.y >= -1;
  47469. return {
  47470. pos: new Vector2(left+x,top+y) ,// 屏幕像素坐标
  47471. vector: pos, //(范围 -1 ~ 1)
  47472. trueSide : pos.z<1, //trueSide为false时,即使在屏幕范围内可见,也是反方向的另一个不可以被渲染的点 参见Tag.update
  47473. inSight : inSight, //在屏幕范围内可见,
  47474. posInViewport: new Vector2(x,y)
  47475. };
  47476. };
  47477. Utils.screenPass = new function () {
  47478. this.screenScene = new Scene();
  47479. this.screenQuad = new Mesh(new PlaneBufferGeometry(2, 2, 1));
  47480. this.screenQuad.material.depthTest = true;
  47481. this.screenQuad.material.depthWrite = true;
  47482. this.screenQuad.material.transparent = true;
  47483. this.screenScene.add(this.screenQuad);
  47484. this.camera = new Camera();
  47485. this.render = function (renderer, material, target, composer) {
  47486. this.screenQuad.material = material;
  47487. if (typeof target === 'undefined') {
  47488. (composer || renderer).render(this.screenScene, this.camera);
  47489. } else {
  47490. let oldTarget = renderer.getRenderTarget();
  47491. renderer.setRenderTarget(target);
  47492. //renderer.clear(); //有时候不能clear,如renderBG后再
  47493. (composer || renderer).render(this.screenScene, this.camera);
  47494. renderer.setRenderTarget(oldTarget);
  47495. }
  47496. };
  47497. }();
  47498. //add
  47499. Utils.computePointcloudsBound = function(pointclouds){
  47500. var boundingBox = new Box3();
  47501. pointclouds.forEach(pointcloud=>{
  47502. pointcloud.updateBound();
  47503. boundingBox.union(pointcloud.bound2);
  47504. });
  47505. var boundSize = boundingBox.getSize(new Vector3);
  47506. var center = boundingBox.getCenter(new Vector3);
  47507. return {boundSize, center, boundingBox}
  47508. };
  47509. Utils.convertScreenPositionToNDC = function(pointer, mouse, width, height) {
  47510. return pointer = pointer || new Vector2,
  47511. pointer.x = mouse.x / width * 2 - 1,
  47512. pointer.y = 2 * -(mouse.y / height) + 1,
  47513. pointer
  47514. };
  47515. Utils.convertNDCToScreenPosition = function(pointer, mouse, width, height) {
  47516. return mouse = mouse || new Vector2,
  47517. mouse.x = Math.round((pointer.x + 1 ) / 2 * width),
  47518. mouse.y = Math.round(-(pointer.y - 1 ) / 2 * height),
  47519. mouse
  47520. };
  47521. Utils.getOrthoCameraMoveVec = function(pointerDelta, camera ){//获取当camera为Ortho型时 屏幕点1 到 屏幕点2 的三维距离
  47522. let cameraViewWidth = camera.right / camera.zoom;
  47523. let cameraViewHeight = camera.top / camera.zoom;
  47524. let moveVec = new Vector3;
  47525. moveVec.set( pointerDelta.x * cameraViewWidth , pointerDelta.y * cameraViewHeight , 0).applyQuaternion(camera.quaternion);
  47526. return moveVec
  47527. };
  47528. Utils.VectorFactory = {
  47529. fromArray : function(t) {
  47530. if (t) {
  47531. if (t.length < 2 || t.length > 3)
  47532. console.error("Wrong number of ordinates for a point!");
  47533. return 3 === t.length ? (new Vector3).fromArray(t) : (new Vector2).fromArray(t)
  47534. }
  47535. },
  47536. fromArray3 : function(t) {
  47537. if (t) {
  47538. if (3 !== t.length)
  47539. console.error("Wrong number of ordinates for a point!");
  47540. return (new Vector3).fromArray(t)
  47541. }
  47542. },
  47543. fromArray2 : function(t) {
  47544. if (t) {
  47545. if (2 !== t.length)
  47546. console.error("Wrong number of ordinates for a point!");
  47547. return (new Vector2).fromArray(t)
  47548. }
  47549. },
  47550. toString : function(t) {
  47551. return t.x.toFixed(8) + "," + t.y.toFixed(8) + "," + t.z.toFixed(3)
  47552. }
  47553. };
  47554. Utils.QuaternionFactory = {
  47555. rot90 : (new Quaternion).setFromAxisAngle(new Vector3(0,0,1), MathUtils$1.degToRad(-90)),
  47556. fromArray : function(t) {
  47557. if (t) {
  47558. if (4 !== t.length)
  47559. console.error("Wrong number of ordinates for a quaternion!");
  47560. return new Quaternion(t[1],t[2],t[3],t[0]).multiply(this.rot90)
  47561. }
  47562. }
  47563. ,
  47564. toArray : function(t) {
  47565. if (t) {
  47566. var e = t.clone().multiply(a).toArray();
  47567. return [e[3], e[0], e[1], e[2]]
  47568. }
  47569. }
  47570. ,
  47571. fromLonLat : function(t) {
  47572. if (t)
  47573. return (new Quaternion).setFromEuler(new Euler(t.lon,t.lat,0))
  47574. }
  47575. ,
  47576. toLonLat : function(t) {
  47577. if (t) {
  47578. var e = (new Euler).setFromQuaternion(t);
  47579. return {
  47580. lon: e.x,
  47581. lat: e.y
  47582. }
  47583. }
  47584. }
  47585. };
  47586. Utils.datasetPosTransform = function(o={}){
  47587. let pointcloud = o.pointcloud || viewer.scene.pointclouds.find(e=>e.dataset_id == o.datasetId);
  47588. let tranMatrix;
  47589. if(pointcloud){
  47590. if(Potree.settings.editType == 'merge'){
  47591. tranMatrix = o.fromDataset ? pointcloud.matrixWorld : new Matrix4().copy(pointcloud.matrixWorld).invert();
  47592. }else {
  47593. tranMatrix = o.fromDataset ? pointcloud.transformMatrix : pointcloud.transformInvMatrix;
  47594. }
  47595. }else {
  47596. if(Potree.settings.intersectOnObjs){
  47597. let object = o.object || viewer.objs.children.find(e=>e.dataset_id == o.datasetId);
  47598. if(object){
  47599. tranMatrix = o.fromDataset ? object.matrixWorld : new Matrix4().copy(object.matrixWorld).invert();
  47600. }
  47601. }
  47602. }
  47603. if(tranMatrix){
  47604. return (new Vector3).copy(o.position).applyMatrix4(tranMatrix)
  47605. }else {
  47606. if(o.datasetId != void 0){
  47607. console.error(`datasetPosTransform找不到datasetId为${o.datasetId}的数据集或模型,请检查数据, 模型未创建或删除`);
  47608. //很可能是旧的热点,需要删除
  47609. }
  47610. }
  47611. };
  47612. Utils.datasetRotTransform = function(o={}){
  47613. let pointcloud = o.pointcloud || viewer.scene.pointclouds.find(e=>e.dataset_id == o.datasetId);
  47614. if(pointcloud){
  47615. var matrix, newMatrix, result;
  47616. if(o.rotation){
  47617. matrix = new Matrix4().makeRotationFromEuler(o.rotation);
  47618. }else if(o.quaternion){
  47619. matrix = new Matrix4().makeRotationFromQuaternion(o.quaternion);
  47620. }else if(o.matrix){
  47621. matrix = o.matrix.clone();
  47622. }else {
  47623. return
  47624. }
  47625. let rotateMatrix = o.fromDataset ? pointcloud.rotateMatrix : pointcloud.rotateInvMatrix;
  47626. newMatrix = new Matrix4().multiplyMatrices(rotateMatrix, matrix );
  47627. if(o.getRotation){
  47628. result = new Euler().setFromRotationMatrix(newMatrix);
  47629. }else if(o.getQuaternion){
  47630. result = new Quaternion().setFromRotationMatrix(newMatrix);
  47631. }else if(o.getMatrix){
  47632. result = newMatrix;
  47633. }
  47634. return result
  47635. }
  47636. };
  47637. Utils.isInsideFrustum = function(bounding, camera){// bounding是否在视野范围内有可见部分(视野就是一个锥状box)
  47638. let frustumMatrix = new Matrix4;
  47639. frustumMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
  47640. let frustum = new Frustum();
  47641. frustum.setFromProjectionMatrix(frustumMatrix);
  47642. if(bounding instanceof Sphere){
  47643. return frustum.intersectsSphere(bounding)
  47644. }else {
  47645. return frustum.intersectsBox(bounding)
  47646. }
  47647. };
  47648. Utils.isIntersectBox = function(object, boxMatrix){//object是否有在box中的部分。 object可以是点或者bounding, box原为1*1*1,但可能形变
  47649. //let frustum = new THREE.Frustum();
  47650. //frustum.setFromProjectionMatrix(boxMatrixInverse) --错
  47651. let px = new Vector3(+0.5, 0, 0).applyMatrix4(boxMatrix);
  47652. let nx = new Vector3(-0.5, 0, 0).applyMatrix4(boxMatrix);
  47653. let py = new Vector3(0, +0.5, 0).applyMatrix4(boxMatrix);
  47654. let ny = new Vector3(0, -0.5, 0).applyMatrix4(boxMatrix);
  47655. let pz = new Vector3(0, 0, +0.5).applyMatrix4(boxMatrix);
  47656. let nz = new Vector3(0, 0, -0.5).applyMatrix4(boxMatrix);
  47657. let pxN = new Vector3().subVectors(nx, px).normalize();
  47658. let nxN = pxN.clone().multiplyScalar(-1);
  47659. let pyN = new Vector3().subVectors(ny, py).normalize();
  47660. let nyN = pyN.clone().multiplyScalar(-1);
  47661. let pzN = new Vector3().subVectors(nz, pz).normalize();
  47662. let nzN = pzN.clone().multiplyScalar(-1);
  47663. let pxPlane = new Plane().setFromNormalAndCoplanarPoint(pxN, px);
  47664. let nxPlane = new Plane().setFromNormalAndCoplanarPoint(nxN, nx);
  47665. let pyPlane = new Plane().setFromNormalAndCoplanarPoint(pyN, py);
  47666. let nyPlane = new Plane().setFromNormalAndCoplanarPoint(nyN, ny);
  47667. let pzPlane = new Plane().setFromNormalAndCoplanarPoint(pzN, pz);
  47668. let nzPlane = new Plane().setFromNormalAndCoplanarPoint(nzN, nz);
  47669. let frustum = new Frustum(pxPlane, nxPlane, pyPlane, nyPlane, pzPlane, nzPlane);
  47670. if(object instanceof Box3){
  47671. var boxBound = new Box3(
  47672. new Vector3(-0.5,-0.5,-0.5), new Vector3(0.5,0.5,0.5),
  47673. ).applyMatrix4(boxMatrix); //large boundingbox
  47674. if(!object.intersectsBox(boxBound))return
  47675. return frustum.intersectsBox(object) //根据该函数, 若存在某个plane在box上的对应点都在plane背面,则不相交. 可得知在box构成的frustum倾斜时不准确,不相交也判断为相交,甚至不如bound相交准确。所以前面加步骤排除下,但仍不完全准确。(可在裁剪中将box放置到数据集上方旋转下校验)
  47676. }else if(object instanceof Array){//点合集, 只能粗略计算下
  47677. let sphere = new Sphere();
  47678. sphere.setFromPoints(object);
  47679. return this.isIntersectBox(sphere, boxMatrix)
  47680. }else if(object instanceof Sphere){
  47681. return frustum.intersectsSphere(object)
  47682. }else if(object instanceof Vector3){
  47683. return frustum.containsPoint(object)
  47684. }else if(object instanceof Matrix4){//第一个参数如果和第二个参数一样都是box的worldMatrix
  47685. }
  47686. /* containsPoint: ƒ containsPoint( point )
  47687. intersectsBox: ƒ intersectsBox( box )
  47688. intersectsObject: ƒ intersectsObject( object )//geo
  47689. intersectsSphere: ƒ intersectsSphere( sphere )
  47690. intersectsSprite: ƒ intersectsSprite( sprite )
  47691. */
  47692. };
  47693. Utils.getIntersect = function (camera, meshes, pointer, raycaster) {
  47694. //获取鼠标和meshes交点
  47695. if(!raycaster){//getMouseIntersect
  47696. camera.updateMatrixWorld();
  47697. raycaster = new Raycaster();
  47698. var origin = new Vector3(pointer.x, pointer.y, -1).unproject(camera),
  47699. end = new Vector3(pointer.x, pointer.y, 1).unproject(camera);
  47700. var dir = end.sub(origin).normalize();
  47701. raycaster.set(origin, dir);
  47702. }
  47703. meshes.forEach(e=>{
  47704. raycaster.layers.enable(math.getBaseLog(2,e.layers.mask));
  47705. });
  47706. var n = raycaster.intersectObjects(meshes);
  47707. if (0 === n.length) return null
  47708. return n[0]
  47709. };
  47710. Utils.addOrRemoveDefine = function(material, defineName, type, value=''){
  47711. let defines = material.defines;
  47712. if(type == 'add'){
  47713. if(defines[defineName] != void 0 && defines[defineName] == value)return
  47714. defines[defineName] = value;
  47715. }else {
  47716. if(defines[defineName] != void 0)return;
  47717. delete defines[defineName];
  47718. }
  47719. material.needsUpdate = true;
  47720. };
  47721. Utils.makeTexDontResize = function(map){//避免贴图因非2的次方而缩小。小心使用
  47722. if(!map || !map.image){
  47723. return console.log('!map || !map.image', map, map&&map.image)
  47724. }
  47725. if(MathUtils$1.isPowerOfTwo(map.image.width ) && MathUtils$1.isPowerOfTwo(map.image.height ))return
  47726. map.wrapS = map.wrapT = ClampToEdgeWrapping; //原默认 RepeatWrapping
  47727. map.minFilter = LinearFilter; // or THREE.NearestFilter 原默认 LinearMipmapLinearFilter
  47728. map.needsUpdate = true;
  47729. };
  47730. Utils.updateVisible = function(object, reason, ifShow, level=0, type){//当所有加入的条件都不为false时才显示. reason='force'一般是强制、临时的
  47731. if(!object.unvisibleReasons) object.unvisibleReasons = []; //如果length>0代表不可见
  47732. if(!object.visibleReasons) object.visibleReasons = []; //在同级时,优先可见
  47733. var update = function(){
  47734. //先按从高到低的level排列
  47735. object.unvisibleReasons = object.unvisibleReasons.sort((a,b)=>b.level-a.level);
  47736. object.visibleReasons = object.visibleReasons.sort((a,b)=>b.level-a.level);
  47737. var maxVisiLevel = object.visibleReasons[0] ? object.visibleReasons[0].level : -1;
  47738. var maxunVisiLevel = object.unvisibleReasons[0] ? object.unvisibleReasons[0].level : -1;
  47739. var shouldVisi = maxVisiLevel >= maxunVisiLevel;
  47740. var visiBefore = object.visible;
  47741. if(visiBefore != shouldVisi){
  47742. object.visible = shouldVisi;
  47743. object.dispatchEvent({
  47744. type: 'isVisible',
  47745. visible: shouldVisi,
  47746. reason,
  47747. });
  47748. }
  47749. };
  47750. if(ifShow){
  47751. var index = object.unvisibleReasons.findIndex(e=>e.reason == reason);
  47752. if(index > -1){
  47753. type = 'cancel';
  47754. object.unvisibleReasons.splice(index, 1);
  47755. }
  47756. if(type == 'add' ){
  47757. if(!object.visibleReasons.some(e=>e.reason == reason)){
  47758. object.visibleReasons.push({reason,level});
  47759. }
  47760. }
  47761. }else {
  47762. var index = object.visibleReasons.findIndex(e=>e.reason == reason);
  47763. if(index > -1){
  47764. type = 'cancel';
  47765. object.visibleReasons.splice(index, 1);
  47766. }
  47767. if(type != 'cancel' ){
  47768. if(!object.unvisibleReasons.some(e=>e.reason == reason)){
  47769. object.unvisibleReasons.push({reason,level});
  47770. }
  47771. }
  47772. }
  47773. update();
  47774. };
  47775. /*
  47776. 复杂案例: 如果物体默认隐藏, 当符合任何一个其他条件时可见,则可:
  47777. Potree.Utils.updateVisible(this, "default", false, 0 ) //默认隐藏
  47778. Potree.Utils.updateVisible(this, 条件名, ifShow, 1, ifShow?'add':'cancel' ) //其他的条件
  47779. */
  47780. Utils.getObjVisiByReason = function(object,reason){//获取在某条件下是否可见. 注: 用户在数据集选择可不可见为"datasetSelection"
  47781. if(object.visible)return true
  47782. else {
  47783. return !object.unvisibleReasons || !object.unvisibleReasons.some(e=>e.reason == reason)
  47784. }
  47785. };
  47786. Utils.setCameraLayers = function(camera, enableLayers, extraEnableLayers=[]){//add
  47787. camera.layers.disableAll();
  47788. enableLayers.concat(extraEnableLayers).forEach(e=>{
  47789. let layer = Potree.config.renderLayers[e];
  47790. if(layer == void 0){
  47791. console.error('setCameraLayer没找到layer!');
  47792. return
  47793. }
  47794. camera.layers.enable(layer);
  47795. });
  47796. };
  47797. Utils.setObjectLayers = function(object, layerName){//add
  47798. let layer = Potree.config.renderLayers[layerName];
  47799. if(layer == void 0){
  47800. console.error('setCameraLayer没找到layer!');
  47801. return
  47802. }
  47803. object.traverse(e=>{
  47804. e.layers.set(layer);
  47805. });
  47806. };
  47807. BinaryLoader.prototype.load = function(node, callback){//解析点云
  47808. if (node.loaded) {
  47809. return;
  47810. }
  47811. let url = node.getURL();
  47812. if (this.version.equalOrHigher('1.4')) {
  47813. url += '.bin';
  47814. }
  47815. //url += '?m='+node.pcoGeometry.timeStamp //add
  47816. let startLoad = (url)=>{
  47817. let xhr = XHRFactory.createXMLHttpRequest();
  47818. xhr.open('GET', url, true);
  47819. xhr.responseType = 'arraybuffer';
  47820. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  47821. xhr.onreadystatechange = () => {
  47822. if (xhr.readyState === 4) {
  47823. if((xhr.status === 200 || xhr.status === 0) && xhr.response !== null){
  47824. let buffer = xhr.response;
  47825. this.parse(node, buffer, callback);
  47826. } else {
  47827. //console.error(`Failed to load file! HTTP status: ${xhr.status}, file: ${url}`);
  47828. throw new Error(`Failed to load file! HTTP status: ${xhr.status}, file: ${url}`);
  47829. }
  47830. }
  47831. };
  47832. try {
  47833. xhr.send(null);
  47834. } catch (e) {
  47835. console.log('fehler beim laden der punktwolke: ' + e);
  47836. }
  47837. };
  47838. Potree.getRealUrl(url, startLoad);
  47839. };
  47840. PointAttribute.RGBA_PACKED = new PointAttribute("rgba", PointAttributeTypes.DATA_TYPE_INT8, 4);
  47841. PointAttribute.COLOR_PACKED = PointAttribute.RGBA_PACKED;
  47842. PointAttribute.INTENSITY = new PointAttribute("intensity", PointAttributeTypes.DATA_TYPE_UINT16, 1);
  47843. PointAttribute.CLASSIFICATION = new PointAttribute("classification", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  47844. PointAttribute.GPS_TIME = new PointAttribute("gps-time", PointAttributeTypes.DATA_TYPE_DOUBLE, 1);
  47845. ProfileWindow.prototype.initTHREE = function(){
  47846. this.renderer = new WebGLRenderer({alpha: true, premultipliedAlpha: false});
  47847. this.renderer.setClearColor(0x000000, 0);
  47848. this.renderer.setSize(10, 10);
  47849. this.renderer.autoClear = false;
  47850. this.renderArea.append($(this.renderer.domElement));
  47851. this.renderer.domElement.tabIndex = '2222';
  47852. $(this.renderer.domElement).css('width', '100%');
  47853. $(this.renderer.domElement).css('height', '100%');
  47854. {
  47855. let gl = this.renderer.getContext();
  47856. if(gl.createVertexArray == null){
  47857. let extVAO = gl.getExtension('OES_vertex_array_object');
  47858. if(!extVAO){
  47859. throw new Error("OES_vertex_array_object extension not supported");
  47860. }
  47861. gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO);
  47862. gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO);
  47863. }
  47864. }
  47865. this.camera = new OrthographicCamera(-1000, 1000, 1000, -1000, -1000, 1000);
  47866. this.camera.up.set(0, 0, 1);
  47867. this.camera.rotation.order = "ZXY";
  47868. this.camera.rotation.x = Math.PI / 2.0;
  47869. this.scene = new Scene();
  47870. this.profileScene = new Scene();
  47871. let sg = new SphereGeometry(1, 16, 16);
  47872. let sm = new MeshNormalMaterial();
  47873. this.pickSphere = new Mesh(sg, sm);
  47874. this.scene.add(this.pickSphere);
  47875. this.viewerPickSphere = new Mesh(sg, sm);
  47876. };
  47877. //Potree_update_visibility
  47878. Potree.updatePointClouds = function(pointclouds,camera, areaSize ){
  47879. viewer.addTimeMark('updateClouds','start');
  47880. for (let pointcloud of pointclouds) {
  47881. let start = performance.now();
  47882. for (let profileRequest of pointcloud.profileRequests) {
  47883. profileRequest.update();
  47884. let duration = performance.now() - start;
  47885. if(duration > 5){
  47886. break;
  47887. }
  47888. }
  47889. let duration = performance.now() - start;
  47890. }
  47891. let result = Potree.updateVisibility(pointclouds, camera, areaSize );
  47892. for (let pointcloud of pointclouds) {
  47893. //pointcloud.updateMaterial(pointcloud.material, pointcloud.visibleNodes, camera, renderer);//转移到渲染时
  47894. pointcloud.updateVisibleBounds();
  47895. }
  47896. Potree.lru.freeMemory();//即Potree.lru 能看到所有在加载的node
  47897. viewer.addTimeMark('updateClouds','end');
  47898. return result;
  47899. };
  47900. Potree.updateVisibilityStructures = function(pointclouds, camera, areaSize) {
  47901. let frustums = {};
  47902. let camObjPositions = {};
  47903. let camObjDirs = {}; //add
  47904. let priorityQueue = new BinaryHeap(function (x) { return 1 / x.weight; });//二叉堆。
  47905. viewer.addTimeMark('visiStructure','start');
  47906. //camera.updateMatrixWorld();
  47907. let viewI = camera.matrixWorldInverse;
  47908. let proj = camera.projectionMatrix;
  47909. let view = camera.matrixWorld;
  47910. let projViewI = new Matrix4().multiply(proj).multiply(viewI);
  47911. /* let list = pointclouds // stopWhenAllUsed = !viewer.lastFrameChanged
  47912. let min = 5, max = Math.max(20 , Math.round(list.length / 10 ))
  47913. let result = Common.batchHandling.getSlice('pcGetFrustum', list, { min,max, durBound1: 3, durBound2: 10} ) //iphonex稳定后大概在7-10。
  47914. */
  47915. for (let i = 0; i < pointclouds.length; i++) {
  47916. let pointcloud = pointclouds[i];
  47917. if (!pointcloud.initialized()) {
  47918. continue;
  47919. }
  47920. /* let info = history.get(pointcloud)
  47921. if() */
  47922. pointcloud.numVisibleNodes = 0;
  47923. pointcloud.numVisiblePoints = 0;
  47924. pointcloud.deepestVisibleLevel = 0;
  47925. pointcloud.visibleNodes = [];
  47926. pointcloud.visibleGeometry = [];
  47927. // 因漫游模式而隐藏的话 依旧需要加入visibleNodes,因为pick需要
  47928. /* if (pointcloud.visible && pointcloud.root !== null) {
  47929. priorityQueue.push({pointcloud: i, node: pointcloud.root, weight: Number.MAX_VALUE});
  47930. } */
  47931. if (pointcloud.visible || /* !pointcloud.hasDepthTex && */ pointcloud.unvisibleReasons && pointcloud.unvisibleReasons.length == 1 && pointcloud.unvisibleReasons[0].reason == 'displayMode' && pointcloud.root !== null) {//改 visible ->
  47932. priorityQueue.push({pointcloud: i, node: pointcloud.root, weight: Number.MAX_VALUE});
  47933. }else {
  47934. continue
  47935. }
  47936. // frustum in object space
  47937. let frustum = new Frustum();
  47938. let world = pointcloud.matrixWorld;
  47939. // use close near plane for frustum intersection
  47940. /* let frustumCam = camera.clone();
  47941. frustumCam.zoom = camera.zoom //add
  47942. frustumCam.near = Math.min(camera.near, 0.1);
  47943. frustumCam.updateProjectionMatrix(); */ //----没用到frustumCam,删了
  47944. let fm = new Matrix4().multiply(projViewI).multiply(world);
  47945. frustum.setFromProjectionMatrix(fm);
  47946. frustums[i] = frustum; //frustums.push(frustum);
  47947. // camera position in object space
  47948. let worldI = pointcloud.matrixWorldInverse;
  47949. let camMatrixObject = new Matrix4().multiply(worldI).multiply(view);//假设点云无变换的话,相机相对于点云的变换矩阵
  47950. let camObjPos = new Vector3().setFromMatrixPosition(camMatrixObject);
  47951. camObjPositions[i] = camObjPos;//camObjPositions.push(camObjPos);
  47952. let quaternion = new Quaternion().setFromRotationMatrix(camMatrixObject);
  47953. let camDir = (new Vector3(0,0,-1)).applyQuaternion(quaternion);
  47954. camObjDirs[i] = camDir;
  47955. // hide all previously visible nodes
  47956. // if(pointcloud.root instanceof PointCloudOctreeNode){
  47957. // pointcloud.hideDescendants(pointcloud.root.sceneNode);
  47958. // }
  47959. if (pointcloud.root.isTreeNode()) {
  47960. pointcloud.hideDescendants(pointcloud.root.sceneNode);
  47961. }
  47962. for (let j = 0; j < pointcloud.boundingBoxNodes.length; j++) {
  47963. pointcloud.boundingBoxNodes[j].visible = false;
  47964. }
  47965. }
  47966. viewer.addTimeMark('visiStructure','end');
  47967. return {
  47968. 'frustums': frustums,
  47969. 'camObjPositions': camObjPositions,
  47970. 'priorityQueue': priorityQueue,
  47971. camObjDirs
  47972. };
  47973. };
  47974. Potree.updateVisibility = function(pointclouds, camera, areaSize){
  47975. let numVisibleNodes = 0;
  47976. let numVisiblePoints = 0;
  47977. let numVisiblePointsInPointclouds = new Map(pointclouds.map(pc => [pc, 0]));
  47978. let visibleNodes = [];
  47979. let visibleGeometry = [];
  47980. let unloadedGeometry = [];
  47981. let lowestSpacing = Infinity;
  47982. // calculate object space frustum and cam pos and setup priority queue
  47983. let s = Potree.updateVisibilityStructures(pointclouds, camera, areaSize);//得到相机可见范围
  47984. let frustums = s.frustums;
  47985. let camObjPositions = s.camObjPositions;
  47986. let priorityQueue = s.priorityQueue;
  47987. let camObjDirs = s.camObjDirs;
  47988. let loadedToGPUThisFrame = 0;
  47989. let domWidth = areaSize.x; //renderer.domElement.clientWidth;
  47990. let domHeight = areaSize.y;//renderer.domElement.clientHeight;
  47991. let fov = (camera.fov * Math.PI) / 180;
  47992. let slope = Math.tan(fov / 2);
  47993. let projFactor0 = (0.5 * domHeight) / slope ;
  47994. // check if pointcloud has been transformed
  47995. // some code will only be executed if changes have been detected
  47996. if(!Potree._pointcloudTransformVersion){
  47997. Potree._pointcloudTransformVersion = new Map();
  47998. }
  47999. let pointcloudTransformVersion = Potree._pointcloudTransformVersion;
  48000. for(let pointcloud of pointclouds){
  48001. if(/* pointcloud.hasDepthTex ? !pointcloud.visible : */ !Potree.Utils.getObjVisiByReason(pointcloud, 'datasetSelection')){//改 visible -> 这一版的深度图不准,就只用在贴图里,pick时需要点云,所以要一直有, 否则但pick时显示的话visibleNodes只能加载出一点点
  48002. continue;
  48003. }
  48004. //if(!pointcloud.visible) continue
  48005. pointcloud.updateMatrixWorld();
  48006. if(!pointcloudTransformVersion.has(pointcloud)){
  48007. pointcloudTransformVersion.set(pointcloud, {number: 0, transform: pointcloud.matrixWorld.clone()});
  48008. }else {
  48009. let version = pointcloudTransformVersion.get(pointcloud);
  48010. if(!version.transform.equals(pointcloud.matrixWorld)){
  48011. version.number++;
  48012. version.transform.copy(pointcloud.matrixWorld);
  48013. pointcloud.dispatchEvent({
  48014. type: "transformation_changed",
  48015. target: pointcloud
  48016. });
  48017. }
  48018. }
  48019. }
  48020. while (priorityQueue.size() > 0) {
  48021. let element = priorityQueue.pop(); //取出权重最大的一个
  48022. let node = element.node;
  48023. let parent = element.parent;
  48024. let pointcloud = pointclouds[element.pointcloud];
  48025. // { // restrict to certain nodes for debugging
  48026. // let allowedNodes = ["r", "r0", "r4"];
  48027. // if(!allowedNodes.includes(node.name)){
  48028. // continue;
  48029. // }
  48030. // }
  48031. let box = node.getBoundingBox();
  48032. let frustum = frustums[element.pointcloud];
  48033. let camObjPos = camObjPositions[element.pointcloud];
  48034. if(!frustum) continue //add
  48035. let camObjDir = camObjDirs[element.pointcloud];
  48036. let insideFrustum = frustum.intersectsBox(box);
  48037. let maxLevel = pointcloud.maxLevel == void 0 ? Infinity : pointcloud.maxLevel;
  48038. let level = node.getLevel();
  48039. let visible = insideFrustum;
  48040. visible = visible && !(numVisiblePoints + node.getNumPoints() > Potree.pointBudget);
  48041. visible = visible && !(numVisiblePointsInPointclouds.get(pointcloud) + node.getNumPoints() > pointcloud.pointBudget); // pointcloud.pointBudget一直是Infinity
  48042. visible = visible && level <= maxLevel; //< 改为 <=
  48043. //visible = visible || node.getLevel() <= 2;
  48044. let intersectBox = (clipBox)=>{
  48045. let pcWorldInverse = pointcloud.matrixWorld.clone().invert();
  48046. let toPCObject = pcWorldInverse.multiply(clipBox.box.matrixWorld); //box乘上点云逆矩阵
  48047. /* let px = new THREE.Vector3(+0.5, 0, 0).applyMatrix4(pcWorldInverse);
  48048. let nx = new THREE.Vector3(-0.5, 0, 0).applyMatrix4(pcWorldInverse);
  48049. let py = new THREE.Vector3(0, +0.5, 0).applyMatrix4(pcWorldInverse);
  48050. let ny = new THREE.Vector3(0, -0.5, 0).applyMatrix4(pcWorldInverse);
  48051. let pz = new THREE.Vector3(0, 0, +0.5).applyMatrix4(pcWorldInverse);
  48052. let nz = new THREE.Vector3(0, 0, -0.5).applyMatrix4(pcWorldInverse);
  48053. let pxN = new THREE.Vector3().subVectors(nx, px).normalize();
  48054. let nxN = pxN.clone().multiplyScalar(-1);
  48055. let pyN = new THREE.Vector3().subVectors(ny, py).normalize();
  48056. let nyN = pyN.clone().multiplyScalar(-1);
  48057. let pzN = new THREE.Vector3().subVectors(nz, pz).normalize();
  48058. let nzN = pzN.clone().multiplyScalar(-1);
  48059. let pxPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(pxN, px);
  48060. let nxPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(nxN, nx);
  48061. let pyPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(pyN, py);
  48062. let nyPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(nyN, ny);
  48063. let pzPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(pzN, pz);
  48064. let nzPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(nzN, nz);
  48065. //if(window.debugdraw !== undefined && window.debugdraw === true && node.name === "r60"){
  48066. // Potree.utils.debugPlane(viewer.scene.scene, pxPlane, 1, 0xFF0000);
  48067. // Potree.utils.debugPlane(viewer.scene.scene, nxPlane, 1, 0x990000);
  48068. // Potree.utils.debugPlane(viewer.scene.scene, pyPlane, 1, 0x00FF00);
  48069. // Potree.utils.debugPlane(viewer.scene.scene, nyPlane, 1, 0x009900);
  48070. // Potree.utils.debugPlane(viewer.scene.scene, pzPlane, 1, 0x0000FF);
  48071. // Potree.utils.debugPlane(viewer.scene.scene, nzPlane, 1, 0x000099);
  48072. // Potree.utils.debugBox(viewer.scene.scene, box, new THREE.Matrix4(), 0x00FF00);
  48073. // Potree.utils.debugBox(viewer.scene.scene, box, pointcloud.matrixWorld, 0xFF0000);
  48074. // Potree.utils.debugBox(viewer.scene.scene, clipBox.box.boundingBox, clipBox.box.matrixWorld, 0xFF0000);
  48075. // window.debugdraw = false;
  48076. //}
  48077. let frustum = new THREE.Frustum(pxPlane, nxPlane, pyPlane, nyPlane, pzPlane, nzPlane);
  48078. let intersects = frustum.intersectsBox(box); //node的bounding
  48079. return !!intersects */
  48080. return Potree.Utils.isIntersectBox(box, pcWorldInverse)
  48081. };
  48082. //改 总共两种box : 可见和不可见(都是并集)
  48083. let clipBoxes_in = pointcloud.material.clipBoxes_in;
  48084. let clipBoxes_out = pointcloud.material.clipBoxes_out;
  48085. let bigClipInBox = pointcloud.material.bigClipInBox;
  48086. if(visible && bigClipInBox){//不在剪裁下载的框内
  48087. if(!intersectBox(bigClipInBox)){
  48088. visible = false;
  48089. }
  48090. }
  48091. if(visible && clipBoxes_in.length > 0){//当有可见box时,需要在任一可见box内才可见
  48092. let visi = false;
  48093. for(let i = 0, length=clipBoxes_in.length; i < length; i++){
  48094. if(intersectBox(clipBoxes_in[i])){
  48095. visi = true;
  48096. break;
  48097. }
  48098. }
  48099. if(!visi){
  48100. visible = false;
  48101. }
  48102. }
  48103. //outside不做处理。因为node必须完全在clipBox内才能完全隐藏,而这里的intersect只能识别出部分在clipBox内。因而只能说明不在任意一个box内绝对可见,没有意义,这里需要找出不可见的。
  48104. /* if(visible && clipBoxes_out.length > 0){ //当有不可见box时,不在所有不可见box内才可见
  48105. let visi = true;
  48106. for(let i = 0,length=clipBoxes_out.length; i < length; i++){
  48107. if(intersectBox(clipBoxes_out[i])){
  48108. visi = false;
  48109. break;
  48110. }
  48111. }
  48112. if(!visi){
  48113. visible = false
  48114. }
  48115. }
  48116. */
  48117. // visible = ["r", "r0", "r06", "r060"].includes(node.name);
  48118. // visible = ["r"].includes(node.name);
  48119. if (node.spacing) {
  48120. lowestSpacing = Math.min(lowestSpacing, node.spacing);
  48121. } else if (node.geometryNode && node.geometryNode.spacing) {
  48122. lowestSpacing = Math.min(lowestSpacing, node.geometryNode.spacing);
  48123. }
  48124. if (numVisiblePoints + node.getNumPoints() > Potree.pointBudget) {
  48125. break;
  48126. }
  48127. if (!visible) {
  48128. continue;
  48129. }
  48130. // TODO: not used, same as the declaration?
  48131. // numVisibleNodes++;
  48132. numVisiblePoints += node.getNumPoints();
  48133. let numVisiblePointsInPointcloud = numVisiblePointsInPointclouds.get(pointcloud);
  48134. numVisiblePointsInPointclouds.set(pointcloud, numVisiblePointsInPointcloud + node.getNumPoints());
  48135. pointcloud.numVisibleNodes++;
  48136. pointcloud.numVisiblePoints += node.getNumPoints();
  48137. if (node.isGeometryNode() && (!parent || parent.isTreeNode())) {
  48138. if (node.isLoaded() && loadedToGPUThisFrame < 2) {
  48139. node = pointcloud.toTreeNode(node, parent);
  48140. loadedToGPUThisFrame++;
  48141. } else {
  48142. //console.log('unloadedGeometry',node)
  48143. unloadedGeometry.push({pointcloud,node}); //加载点云。虽然还没加载,但也计入了visibleNodes,只是无children,numPoints=0
  48144. visibleGeometry.push(node);
  48145. }
  48146. }
  48147. if (node.isTreeNode()) {
  48148. Potree.lru.touch(node.geometryNode);//在缓存中计入点云
  48149. node.sceneNode.visible = true;
  48150. node.sceneNode.material = pointcloud.material;
  48151. visibleNodes.push(node);
  48152. pointcloud.visibleNodes.push(node);
  48153. if(node._transformVersion === undefined){
  48154. node._transformVersion = -1;
  48155. }
  48156. let transformVersion = pointcloudTransformVersion.get(pointcloud);
  48157. if(node._transformVersion !== transformVersion.number){
  48158. node.sceneNode.updateMatrix();
  48159. //node.sceneNode.matrixWorld.multiplyMatrices(pointcloud.matrixWorld, node.sceneNode.matrix);
  48160. node.sceneNode.matrixWorld.multiplyMatrices(pointcloud.matrixWorld, node.sceneNode.matrix);
  48161. node._transformVersion = transformVersion.number;
  48162. }
  48163. if (pointcloud.showBoundingBox && !node.boundingBoxNode && node.getBoundingBox) {
  48164. let colorHue = level / (maxLevel+1);
  48165. let s = 0.1 + level / (maxLevel+1);
  48166. let color = (new Color()).setHSL(colorHue, s, s);
  48167. let boxHelper = new Box3Helper$1(node.getBoundingBox(),color);
  48168. boxHelper.matrixAutoUpdate = false;
  48169. pointcloud.boundingBoxNodes.push(boxHelper);
  48170. node.boundingBoxNode = boxHelper;
  48171. node.boundingBoxNode.matrix.copy(pointcloud.matrixWorld);
  48172. } else if (pointcloud.showBoundingBox) {
  48173. node.boundingBoxNode.visible = true;
  48174. node.boundingBoxNode.matrix.copy(pointcloud.matrixWorld);
  48175. } else if (!pointcloud.showBoundingBox && node.boundingBoxNode) {
  48176. node.boundingBoxNode.visible = false;
  48177. }
  48178. // if(node.boundingBoxNode !== undefined && exports.debug.allowedNodes !== undefined){
  48179. // if(!exports.debug.allowedNodes.includes(node.name)){
  48180. // node.boundingBoxNode.visible = false;
  48181. // }
  48182. // }
  48183. }
  48184. // add child nodes to priorityQueue 由近及远、由大及小逐渐加载
  48185. let children = node.getChildren();
  48186. for (let i = 0; i < children.length; i++) {
  48187. let child = children[i];
  48188. let weight = 0;
  48189. if(camera.isPerspectiveCamera){
  48190. let sphere = child.getBoundingSphere();
  48191. let center = sphere.center;
  48192. let dd = sphere.center.distanceToSquared(camObjPos);
  48193. let addPow = viewer.mainViewport.view.isFlying() ? 0 : 0.5; //0-0.5,正常原本是0. 数字越大近处加载越快。但会造成远处加载慢甚至因pointBudge限制不加载。 isFlying:漫游时需要尽量加载一下远处的点云
  48194. //addPow *= window.devicePixelRatio //devicePixelRatio高的手机需要优先加载最近的高级点云,减少远处的中高级点云。
  48195. let distance = Math.pow(dd,0.5+addPow);//Math.sqrt(dd); //提高距离权重,为了提高近处加载速度。 某些场景近处加载慢优化明显,如SS-t-cqCAL6rJ5i
  48196. //let attenuateDis = 10;//add
  48197. let radius = sphere.radius;
  48198. let projFactor = projFactor0 / distance;
  48199. let screenPixelRadius = radius * projFactor;
  48200. /* if(distance > attenuateDis){
  48201. screenPixelRadius -= (distance - attenuateDis) * Math.sqrt(radius) * projFactor0 * 0.002
  48202. } */
  48203. //screenPixelRadius 和 domHeight 成正比,所以手机横屏后screenPixelRadius会变小。这是正常的,因为vhov不变,相同物体高度在横屏后高度变小,所需要的密度不需要那么高了。但hfov横屏后扩大,所以可见的node范围变大,又增加了一些可见node;只是总体的可见node还是减少了。
  48204. //使用hfov和domWidth计算结果相同。
  48205. if(screenPixelRadius < pointcloud.minimumNodePixelSize / Math.pow(dd,addPow)){ //理论上因手机像素小,更不容易堆叠铺满,minimumNodePixelSize应该除以window.deviceRatio 但会造成加载过多,而内存小
  48206. continue;
  48207. }
  48208. weight = screenPixelRadius;
  48209. if( !sphere.containsPoint(camObjPos) ){ //add 优先加载屏幕中央的点云(手机端缩小离远效果明显,不会那么稀疏)
  48210. let dir = new Vector3().subVectors(center, camObjPos).normalize();
  48211. let cos = 1+dir.dot(camObjDir); //0-2
  48212. weight *= cos/2;//Math.pow(cos,0.5) //幂越高,旁边的容易加载不到,出现缺块
  48213. }
  48214. if(distance - radius < 0){
  48215. weight = Number.MAX_VALUE;
  48216. }
  48217. //如果能得到每个方向上的密度,也就是node数量,密度大的远处少加载,因为被遮挡了显示也没有意义,就好了。
  48218. } else {
  48219. // TODO ortho visibility
  48220. //let bb = child.getBoundingBox();
  48221. let sphere = child.getBoundingSphere();
  48222. //let diagonal = bb.max.clone().sub(bb.min).length();
  48223. const reduce = 0; //0-0.5,正常原本是0.
  48224. if( sphere.radius * /* Math.pow( */camera.zoom/* ,1-reduce) */ < pointcloud.minimumNodePixelSize ){
  48225. continue;
  48226. }
  48227. let distance = sphere.center.distanceToSquared(camObjPos); //先加载中间然后四周
  48228. weight = sphere.radius / distance;
  48229. //weight = diagonal;
  48230. }
  48231. priorityQueue.push({pointcloud: element.pointcloud, node: child, parent: node, weight: weight}); //貌似好像二叉堆中子节点和父节点没什么关系,就只是为了方便排序层层遍历
  48232. }
  48233. //手机上像素点更小,所以远处感觉会更稀疏
  48234. }// end priority queue loop
  48235. { // update DEM 这是什么
  48236. let maxDEMLevel = 4;
  48237. let candidates = pointclouds.filter(p => (p.generateDEM && p.dem instanceof Potree.DEM));
  48238. for (let pointcloud of candidates) {
  48239. let updatingNodes = pointcloud.visibleNodes.filter(n => n.getLevel() <= maxDEMLevel);
  48240. pointcloud.dem.update(updatingNodes);
  48241. }
  48242. }
  48243. if(unloadedGeometry.length){//加载点云
  48244. /* for (let i = 0; i < Math.min(Potree.maxNodesLoading, unloadedGeometry.length); i++) {
  48245. unloadedGeometry[i].node.load(unloadedGeometry[i].pointcloud.pcoGeometry);
  48246. } */
  48247. let maxNodesLoading = Common$1.getBestCount('unloadedGeometry', viewer.lastFrameChanged?1:3, 6, 4, 15 /* , true */ );//dur在iphoneX中静止有7,pc是2 //!lastFrameChanged静止时加速下载
  48248. //THREE.Math.clamp(Math.round(9 - dur), 1, 6 )
  48249. //主要在手机端有效果。不改之前在展示的点云较多时前进会卡。
  48250. for (let i = 0; i < Math.min(maxNodesLoading, unloadedGeometry.length); i++) {
  48251. unloadedGeometry[i].node.load(unloadedGeometry[i].pointcloud.pcoGeometry);
  48252. }
  48253. }
  48254. //add:
  48255. Potree.numVisiblePoints = numVisiblePoints;
  48256. return {
  48257. visibleNodes: visibleNodes,
  48258. numVisiblePoints: numVisiblePoints,
  48259. lowestSpacing: lowestSpacing
  48260. };
  48261. };
  48262. /*
  48263. note:
  48264. 缓存中的点数 Potree.lru.numPoints 一般会 大于 每个点云显示点总数的numVisiblePoints
  48265. 当超出缓冲区最大点云数时,加载的点云节点会被dispose彻底消除;否则,隐藏的节点就会等待再次被使用显示
  48266. 由于加载按照由近及远、由大及小的顺序,要降低卡顿,就只需要降低Potree.pointBudget即可。但目前只设置了三个层次;另外提供maxLevel细节调节,能显示更均匀. 最好多一个调节pointBudge的滑动条
  48267. Potree.lru.numPoints
  48268. Potree.numVisiblePoints
  48269. viewer.scene.pointclouds[0].visibleNodes.length
  48270. */
  48271. {//HQSplatRenderer
  48272. let oldInit = HQSplatRenderer.prototype.init;
  48273. HQSplatRenderer.prototype.init = function(){
  48274. oldInit();
  48275. viewer.addEventListener('resize',this.resize.bind(this));
  48276. };
  48277. HQSplatRenderer.prototype.resize = function(e){
  48278. this.rtDepth.setSize(e.canvasWidth, e.canvasHeight);
  48279. this.rtAttribute.setSize(e.canvasWidth, e.canvasHeight);
  48280. };
  48281. HQSplatRenderer.prototype.clear = function(params={}){
  48282. this.init();
  48283. const {renderer, background} = this.viewer;
  48284. if(background === "skybox"){
  48285. renderer.setClearColor(0x000000, 0);
  48286. } else if (background === 'gradient') {
  48287. renderer.setClearColor(0x000000, 0);
  48288. } else if (background === 'black') {
  48289. renderer.setClearColor(0x000000, 1);
  48290. } else if (background === 'white') {
  48291. renderer.setClearColor(0xFFFFFF, 1);
  48292. } else {
  48293. renderer.setClearColor(0x000000, 0);
  48294. }
  48295. params.target || renderer.clear();
  48296. this.clearTargets(params);
  48297. };
  48298. HQSplatRenderer.prototype.render = function(params={}) {
  48299. this.init();
  48300. const viewer = this.viewer;
  48301. const camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  48302. const {width, height} = params.width ? params : this.viewer.renderer.getSize(new Vector2());
  48303. viewer.renderer.setRenderTarget(params.target||null);
  48304. viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
  48305. //params.target || this.resize(width, height);
  48306. const visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible);
  48307. const originalMaterials = new Map();
  48308. for(let pointcloud of visiblePointClouds){
  48309. originalMaterials.set(pointcloud, pointcloud.material);
  48310. if(!this.attributeMaterials.has(pointcloud)){
  48311. let attributeMaterial = new ExtendPointCloudMaterial();
  48312. this.attributeMaterials.set(pointcloud, attributeMaterial);
  48313. }
  48314. if(!this.depthMaterials.has(pointcloud)){
  48315. let depthMaterial = new ExtendPointCloudMaterial();
  48316. depthMaterial.setDefine("depth_pass", "#define hq_depth_pass");
  48317. depthMaterial.setDefine("use_edl", "#define use_edl");
  48318. this.depthMaterials.set(pointcloud, depthMaterial);
  48319. }
  48320. }
  48321. { // DEPTH PASS
  48322. for (let pointcloud of visiblePointClouds) {
  48323. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  48324. let material = originalMaterials.get(pointcloud);
  48325. let depthMaterial = this.depthMaterials.get(pointcloud);
  48326. depthMaterial.size = material.size;
  48327. depthMaterial.minSize = material.minSize;
  48328. depthMaterial.maxSize = material.maxSize;
  48329. depthMaterial.pointSizeType = material.pointSizeType;
  48330. depthMaterial.visibleNodesTexture = material.visibleNodesTexture;
  48331. depthMaterial.weighted = false;
  48332. depthMaterial.screenWidth = width;
  48333. depthMaterial.shape = PointShape.CIRCLE;
  48334. depthMaterial.screenHeight = height;
  48335. depthMaterial.uniforms.visibleNodes.value = material.visibleNodesTexture;
  48336. depthMaterial.uniforms.octreeSize.value = octreeSize;
  48337. depthMaterial.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(...pointcloud.scale.toArray());
  48338. depthMaterial.classification = material.classification;
  48339. depthMaterial.uniforms.classificationLUT.value.image.data = material.uniforms.classificationLUT.value.image.data;
  48340. depthMaterial.classificationTexture.needsUpdate = true;
  48341. depthMaterial.uniforms.uFilterReturnNumberRange.value = material.uniforms.uFilterReturnNumberRange.value;
  48342. depthMaterial.uniforms.uFilterNumberOfReturnsRange.value = material.uniforms.uFilterNumberOfReturnsRange.value;
  48343. depthMaterial.uniforms.uFilterGPSTimeClipRange.value = material.uniforms.uFilterGPSTimeClipRange.value;
  48344. depthMaterial.uniforms.uFilterPointSourceIDClipRange.value = material.uniforms.uFilterPointSourceIDClipRange.value;
  48345. depthMaterial.clipTask = material.clipTask;
  48346. depthMaterial.clipMethod = material.clipMethod;
  48347. depthMaterial.setClipBoxes(material.clipBoxes);
  48348. depthMaterial.setClipPolygons(material.clipPolygons);
  48349. pointcloud.material = depthMaterial;
  48350. }
  48351. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, (params.rtEDL || this.rtDepth), {
  48352. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
  48353. });
  48354. }
  48355. { // ATTRIBUTE PASS
  48356. for (let pointcloud of visiblePointClouds) {
  48357. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  48358. let material = originalMaterials.get(pointcloud);
  48359. let attributeMaterial = this.attributeMaterials.get(pointcloud);
  48360. attributeMaterial.size = material.size;
  48361. attributeMaterial.minSize = material.minSize;
  48362. attributeMaterial.maxSize = material.maxSize;
  48363. attributeMaterial.pointSizeType = material.pointSizeType;
  48364. attributeMaterial.activeAttributeName = material.activeAttributeName;
  48365. attributeMaterial.visibleNodesTexture = material.visibleNodesTexture;
  48366. attributeMaterial.weighted = true;
  48367. attributeMaterial.screenWidth = width;
  48368. attributeMaterial.screenHeight = height;
  48369. attributeMaterial.shape = PointShape.CIRCLE;
  48370. attributeMaterial.uniforms.visibleNodes.value = material.visibleNodesTexture;
  48371. attributeMaterial.uniforms.octreeSize.value = octreeSize;
  48372. attributeMaterial.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(...pointcloud.scale.toArray());
  48373. attributeMaterial.classification = material.classification;
  48374. attributeMaterial.uniforms.classificationLUT.value.image.data = material.uniforms.classificationLUT.value.image.data;
  48375. attributeMaterial.classificationTexture.needsUpdate = true;
  48376. attributeMaterial.uniforms.uFilterReturnNumberRange.value = material.uniforms.uFilterReturnNumberRange.value;
  48377. attributeMaterial.uniforms.uFilterNumberOfReturnsRange.value = material.uniforms.uFilterNumberOfReturnsRange.value;
  48378. attributeMaterial.uniforms.uFilterGPSTimeClipRange.value = material.uniforms.uFilterGPSTimeClipRange.value;
  48379. attributeMaterial.uniforms.uFilterPointSourceIDClipRange.value = material.uniforms.uFilterPointSourceIDClipRange.value;
  48380. attributeMaterial.elevationGradientRepeat = material.elevationGradientRepeat;
  48381. attributeMaterial.elevationRange = material.elevationRange;
  48382. attributeMaterial.gradient = material.gradient;
  48383. attributeMaterial.matcap = material.matcap;
  48384. attributeMaterial.intensityRange = material.intensityRange;
  48385. attributeMaterial.intensityGamma = material.intensityGamma;
  48386. attributeMaterial.intensityContrast = material.intensityContrast;
  48387. attributeMaterial.intensityBrightness = material.intensityBrightness;
  48388. attributeMaterial.rgbGamma = material.rgbGamma;
  48389. attributeMaterial.rgbContrast = material.rgbContrast;
  48390. attributeMaterial.rgbBrightness = material.rgbBrightness;
  48391. attributeMaterial.weightRGB = material.weightRGB;
  48392. attributeMaterial.weightIntensity = material.weightIntensity;
  48393. attributeMaterial.weightElevation = material.weightElevation;
  48394. attributeMaterial.weightRGB = material.weightRGB;
  48395. attributeMaterial.weightClassification = material.weightClassification;
  48396. attributeMaterial.weightReturnNumber = material.weightReturnNumber;
  48397. attributeMaterial.weightSourceID = material.weightSourceID;
  48398. attributeMaterial.color = material.color;
  48399. attributeMaterial.clipTask = material.clipTask;
  48400. attributeMaterial.clipMethod = material.clipMethod;
  48401. attributeMaterial.setClipBoxes(material.clipBoxes);
  48402. attributeMaterial.setClipPolygons(material.clipPolygons);
  48403. pointcloud.material = attributeMaterial;
  48404. }
  48405. let gl = this.gl;
  48406. //viewer.renderer.setRenderTarget(null);
  48407. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtAttribute, {
  48408. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
  48409. //material: this.attributeMaterial,
  48410. blendFunc: [gl.SRC_ALPHA, gl.ONE],
  48411. //depthTest: false,
  48412. depthWrite: false
  48413. });
  48414. }
  48415. for(let [pointcloud, material] of originalMaterials){
  48416. pointcloud.material = material;
  48417. }
  48418. if(viewer.background === "skybox"){
  48419. viewer.renderer.setClearColor(0x000000, 0);
  48420. viewer.renderer.clear();
  48421. viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
  48422. viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
  48423. viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
  48424. viewer.skybox.parent.rotation.x = 0;
  48425. viewer.skybox.parent.updateMatrixWorld();
  48426. viewer.skybox.camera.updateProjectionMatrix();
  48427. viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
  48428. } else if (viewer.background === 'gradient') {
  48429. viewer.renderer.setClearColor(0x000000, 0);
  48430. viewer.renderer.clear();
  48431. viewer.renderer.render(viewer.scene.sceneBG, viewer.scene.cameraBG);
  48432. } else if (viewer.background === 'black') {
  48433. viewer.renderer.setClearColor(0x000000, 1);
  48434. viewer.renderer.clear();
  48435. } else if (viewer.background === 'white') {
  48436. viewer.renderer.setClearColor(0xFFFFFF, 1);
  48437. viewer.renderer.clear();
  48438. } else {
  48439. viewer.renderer.setClearColor(0x000000, 0);
  48440. viewer.renderer.clear();
  48441. }
  48442. { // NORMALIZATION PASS
  48443. let normalizationMaterial = this.useEDL ? this.normalizationEDLMaterial : this.normalizationMaterial;
  48444. if(this.useEDL){
  48445. normalizationMaterial.uniforms.edlStrength.value = viewer.edlStrength;
  48446. normalizationMaterial.uniforms.radius.value = viewer.edlRadius;
  48447. normalizationMaterial.uniforms.screenWidth.value = width;
  48448. normalizationMaterial.uniforms.screenHeight.value = height;
  48449. normalizationMaterial.uniforms.uEDLMap.value = (params.rtEDL || this.rtDepth).texture;
  48450. }
  48451. normalizationMaterial.uniforms.uWeightMap.value = this.rtAttribute.texture;
  48452. normalizationMaterial.uniforms.uDepthMap.value = this.rtAttribute.depthTexture;
  48453. Utils.screenPass.render(viewer.renderer, normalizationMaterial);
  48454. }
  48455. viewer.renderer.render(viewer.scene.scene, camera);
  48456. viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer});
  48457. viewer.renderer.render(viewer.scene.sceneOverlay, camera);// add 透明贴图层
  48458. viewer.renderer.clearDepth();
  48459. viewer.transformationTool.update();
  48460. if(!params.target){
  48461. //测量线
  48462. viewer.dispatchEvent({type: "render.pass.perspective_overlay",viewer: viewer, camera});
  48463. viewer.renderer.render(viewer.overlay, camera);//从 viewer.renderDefault搬过来,为了reticule不遮住测量线
  48464. }
  48465. viewer.renderer.render(viewer.controls.sceneControls, camera);
  48466. viewer.renderer.render(viewer.clippingTool.sceneVolume, camera);
  48467. viewer.renderer.render(viewer.transformationTool.scene, camera);
  48468. viewer.renderer.setViewport(width - viewer.navigationCube.width,
  48469. height - viewer.navigationCube.width,
  48470. viewer.navigationCube.width, viewer.navigationCube.width);
  48471. viewer.renderer.render(viewer.navigationCube, viewer.navigationCube.camera);
  48472. viewer.renderer.setViewport(0, 0, width, height);
  48473. viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
  48474. viewer.renderer.setRenderTarget(null);
  48475. };
  48476. }
  48477. //PointCloudOctreeGeometry.js
  48478. PointCloudOctreeGeometryNode.prototype.loadHierachyThenPoints = function(pointcloud){
  48479. let node = this;
  48480. // load hierarchy
  48481. let callback = function (node, hbuffer) {
  48482. let tStart = performance.now();
  48483. let view = new DataView(hbuffer);
  48484. let stack = [];
  48485. let children = view.getUint8(0);
  48486. let numPoints = view.getUint32(1, true);
  48487. node.numPoints = numPoints;
  48488. stack.push({children: children, numPoints: numPoints, name: node.name});
  48489. let decoded = [];
  48490. let offset = 5;
  48491. while (stack.length > 0) {
  48492. let snode = stack.shift();
  48493. let mask = 1;
  48494. for (let i = 0; i < 8; i++) {
  48495. if ((snode.children & mask) !== 0) {
  48496. let childName = snode.name + i;
  48497. let childChildren = view.getUint8(offset);
  48498. let childNumPoints = view.getUint32(offset + 1, true);
  48499. stack.push({children: childChildren, numPoints: childNumPoints, name: childName});
  48500. decoded.push({children: childChildren, numPoints: childNumPoints, name: childName});
  48501. offset += 5;
  48502. }
  48503. mask = mask * 2;
  48504. }
  48505. if (offset === hbuffer.byteLength) {
  48506. break;
  48507. }
  48508. }
  48509. // console.log(decoded);
  48510. let nodes = {};
  48511. nodes[node.name] = node;
  48512. let pco = node.pcoGeometry;
  48513. let maxLevel_ = 0;
  48514. for (let i = 0; i < decoded.length; i++) {
  48515. let name = decoded[i].name;
  48516. let decodedNumPoints = decoded[i].numPoints;
  48517. let index = parseInt(name.charAt(name.length - 1));
  48518. let parentName = name.substring(0, name.length - 1);
  48519. let parentNode = nodes[parentName];
  48520. let level = name.length - 1;
  48521. maxLevel_ = Math.max(maxLevel_,level);//add
  48522. let boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
  48523. let currentNode = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
  48524. currentNode.level = level;
  48525. currentNode.numPoints = decodedNumPoints;
  48526. currentNode.hasChildren = decoded[i].children > 0;
  48527. currentNode.spacing = pco.spacing / Math.pow(2, level);
  48528. parentNode.addChild(currentNode);
  48529. nodes[name] = currentNode;
  48530. }
  48531. pco.dispatchEvent({type:'updateNodeMaxLevel',level:maxLevel_});//add
  48532. let duration = performance.now() - tStart;
  48533. if(duration > 5){
  48534. /* let msg = `duration: ${duration}ms, numNodes: ${decoded.length}`;
  48535. console.log(msg); */
  48536. }
  48537. node.loadPoints();
  48538. };
  48539. if ((node.level % node.pcoGeometry.hierarchyStepSize) === 0) {
  48540. // let hurl = node.pcoGeometry.octreeDir + "/../hierarchy/" + node.name + ".hrc";
  48541. let hurl = node.pcoGeometry.octreeDir + '/' + node.getHierarchyPath() + '/' + node.name + '.hrc';
  48542. //hurl += '?m='+node.pcoGeometry.timeStamp //add
  48543. let startLoad = (hurl)=>{
  48544. let xhr = XHRFactory.createXMLHttpRequest();
  48545. xhr.open('GET', hurl, true);
  48546. xhr.responseType = 'arraybuffer';
  48547. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  48548. xhr.onreadystatechange = () => {
  48549. if (xhr.readyState === 4) {
  48550. if (xhr.status === 200 || xhr.status === 0) {
  48551. let hbuffer = xhr.response;
  48552. callback(node, hbuffer);
  48553. } else {
  48554. console.log('Failed to load file! HTTP status: ' + xhr.status + ', file: ' + hurl);
  48555. Potree.numNodesLoading--;
  48556. }
  48557. }
  48558. };
  48559. try {
  48560. xhr.send(null);
  48561. } catch (e) {
  48562. console.log('fehler beim laden der punktwolke: ' + e);
  48563. }
  48564. };
  48565. Potree.getRealUrl(hurl, startLoad);
  48566. }
  48567. };
  48568. PointCloudOctreeGeometryNode.prototype.loadPoints = function(){
  48569. let name = this.name;
  48570. this.pcoGeometry.loader.load(this, ()=>{//callback
  48571. viewer.dispatchEvent('pointcloud_changed');
  48572. //console.log('loadPoints success ', name)
  48573. });
  48574. };
  48575. //加载点云成功->准备渲染画面->更新点云可见性updateVisibility->请求加载新的点云
  48576. PointCloudOctreeGeometryNode.prototype.traverse = function(t, e){//add from navvis 25.js
  48577. void 0 === e && (e = !0);
  48578. for (var n, i = e ? [this] : []; void 0 !== (n = i.pop()); ) {
  48579. t(n);
  48580. for (var o = 0, r = n.children; o < r.length; o++) {
  48581. var a = r[o];
  48582. null !== a && i.push(a);
  48583. }
  48584. }
  48585. };
  48586. Object.assign( PointCloudOctreeGeometry.prototype, EventDispatcher.prototype );
  48587. LRU.prototype.freeMemory = function(){
  48588. if (this.elements <= 1) {
  48589. return;
  48590. }
  48591. let memoryRatio = browser.isMobile() ? 2 : 5;
  48592. //改成navvis的,使用pointBudget,否则四屏点云闪烁。 (似乎要比updateVisiblede的node时限制要宽些,作为缓存继续存着。否则会闪烁)
  48593. let max = viewer.viewports.length * memoryRatio * Potree.pointBudget;
  48594. for (; this.numPoints > max; ) {
  48595. var node = this.getLRUItem();
  48596. node && this.disposeDescendants(node); //this.disposeSubtree(node)
  48597. }
  48598. };
  48599. /*
  48600. LRU.prototype.disposeSubtree = function(t) {//add from navvis 25.js 和原来的disposeDescendants功能一样
  48601. var e = [t];
  48602. t.traverse((function(t) {
  48603. t.loaded && e.push(t)
  48604. }));
  48605. for (var n = 0, i = e; n < i.length; n++) {
  48606. var o = i[n];
  48607. o.dispose(),
  48608. this.remove(o)
  48609. }
  48610. }*/
  48611. VolumeTool.prototype.update = function(){};
  48612. VolumeTool.prototype.startInsertion = function(args = {}){
  48613. let volume;
  48614. if(args.type){
  48615. volume = new args.type();
  48616. }else {
  48617. volume = new Potree.BoxVolume(Object.assign(args,{clip:true}) );
  48618. }
  48619. volume.highlight = true;
  48620. volume.name = args.name || 'Volume-'+args.clipTask;
  48621. volume.isNew = true;
  48622. viewer.transformObject(null);//先清空
  48623. //console.log('startInsertion',volume.uuid)
  48624. let oldVisiBoxes;
  48625. if(args.clipTask == Potree.ClipTask.SHOW_INSIDE){ //如果是显示类型,需要将所有同类型的解除效果,否则看不到效果。 (或者可以在添加非第一个时去除highlight效果,会更自然,但看不清全貌)
  48626. oldVisiBoxes = viewer.scene.volumes.filter(v => v.clipTask == Potree.ClipTask.SHOW_INSIDE && !v.highlight );
  48627. oldVisiBoxes.forEach(box=>box.highlight = true);
  48628. }
  48629. let updatePose = ()=>{ //保证在视野中的大小一致:
  48630. let camera = this.viewer.scene.getActiveCamera();
  48631. let w = math.getScaleForConstantSize({
  48632. width2d: 300,
  48633. camera , position:volume.getWorldPosition(new Vector3()) ,
  48634. resolution: viewer.mainViewport.resolution//2
  48635. });
  48636. /* let wp = volume.getWorldPosition(new THREE.Vector3()).applyMatrix4(camera.matrixWorldInverse);
  48637. // let pp = new THREE.Vector4(wp.x, wp.y, wp.z).applyMatrix4(camera.projectionMatrix);
  48638. let w = Math.abs((wp.z / 3));*/
  48639. if(!isNaN(w))volume.scale.set(w, w, w);
  48640. {//使水平朝向与camera一致
  48641. let direction = viewer.mainViewport.view.direction.setZ(0);
  48642. volume.quaternion.copy(math.getQuaByAim(direction));
  48643. }
  48644. };
  48645. this.dispatchEvent({
  48646. type: 'start_inserting_volume',
  48647. volume: volume
  48648. });
  48649. updatePose();
  48650. this.viewer.scene.addVolume(volume);
  48651. this.scene.add(volume);
  48652. let drag = e => {
  48653. let I = Utils.getMousePointCloudIntersection(
  48654. viewer.mainViewport,
  48655. viewer.inputHandler.mouse,
  48656. viewer.inputHandler.pointer,
  48657. this.viewer.scene.getActiveCamera(),
  48658. this.viewer,
  48659. this.viewer.scene.pointclouds,
  48660. {pickClipped: args.clipTask == Potree.ClipTask.SHOW_OUTSIDE } //无视clip状态
  48661. );
  48662. var worldPos = I && I.location;
  48663. if(!worldPos){
  48664. return
  48665. }
  48666. volume.position.copy(worldPos);
  48667. updatePose();
  48668. };
  48669. let cancel = ()=>{
  48670. end('remove');
  48671. };
  48672. let end = (e) => {
  48673. if(e.button == MOUSE.RIGHT && e.pressDistance<=Potree.config.clickMaxDragDis) {//remove
  48674. e = 'remove';
  48675. }
  48676. //console.log('end',volume.uuid, e)
  48677. if(e != 'remove' && (!e.isAtDomElement || e.pressDistance>Potree.config.clickMaxDragDis))return continueDrag()
  48678. volume.removeEventListener('drag', drag);
  48679. volume.removeEventListener('drop', end);
  48680. this.viewer.removeEventListener('cancel_insertions', cancel);
  48681. volume.isNew = false;
  48682. viewer.removeEventListener('camera_changed', updatePose);
  48683. if(e == 'remove'){
  48684. viewer.scene.removeVolume(volume); //删除没完成的
  48685. }else {
  48686. viewer.transformObject(volume);
  48687. volume.highlight = false;
  48688. }
  48689. volume.dispatchEvent({type:'createFinish', success:e != 'remove' });
  48690. oldVisiBoxes && oldVisiBoxes.forEach(box=>box.highlight = false);
  48691. };
  48692. let continueDrag = ( )=>{
  48693. //console.log('continueDrag',volume.uuid )
  48694. var timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
  48695. if(volume.parent && volume.isNew){
  48696. viewer.inputHandler.startDragging( volume , {notPressMouse:true}
  48697. /* {endDragFun: e.drag.endDragFun, notPressMouse:e.drag.notPressMouse, dragViewport:e.drag.dragViewport} */
  48698. );
  48699. }
  48700. },1);
  48701. return timer
  48702. };
  48703. volume.addEventListener('drag', drag);
  48704. volume.addEventListener('drop', end);
  48705. this.viewer.addEventListener('cancel_insertions', cancel);
  48706. viewer.addEventListener('camera_changed', updatePose);
  48707. this.viewer.inputHandler.startDragging(volume, {notPressMouse:true});
  48708. return volume;
  48709. };
  48710. LineGeometry.prototype.setPositions = function( array ) { //xzw改成类似LineSegments的多段线 (第二个点和第三个点之间是没有线段的, 所以不用在意线段顺序)
  48711. const points = new Float32Array( array );
  48712. LineSegmentsGeometry.prototype.setPositions.call(this, points );
  48713. return this;
  48714. };
  48715. Object.assign(ExtendView.prototype, EventDispatcher.prototype);
  48716. Object.assign(ExtendScene.prototype, EventDispatcher.prototype );
  48717. function start(dom, navDom, number ){ //t-Zvd3w0m
  48718. Potree.settings.number = number || 't-o5YMR13';// 't-iksBApb'// 写在viewer前
  48719. if(browser.urlHasValue('timing'))Potree.measureTimings = 1;
  48720. let viewer = new Potree.Viewer(dom , navDom);
  48721. viewer.setEDLEnabled(false);
  48722. viewer.setFOV(Potree.config.view.fov);
  48723. if(!Potree.settings.isOfficial){
  48724. viewer.loadGUI(() => {
  48725. viewer.setLanguage('en');
  48726. $("#menu_tools").next().show();
  48727. $("#menu_scene").next().show();
  48728. viewer.toggleSidebar();
  48729. });
  48730. Potree.settings.sizeFitToLevel = true;//当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  48731. Potree.settings.rotAroundPoint = false;
  48732. }
  48733. if( browser.isMobile() && browser.urlHasValue('log')){
  48734. changeLog();
  48735. }
  48736. {
  48737. var cloudPath = //`${Potree.settings.urls.prefix1}/webcloud/cloud.js`
  48738. `${Potree.settings.urls.prefix1}/floor_0_webcloud/cloud.js`;
  48739. var timeStamp = 0; //var timeStamp = dataset.updateTime ? dataset.updateTime.replace(/[^0-9]/ig,'') : ''; //每重算一次后缀随updateTime更新一次
  48740. Potree.loadPointCloud(cloudPath, timeStamp, e => {
  48741. let scene = viewer.scene;
  48742. let pointcloud = e.pointcloud;
  48743. let config = Potree.config.material;
  48744. let material = pointcloud.material;
  48745. //pointcloud.datasetData = dataset
  48746. //pointcloud.dataset_id = dataset.id;//供漫游点找到属于的dataset点云
  48747. pointcloud.hasDepthTex = Potree.settings.useDepthTex;
  48748. material.minSize = config.minSize;
  48749. material.maxSize = config.maxSize;
  48750. material.pointSizeType =/* Potree.settings.isOfficial ? */ config.pointSizeType; /* : 'ADAPTIVE' */ //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
  48751. pointcloud.changePointSize(config.realPointSize); //material.size = config.pointSize;
  48752. pointcloud.changePointOpacity(1);
  48753. material.shape = Potree.PointShape.SQUARE;
  48754. //pointcloud.color = pointcloud.material.color = dataset.color
  48755. pointcloud.timeStamp = timeStamp;
  48756. //transformPointcloud(pointcloud,dataset)
  48757. scene.addPointCloud(pointcloud);
  48758. Potree.loadPanos( (data) => {
  48759. //console.log('loadPanos',dataset.sceneCode, dataset.id, data)
  48760. viewer.images360.addPanoData(data );
  48761. viewer.images360.loadDone();
  48762. viewer.scene.add360Images(viewer.images360);
  48763. viewer.updateModelBound(); //需等pano加载完
  48764. let {boundSize, center} = viewer.bound;
  48765. viewer.dispatchEvent({type:'loadPointCloudDone'});
  48766. if(!Potree.settings.UserPointDensity){
  48767. Potree.settings.UserPointDensity = 'high';//'middle'
  48768. }
  48769. {//初始位置
  48770. var panoId = browser.urlHasValue('pano',true);
  48771. if(panoId !== ''){
  48772. var pos;
  48773. var pano = viewer.images360.panos.find(e=>e.id==panoId);
  48774. if(pano){
  48775. viewer.images360.focusPano({
  48776. pano,
  48777. duration:0,
  48778. callback:()=>{/* Potree.settings.displayMode = 'showPanos' */}
  48779. });
  48780. }
  48781. }else {//考虑到多数据集距离很远,或者像隧道那种场景,要使视野范围内一定能看到点云,最好初始点设置在漫游点上
  48782. let {boundSize, center} = viewer.bound;
  48783. let pano = viewer.images360.findNearestPano(center);
  48784. pano && viewer.images360.flyToPano({
  48785. pano, duration:0,
  48786. target : viewer.images360.bound.center.setZ(pano.position.z) //平视中心区域(但也不能保证这个方向一定能看到点云密集区,如果在边缘的话)
  48787. });
  48788. }
  48789. }
  48790. let boxHelper = new Potree.Box3Helper(viewer.bound.boundingBox);
  48791. boxHelper.matrixAutoUpdate = false;
  48792. viewer.scene.scene.add(boxHelper);
  48793. viewer.bound.boxHelper = boxHelper;
  48794. boxHelper.visible = false;
  48795. console.log('allLoaded');
  48796. viewer.dispatchEvent('allLoaded');
  48797. });
  48798. });
  48799. }
  48800. window.THREE = THREE$1;
  48801. if(Potree.settings.isLocalhost){
  48802. let before = {};
  48803. viewer.inputHandler.addEventListener('keydown',e=>{ //测试的代码
  48804. if(e.event.key == 't'){
  48805. viewer.images360.cube.visible = true;
  48806. viewer.images360.cube.material.wireframe = true;
  48807. }else if(e.event.key == 'y'){
  48808. viewer.images360.cube.material.wireframe = false;
  48809. viewer.images360.cube.visible = Potree.settings.displayMode == 'showPanos';
  48810. }
  48811. });
  48812. }
  48813. //--------------------------------
  48814. /* if(!number){
  48815. Potree.settings.boundAddObjs = true
  48816. Potree.settings.intersectOnObjs = true
  48817. // Load untextured bunny from ply
  48818. viewer.loadModel({
  48819. fileType:'ply',
  48820. url:Potree.resourcePath + "/models/indoor.ply",
  48821. name:'test',
  48822. },
  48823. (object)=>{
  48824. object.isModel = true
  48825. viewer.updateModelBound()
  48826. }
  48827. )
  48828. } */
  48829. }
  48830. var changeLog = ()=>{
  48831. var textarea = document.createElement('textarea');
  48832. textarea.id = "consoleLog";
  48833. textarea.style.width = '160px';
  48834. textarea.style.height = '200px';
  48835. textarea.style.position = 'fixed';
  48836. textarea.style.right = 0;
  48837. textarea.style.bottom = '1px';
  48838. textarea.style['z-index'] = 9999;
  48839. textarea.style.color = 'black';
  48840. textarea.style.opacity = 0.9;
  48841. textarea.style['font-size'] = '12px';
  48842. textarea.style['backgroundColor'] = '#ffffff';
  48843. document.getElementsByTagName("body")[0].appendChild(textarea);
  48844. var list = ["log", "error", "warn", "debug", "info", "time", "timeEnd"];
  48845. var exchange = function (o) {
  48846. console["old" + o] = console[o];
  48847. console[o] = function () {
  48848. var args = Array.from(arguments);
  48849. console["old" + o].apply(this, arguments);
  48850. var t = document.getElementById("consoleLog").innerHTML;
  48851. var str = '';
  48852. args.forEach(a=>{
  48853. str += a + ' ';
  48854. });
  48855. document.getElementById("consoleLog").innerHTML = str + "\n\n" + t;
  48856. };
  48857. };
  48858. for (var i = 0; i < list.length; i++) {
  48859. exchange(list[i]);
  48860. }
  48861. };
  48862. //xzw add
  48863. const config$1 = {//配置参数 不可修改
  48864. displayMode:{
  48865. showPointCloud:{
  48866. atPano:{
  48867. showPoint : true,
  48868. showSkybox: false,
  48869. pointUsePanoTex : false
  48870. },
  48871. transition:{
  48872. showPoint: true,
  48873. showSkybox: false,
  48874. pointUsePanoTex: false
  48875. },
  48876. canLeavePano: true //是否能离开pano位置
  48877. },
  48878. showPanos:{
  48879. atPano:{
  48880. showPoint : false,
  48881. showSkybox: true,
  48882. pointUsePanoTex : false
  48883. },
  48884. transition:{
  48885. //showPoint: true,
  48886. showSkybox: true,
  48887. //pointUsePanoTex: true //是否使用全景贴图
  48888. },
  48889. canLeavePano: false
  48890. },
  48891. showBoth:{
  48892. atPano:{
  48893. showPoint : true,
  48894. showSkybox: true,
  48895. pointUsePanoTex : false //?
  48896. },
  48897. transition:{
  48898. showPoint: true,
  48899. showSkybox: true,
  48900. pointUsePanoTex: true
  48901. },
  48902. canLeavePano: true //是否能离开pano位置 离开后自动变为showPointCloud
  48903. },
  48904. //test:
  48905. pointUsePanoTex:{ //---静止时调点云
  48906. atPano:{
  48907. showPoint : true,
  48908. showSkybox: false,
  48909. pointUsePanoTex : true
  48910. },
  48911. transition:{
  48912. showPoint: true,
  48913. showSkybox: true,
  48914. pointUsePanoTex: true //是否使用全景贴图
  48915. },
  48916. canLeavePano: false
  48917. },
  48918. },
  48919. urls:{
  48920. //localTextures:'../resources/textures/',
  48921. prefix1: '',//'https://laser-oss.4dkankan.com',//oss
  48922. prefix2: '',//'https://testlaser.4dkankan.com',
  48923. prefix3: '',//'https://4dkk.4dage.com',
  48924. prefix4: '',//'https://uat-laser.4dkankan.com',//test.4dkankan
  48925. prefix5: '',//'https://laser.4dkankan.com',
  48926. prefix6: '',//'https://mix3d.4dkankan.com/backend',
  48927. },
  48928. transitionsTime:{
  48929. flyMinTime : 300 , // 毫秒/米
  48930. flytimeDistanceMultiplier: 130 ,
  48931. panoToPanoMax: 1800 ,
  48932. flyIn:1000,
  48933. flyOut:1000
  48934. }
  48935. ,
  48936. view:{
  48937. fov:70, //navvis:50
  48938. near:0.1,
  48939. far: 10000,
  48940. },
  48941. map:{//mapViewer
  48942. mapHeight : -1000,//要比点云低。最低
  48943. cameraHeight : 1000, //最高 ,注意(如sitemodel)其他的物体不能超过这个高度
  48944. },
  48945. minNodeSize:30, // perspectiveCamera允许加载的node的最小可见像素宽度。越大越省性能
  48946. pointDensity:{
  48947. magnifier:{
  48948. maxLevelPercent: 1,
  48949. pointBudget : 8*1000*1000,
  48950. },
  48951. panorama:{//显示全景时的漫游。因为点只能显示1个像素的大小,所以必须很密集,但又要限制点的数量
  48952. maxLevelPercent: 0.6,
  48953. pointBudget : /* 4*1000*1000// */browser.isMobile() ? 0.1*1000*1000 : 0.4*1000*1000, //点云总最大数
  48954. minNodeSize : 100,
  48955. },
  48956. fourViewports:{//分四屏时防止卡顿
  48957. maxLevelPercent: 0.4,
  48958. pointBudget :1*1000*1000, // 只要限制这个就足够 (为什么分屏focus区域不同会闪烁,navvis不会)(navvis:maxLevel:5,pointBudget:1*1000*1000)
  48959. minNodeSize : 70,
  48960. },
  48961. fourViewportsMain:{//分四屏时防止卡顿
  48962. maxLevelPercent: 0.8,
  48963. pointBudget :1*1000*1000, // 只要限制这个就足够 (为什么分屏focus区域不同会闪烁,navvis不会)(navvis:maxLevel:5,pointBudget:1*1000*1000)
  48964. minNodeSize : 70,
  48965. }
  48966. ,
  48967. panoEdit:{
  48968. maxLevelPercent: 1, //在远处时由于pointBudget限制而展示稀疏,凑近时就变为最高质量了
  48969. pointBudget :6*1000*1000, //比最高的低一点,避免卡顿
  48970. percentByUser:true,
  48971. minNodeSize : 50 ,
  48972. },
  48973. low:{//highPerformance
  48974. maxLevelPercent: 0.4, //最小为0
  48975. percentByUser:true, //如果用户定义了percent,使用用户的
  48976. pointBudget : browser.isMobile() ? 1*1000*1000 : 2*1000*1000,
  48977. minNodeSize : 40 / window.devicePixelRatio ,
  48978. },
  48979. middle:{//balanced //不同场景相同级别所产生的numVisibleNodes和numVisiblePoints不同,如果分层比较细,可能要到level8才能看清,那么level5看到的点就很大且很少,如隧道t-e2Kb2iU
  48980. maxLevelPercent: 0.7,
  48981. percentByUser:true,
  48982. pointBudget: browser.isMobile() ? 2.0*1000*1000 : 3.5*1000*1000,
  48983. minNodeSize : 30 / window.devicePixelRatio ,
  48984. },
  48985. high:{//highQuality
  48986. maxLevelPercent: 1,
  48987. percentByUser:true,
  48988. pointBudget:browser.isMobile() ? 3*1000*1000 : 6*1000*1000, //原本最高是8,但是大部分电脑都太卡了,降
  48989. minNodeSize : 20 / window.devicePixelRatio , //手机上因为像素点小,远一点的时候更需要加载密集的点云。(没事,有pointBudget限制着,会先从近处加载高级node,再远就不加载了)
  48990. }
  48991. //数值由testLevelSteps得来,其中nodeMaxLevel为2时,low和middle的都是1,如果真有这么低的点云就单独处理下。
  48992. //多个viewport尽量保证pointBudget一样,或者pointBudget不能太低于所需,否则会反复加载了又清除
  48993. },
  48994. clip:{
  48995. color: '#FFC266', //map
  48996. },
  48997. measure:{
  48998. color:'#00C8AF',
  48999. default:{
  49000. color:"#2F8FFF",//"#00c7b2",
  49001. opacity:0.8
  49002. },
  49003. highlight:{
  49004. color:"#ff8f28",//"#00c7b2", (255, 143, 40, 1
  49005. opacity:1
  49006. },
  49007. guide:{
  49008. color:'#FFFFFF',
  49009. opacity:1
  49010. }
  49011. ,
  49012. backColor:'#333333',
  49013. lineWidth: 3,
  49014. textColor: "#FFFFFF"
  49015. },
  49016. material:{//初始化
  49017. pointSize: 0.1,
  49018. realPointSize : 0.1,//实际上的ui滑动条默认大小(兼容旧的版本)
  49019. minSize: 0.1,
  49020. maxSize: 10000,
  49021. pointSizeType: 'ATTENUATED', //'ADAPTIVE'//'ADAPTIVE' \ FIXED //ADAPTIVE的在小房间里大小会不太匹配,但在远景似乎更好
  49022. /*
  49023. ATTENUATED : 衰减 真实大小,靠近时感觉是点云一点点变多,缝隙变小
  49024. ADAPTIVE: 自适应 大小根据level变化,越高越小。靠近时感觉点云由大慢慢细分成小份。这个感觉更佳但是navvis为何不用这个
  49025. */
  49026. absolutePanoramaSize: 1.3 ,//全景漫游时的size 是fixed的模式
  49027. //sizeAtPanoRtEDL : 2000,
  49028. pointColor:'#ffffff',
  49029. //sizeAddAtPanoRtEDL : 0.5, //全景模式静止时的size
  49030. //ADAPTIVE : 字会失真扭曲
  49031. //'ATTENUATED' 往旁边看有缝隙、点在浮动
  49032. }
  49033. ,
  49034. skyboxBgWidth : 100 ,
  49035. renderLayers:{//渲染层,方便分批渲染管理,替代scene的创建。数字不代表顺序。(数字不能太大)
  49036. bg: 20,
  49037. bg2: 21,
  49038. skybox: 1,
  49039. pointcloud: 11,
  49040. sceneObjects:0,//default
  49041. model : 2,
  49042. light: 15,
  49043. measure:4,
  49044. magnifier:5,
  49045. magnifierContent:16,
  49046. volume:6,
  49047. transformationTool:7,
  49048. map:8,
  49049. mapObjects:9,//default
  49050. bothMapAndScene: 3,
  49051. siteModeOnlyMapVisi:12,//只能mapViewer可见
  49052. siteModelMapUnvisi:13,//只有mapViewer不可见
  49053. siteModeSideVisi:14,//只有侧面可见
  49054. layer1: 18,// 备用1
  49055. layer2: 17,// 备用2
  49056. },
  49057. renderOrders:{ //会影响到绘制、pick时的顺序。
  49058. model:10
  49059. },
  49060. siteModel:{
  49061. names:{
  49062. 'building': '建筑',
  49063. 'floor':'楼层',
  49064. 'room':'房间'
  49065. },
  49066. floorHeightDefault: 5,//一层楼的高度
  49067. },
  49068. panosEdit:{
  49069. },
  49070. tiling: {
  49071. panoPreRenderRepeatDelay: 2500,
  49072. panoPreRenderDelay: 500,
  49073. preRenderTourPanos: browser.valueFromHash("tileprerender", 0),
  49074. tilingFlagNames: ["usetiles", "tiles"],
  49075. maxNavPanoQuality: browser.valueFromHash("maxtileq", null),
  49076. maxZoomPanoQuality: browser.valueFromHash("maxztileq", null),
  49077. overlayStyle: browser.valueFromHash("tileoverlay", 0),
  49078. uploadIntervalDelay: browser.valueFromHash("tileupdelay", 10 ),
  49079. initialIntervalDelay: browser.valueFromHash("itiledelay", 0),
  49080. maxNonBaseUploadsPerFrame: browser.valueFromHash("maxnbtpf", 1),
  49081. maxBaseUploadsPerFrame: browser.valueFromHash("maxbtpf",6),
  49082. customCompression: browser.valueFromHash("tilecustcomp", 0),
  49083. mobileHighQualityOverride: !1,
  49084. allowUltraHighResolution: !0
  49085. },
  49086. navigation: {
  49087. panoScores: !1,
  49088. mouseDirection: !0,
  49089. filterStrictness: .75,
  49090. angleFactor: -30,
  49091. directionFactor: 10,
  49092. distanceFactor: -1,
  49093. optionalityFactor: 3
  49094. }
  49095. ,
  49096. axis : { 'x':{color:'#ea3f3f'/* '#d0021b' */ /* 'red' */}, 'y':{ color:'#86c215' /* '#86c542' *//* 'green' */}, 'z': {color:'#3396f8'/* '#3399c8' */ /* 'blue' */}, 'xyz':{color:'#ccc',}},
  49097. shelterMargin:0.1,
  49098. highQualityMaxZoom: 2,
  49099. ultraHighQualityMaxZoom: 3,
  49100. panoFieldRadius : 10, //当前位置多远范围内可以切全景模式
  49101. clickMaxDragDis:5,
  49102. clickMaxPressTime:500, //ms
  49103. doubleClickTime:200,//双击间隔时间
  49104. testNodeCount1: browser.isMobile() ? 5 : 3, //testMaxNode次数达到这个数字时,changePointSize才使用nodeMaxLevel。 (调试时比较卡,在线上实际只需要3)
  49105. background: '#232323',
  49106. mapBG:/* '#232323', */ '#F5F5F5', //地图的clearColor
  49107. colors: { //from navvis
  49108. red: [213,0,0],
  49109. pink: [197,17,98],
  49110. purple: [170,0,255],
  49111. "deep purple": [98,0,234],
  49112. blue: [ 41,98,255],
  49113. "light blue": [ 0,145,234],
  49114. cyan: [ 0,184,212],
  49115. teal: [ 0,191,165],
  49116. green: [0,200,83],
  49117. "light green": [ 100,221,23],
  49118. lime: [ 174,234,0],
  49119. yellow: [ 255,214,0],
  49120. amber: [ 255,171,0],
  49121. orange: [ 255,109,0],
  49122. "deep orange": [ 255,61,0],
  49123. },
  49124. depthTexUVyLimit: 0.141, // 在这个范围内是没有深度的,从图片算的0.14003, 设置为稍大于这个数值
  49125. };
  49126. config$1.OrthoCameraLimit = {
  49127. standard:{
  49128. zoom:{min:0.0004, max:500}, //如果camera缩太小,地图会因为数字边界问题而扭曲
  49129. latPad:20,
  49130. xBound:[-4e6, 4e6],
  49131. },
  49132. expand:{
  49133. zoom:{min:0.0004, max:500}, //如果camera缩太小,地图会因为数字边界问题而扭曲
  49134. latPad:20,
  49135. xBound:[-6e6, 6e6],
  49136. },
  49137. };
  49138. /* 显示模式:
  49139. 1只显示点云: 滚轮为前进后退,方向键可以行走。进入漫游点时自动变为混合(这样全景可以弥补缝隙),过渡时只显示点云。
  49140. 2只显示全景: 不能任意行走。 过渡时显示贴图材质非edl的点云(否则有折痕不贴合)。
  49141. 3混合:都显示。 不能任意行走。过渡时显示贴图材质非edl的点云(因为只显示点云的话不太美,点云很碎,不细腻)
  49142. */
  49143. window.testLevelSteps = function(steps){//[0.4,0.7,1]
  49144. if(!steps){
  49145. let s = Potree.config.pointDensity;
  49146. steps = [s.low.maxLevelPercent, s.middle.maxLevelPercent, s.high.maxLevelPercent, ];
  49147. }
  49148. let max = 1;
  49149. while(++max<=12){
  49150. let r1 = steps.map(e=>e * max);
  49151. let r2 = steps.map(e=>Math.round(e * max));
  49152. console.log(`当nodeMaxLevel为${max}时,每一级的level分别为${r2}, (小数:${r1})`);
  49153. }
  49154. console.log('请检查每一层的三个level是否有重复');
  49155. };
  49156. function getPrefix(){
  49157. let u = window.location.href.split('//');
  49158. let v = u[1].split('/');
  49159. return v[0]
  49160. }
  49161. let isTest = browser.urlHasValue('test');
  49162. let settings = {//设置 可修改
  49163. editType : '',
  49164. number: '', //场景序号
  49165. originDatasetId:'',//场景原本的数据集id,应该就是数据集第一个吧
  49166. isOfficial:false,
  49167. webSite:'testdata',//正式:'datav1', //不同环境对应的静态文件的地址不同
  49168. isLocal:false, //是否本地 局域网版本
  49169. libsUrl:'../libs/',
  49170. displayMode:'',
  49171. isTest ,
  49172. prefix: getPrefix(),
  49173. pointDensity: '', UserPointDensity:'',//pointDensity会随着进入不同的模块而自动改变,UserPointDensity记录了用户的设置
  49174. UserDensityPercent:null,//点云密度百分比
  49175. ifShowMarker:true,//显示漫游点
  49176. floorplanType:{},//平面图类型 'default' | 'diy' 不同数据集不同{datasetId:...}
  49177. floorplanEnable:false,
  49178. floorplanEnables:{},
  49179. floorplanRequests:{},//开始加载了的
  49180. mapEnable:true,//地图区域是否加载地图
  49181. cameraFar : config$1.view.far, //相机最远范围 1-300
  49182. //limitFar: true, //是否使用setting的cameraFar来限制(如在点云裁剪时为false)
  49183. showPanoMesh:false, //显示小球,
  49184. dblToFocusPoint:false,//调试时如果需要双击飞向某个点云的点,就打开。此时不在漫游点的话单击将无法漫游。//因和单击漫游冲突
  49185. unableNavigate : false,//进入如裁剪界面时 禁止漫游
  49186. sizeFitToLevel: false,//当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  49187. zoom:{
  49188. enabled : true,
  49189. min:1,
  49190. max: config$1.highQualityMaxZoom
  49191. },
  49192. navConstantly:true,
  49193. navTileClass: /* browser.isMobile() ? '1k' : */ '2k', //默认加载到
  49194. tileClass:'4k', //最高可达
  49195. /* loadTilesWhenUnfocus:false, //页面unfocus时也仍在加载tiles
  49196. loadPointsWhenUnfocus:true, //页面unfocus时也仍在加载点云 */
  49197. //initialShowPano:true
  49198. drawEntityData: false, //包括marker、线
  49199. zoomFromPointert:{//定点缩放(包括点云模式、全景模式、地图)
  49200. whenPanos:true,
  49201. whenPointCloud:true,
  49202. map:true,
  49203. },
  49204. rotAroundPoint:true,//点云模式是否能绕intersectPoint旋转
  49205. tourTestCameraMove:false, //测试镜头时,不移动真实的镜头, 只移动frustum
  49206. cameraAniSmoothRatio : 20, //镜头动画平滑系数,越高越平滑
  49207. urls : $.extend({}, config$1.urls, {
  49208. prefix : config$1.urls.prefix4 //主要使用的 是测试环境,根据不同工程更改
  49209. }),
  49210. useDepthTex: true,//使用深度贴图,但不代表一定有(得到的intersect更快速准确和稳定) SS-t-7DUfWAUZ3V
  49211. //matUseDepth:false,
  49212. //panoEdit:
  49213. datasetsPanos:{},
  49214. //mergeModel:
  49215. boundAddObjs:false,
  49216. intersectOnObjs:false,
  49217. intersectWhenHover:true,
  49218. depTexLocBindDataset: true,//是否在pano模式下,使用深度图得到intersect的话,改intersect能属于该pano所在的点云。也就相当于在全景模式下intersect的点属于该全景图
  49219. notAdditiveBlending:false, //点云是否使用普通的blend, 否则会曝光过渡
  49220. precision:2, // 两位小数
  49221. useV4url:true, //v4的全景图等路径不一样 scene_view_data
  49222. useRTskybox:true, //直接使用rtEDL绘制到屏幕,当是全景模式时. 在降4倍时能给render节省1毫秒,gpu时间未测
  49223. //useRTPoint:true, //直接使用rtEDL绘制到屏幕,当是点云模式时。可以大大节省gpu时间. 大部分时候是有测量线的,失去抗锯齿了算了
  49224. pointEnableRT:false,//点云是否允许绘制到rtEDL。只在有需要时使用
  49225. cloudSameMat:true, //因为点云个数较多,就使用相同的材质,可见降低绘制速度(要保证所有点云的maxNodelevel一样,且要算出 material.spacing的平均值)
  49226. //showCompass : isTest,
  49227. showAxis : isTest,
  49228. //testCube : true,
  49229. };
  49230. settings.isLocalhost = settings.prefix.includes('localhost');
  49231. console.log('2023-1');
  49232. class U {
  49233. static toVector3(v, offset) {
  49234. return new Vector3().fromArray(v, offset || 0);
  49235. }
  49236. static toBox3(b) {
  49237. return new Box3(U.toVector3(b), U.toVector3(b, 3));
  49238. };
  49239. static findDim(schema, name) {
  49240. var dim = schema.find((dim) => dim.name == name);
  49241. if (!dim) throw new Error('Failed to find ' + name + ' in schema');
  49242. return dim;
  49243. }
  49244. static sphereFrom(b) {
  49245. return b.getBoundingSphere(new Sphere());
  49246. }
  49247. };
  49248. class PointCloudEptGeometry {
  49249. constructor(url, info) {
  49250. let version = info.version;
  49251. let schema = info.schema;
  49252. let bounds = info.bounds;
  49253. let boundsConforming = info.boundsConforming;
  49254. let xyz = [
  49255. U.findDim(schema, 'X'),
  49256. U.findDim(schema, 'Y'),
  49257. U.findDim(schema, 'Z')
  49258. ];
  49259. let scale = xyz.map((d) => d.scale || 1);
  49260. let offset = xyz.map((d) => d.offset || 0);
  49261. this.eptScale = U.toVector3(scale);
  49262. this.eptOffset = U.toVector3(offset);
  49263. this.url = url;
  49264. this.info = info;
  49265. this.type = 'ept';
  49266. this.schema = schema;
  49267. this.span = info.span || info.ticks;
  49268. this.boundingBox = U.toBox3(bounds);
  49269. this.tightBoundingBox = U.toBox3(boundsConforming);
  49270. this.offset = U.toVector3([0, 0, 0]);
  49271. this.boundingSphere = U.sphereFrom(this.boundingBox);
  49272. this.tightBoundingSphere = U.sphereFrom(this.tightBoundingBox);
  49273. this.version = new Potree.Version('1.7');
  49274. this.projection = null;
  49275. this.fallbackProjection = null;
  49276. if (info.srs && info.srs.horizontal) {
  49277. this.projection = info.srs.authority + ':' + info.srs.horizontal;
  49278. }
  49279. if (info.srs.wkt) {
  49280. if (!this.projection) this.projection = info.srs.wkt;
  49281. else this.fallbackProjection = info.srs.wkt;
  49282. }
  49283. {
  49284. // TODO [mschuetz]: named projections that proj4 can't handle seem to cause problems.
  49285. // remove them for now
  49286. try{
  49287. proj4(this.projection);
  49288. }catch(e){
  49289. this.projection = null;
  49290. }
  49291. }
  49292. {
  49293. const attributes = new PointAttributes();
  49294. attributes.add(PointAttribute.POSITION_CARTESIAN);
  49295. attributes.add(new PointAttribute("rgba", PointAttributeTypes.DATA_TYPE_UINT8, 4));
  49296. attributes.add(new PointAttribute("intensity", PointAttributeTypes.DATA_TYPE_UINT16, 1));
  49297. attributes.add(new PointAttribute("classification", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  49298. attributes.add(new PointAttribute("gps-time", PointAttributeTypes.DATA_TYPE_DOUBLE, 1));
  49299. attributes.add(new PointAttribute("returnNumber", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  49300. attributes.add(new PointAttribute("number of returns", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  49301. attributes.add(new PointAttribute("return number", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  49302. attributes.add(new PointAttribute("source id", PointAttributeTypes.DATA_TYPE_UINT16, 1));
  49303. this.pointAttributes = attributes;
  49304. }
  49305. this.spacing =
  49306. (this.boundingBox.max.x - this.boundingBox.min.x) / this.span;
  49307. let hierarchyType = info.hierarchyType || 'json';
  49308. const dataType = info.dataType;
  49309. if (dataType == 'laszip') {
  49310. this.loader = new Potree.EptLaszipLoader();
  49311. }
  49312. else if (dataType == 'binary') {
  49313. this.loader = new Potree.EptBinaryLoader();
  49314. }
  49315. else if (dataType == 'zstandard') {
  49316. this.loader = new Potree.EptZstandardLoader();
  49317. }
  49318. else {
  49319. throw new Error('Could not read data type: ' + dataType);
  49320. }
  49321. }
  49322. };
  49323. class EptKey {
  49324. constructor(ept, b, d, x, y, z) {
  49325. this.ept = ept;
  49326. this.b = b;
  49327. this.d = d;
  49328. this.x = x || 0;
  49329. this.y = y || 0;
  49330. this.z = z || 0;
  49331. }
  49332. name() {
  49333. return this.d + '-' + this.x + '-' + this.y + '-' + this.z;
  49334. }
  49335. step(a, b, c) {
  49336. let min = this.b.min.clone();
  49337. let max = this.b.max.clone();
  49338. let dst = new Vector3().subVectors(max, min);
  49339. if (a) min.x += dst.x / 2;
  49340. else max.x -= dst.x / 2;
  49341. if (b) min.y += dst.y / 2;
  49342. else max.y -= dst.y / 2;
  49343. if (c) min.z += dst.z / 2;
  49344. else max.z -= dst.z / 2;
  49345. return new Potree.EptKey(
  49346. this.ept,
  49347. new Box3(min, max),
  49348. this.d + 1,
  49349. this.x * 2 + a,
  49350. this.y * 2 + b,
  49351. this.z * 2 + c);
  49352. }
  49353. children() {
  49354. var result = [];
  49355. for (var a = 0; a < 2; ++a) {
  49356. for (var b = 0; b < 2; ++b) {
  49357. for (var c = 0; c < 2; ++c) {
  49358. var add = this.step(a, b, c).name();
  49359. if (!result.includes(add)) result = result.concat(add);
  49360. }
  49361. }
  49362. }
  49363. return result;
  49364. }
  49365. }
  49366. class PointCloudEptGeometryNode extends PointCloudTreeNode {
  49367. constructor(ept, b, d, x, y, z) {
  49368. super();
  49369. this.ept = ept;
  49370. this.key = new Potree.EptKey(
  49371. this.ept,
  49372. b || this.ept.boundingBox,
  49373. d || 0,
  49374. x,
  49375. y,
  49376. z);
  49377. this.id = PointCloudEptGeometryNode.IDCount++;
  49378. this.geometry = null;
  49379. this.boundingBox = this.key.b;
  49380. this.tightBoundingBox = this.boundingBox;
  49381. this.spacing = this.ept.spacing / Math.pow(2, this.key.d);
  49382. this.boundingSphere = U.sphereFrom(this.boundingBox);
  49383. // These are set during hierarchy loading.
  49384. this.hasChildren = false;
  49385. this.children = { };
  49386. this.numPoints = -1;
  49387. this.level = this.key.d;
  49388. this.loaded = false;
  49389. this.loading = false;
  49390. this.oneTimeDisposeHandlers = [];
  49391. let k = this.key;
  49392. this.name = this.toPotreeName(k.d, k.x, k.y, k.z);
  49393. this.index = parseInt(this.name.charAt(this.name.length - 1));
  49394. }
  49395. isGeometryNode() { return true; }
  49396. getLevel() { return this.level; }
  49397. isTreeNode() { return false; }
  49398. isLoaded() { return this.loaded; }
  49399. getBoundingSphere() { return this.boundingSphere; }
  49400. getBoundingBox() { return this.boundingBox; }
  49401. url() { return this.ept.url + 'ept-data/' + this.filename(); }
  49402. getNumPoints() { return this.numPoints; }
  49403. filename() { return this.key.name(); }
  49404. getChildren() {
  49405. let children = [];
  49406. for (let i = 0; i < 8; i++) {
  49407. if (this.children[i]) {
  49408. children.push(this.children[i]);
  49409. }
  49410. }
  49411. return children;
  49412. }
  49413. addChild(child) {
  49414. this.children[child.index] = child;
  49415. child.parent = this;
  49416. }
  49417. load() {
  49418. if (this.loaded || this.loading) return;
  49419. if (Potree.numNodesLoading >= Potree.maxNodesLoading) return;
  49420. this.loading = true;
  49421. ++Potree.numNodesLoading;
  49422. if (this.numPoints == -1) this.loadHierarchy();
  49423. this.loadPoints();
  49424. }
  49425. loadPoints(){
  49426. this.ept.loader.load(this);
  49427. }
  49428. async loadHierarchy() {
  49429. let nodes = { };
  49430. nodes[this.filename()] = this;
  49431. this.hasChildren = false;
  49432. let eptHierarchyFile =
  49433. `${this.ept.url}ept-hierarchy/${this.filename()}.json`;
  49434. let response = await fetch(eptHierarchyFile);
  49435. let hier = await response.json();
  49436. // Since we want to traverse top-down, and 10 comes
  49437. // lexicographically before 9 (for example), do a deep sort.
  49438. var keys = Object.keys(hier).sort((a, b) => {
  49439. let [da, xa, ya, za] = a.split('-').map((n) => parseInt(n, 10));
  49440. let [db, xb, yb, zb] = b.split('-').map((n) => parseInt(n, 10));
  49441. if (da < db) return -1; if (da > db) return 1;
  49442. if (xa < xb) return -1; if (xa > xb) return 1;
  49443. if (ya < yb) return -1; if (ya > yb) return 1;
  49444. if (za < zb) return -1; if (za > zb) return 1;
  49445. return 0;
  49446. });
  49447. keys.forEach((v) => {
  49448. let [d, x, y, z] = v.split('-').map((n) => parseInt(n, 10));
  49449. let a = x & 1, b = y & 1, c = z & 1;
  49450. let parentName =
  49451. (d - 1) + '-' + (x >> 1) + '-' + (y >> 1) + '-' + (z >> 1);
  49452. let parentNode = nodes[parentName];
  49453. if (!parentNode) return;
  49454. parentNode.hasChildren = true;
  49455. let key = parentNode.key.step(a, b, c);
  49456. let node = new Potree.PointCloudEptGeometryNode(
  49457. this.ept,
  49458. key.b,
  49459. key.d,
  49460. key.x,
  49461. key.y,
  49462. key.z);
  49463. node.level = d;
  49464. node.numPoints = hier[v];
  49465. parentNode.addChild(node);
  49466. nodes[key.name()] = node;
  49467. });
  49468. }
  49469. doneLoading(bufferGeometry, tightBoundingBox, np, mean) {
  49470. bufferGeometry.boundingBox = this.boundingBox;
  49471. this.geometry = bufferGeometry;
  49472. this.tightBoundingBox = tightBoundingBox;
  49473. this.numPoints = np;
  49474. this.mean = mean;
  49475. this.loaded = true;
  49476. this.loading = false;
  49477. --Potree.numNodesLoading;
  49478. }
  49479. toPotreeName(d, x, y, z) {
  49480. var name = 'r';
  49481. for (var i = 0; i < d; ++i) {
  49482. var shift = d - i - 1;
  49483. var mask = 1 << shift;
  49484. var step = 0;
  49485. if (x & mask) step += 4;
  49486. if (y & mask) step += 2;
  49487. if (z & mask) step += 1;
  49488. name += step;
  49489. }
  49490. return name;
  49491. }
  49492. dispose() {
  49493. if (this.geometry && this.parent != null) {
  49494. this.geometry.dispose();
  49495. this.geometry = null;
  49496. this.loaded = false;
  49497. // this.dispatchEvent( { type: 'dispose' } );
  49498. for (let i = 0; i < this.oneTimeDisposeHandlers.length; i++) {
  49499. let handler = this.oneTimeDisposeHandlers[i];
  49500. handler();
  49501. }
  49502. this.oneTimeDisposeHandlers = [];
  49503. }
  49504. }
  49505. }
  49506. PointCloudEptGeometryNode.IDCount = 0;
  49507. class ExtendPointCloudOctree extends PointCloudOctree{
  49508. constructor(geometry, material){
  49509. material = material || new ExtendPointCloudMaterial();
  49510. super(geometry, material);
  49511. //xzw move from material 。 adaptive_point_size才使用
  49512. /* this.visibleNodesTexture = Utils.generateDataTexture(2048, 1, new THREE.Color(0xffffff));
  49513. this.visibleNodesTexture.minFilter = THREE.NearestFilter;
  49514. this.visibleNodesTexture.magFilter = THREE.NearestFilter; */
  49515. this.boundingBox = this.pcoGeometry.tightBoundingBox;//this.pcoGeometry.boundingBox; //boundingBox是正方体,所以换掉
  49516. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  49517. this.nodeMaxLevel = 0;//add
  49518. this.maxLevel = Infinity;
  49519. this.temp = { sizeFitToLevel:{}, opacity:{}};//add
  49520. //add
  49521. this.panos = [];
  49522. this.matrixAutoUpdate = false; //最好禁止updateMatrix 直接使用matrixWorld
  49523. this.orientationUser = 0;
  49524. this.translateUser = new Vector3;
  49525. this.rotateMatrix = new Matrix4;
  49526. this.transformMatrix = new Matrix4;// 数据集的变化矩阵
  49527. this.transformInvMatrix = new Matrix4;
  49528. this.rotateInvMatrix = new Matrix4;
  49529. this.material.spacing = this.pcoGeometry.spacing;//初始化一下 以便于设置pointsize
  49530. this.nodeMaxLevelPredict = this.predictNodeMaxLevel();//预测maxNodeLevel
  49531. this.testMaxNodeCount = this.testMaxNodeCount2 = 0;
  49532. this._visible = true;
  49533. this.pcoGeometry.addEventListener('updateNodeMaxLevel', this.updateNodeMaxLevel.bind(this));
  49534. this.isPointcloud = true; //add
  49535. }
  49536. /*
  49537. 注释:node的level从最大的box 0开始。
  49538. 且加载任意一个node必定也会加载它的所有祖先。(如visibleNodes中有一个level为4,则一定有3,2,1,0)
  49539. visibleNodes就是所有可见的node,比如:
  49540. 如果相机在0这个位置朝下,这时候的visibleNodes中只有一个level为0的node;
  49541. 而如果朝上看,上方的几个node如果在视野中占据足够大的位置的话,就会加载。
  49542. 如果相机在2这个位置朝上,这时候的visibleNodes中所包含的level为: 0,1,2
  49543. ________________
  49544. | | | |
  49545. |__2| | |
  49546. | 1 | 1 |
  49547. |_______|_______|
  49548. | |
  49549. | |
  49550. | 0 |
  49551. |_______________|
  49552. 查看box可在potree中开启
  49553. */
  49554. updateNodeMaxLevel(e){//目前点云包含node的最高level
  49555. var level = Math.max(e.level, this.nodeMaxLevel);
  49556. if(level != this.nodeMaxLevel){
  49557. this.nodeMaxLevel = level;
  49558. //viewer.dispatchEvent({type:'updateNodeMaxLevel', pointcloud: this, nodeMaxLevel:level})
  49559. console.log('updateNodeMaxLevel ' + this.dataset_id + " : "+ this.nodeMaxLevel);
  49560. this.setPointLevel();//重新计算
  49561. if(!Potree.settings.sizeFitToLevel){
  49562. this.changePointSize();
  49563. }
  49564. }
  49565. }//注:在没有加载到真实的 nodeMaxLevel之前,点云会显示得偏大
  49566. //panoEdit时比预测值小很多?
  49567. testMaxNodeLevel(camera){//手动使maxLevel达到最高,从而迫使updateNodeMaxLevel。 因为Potree.settings.pointDensity 不为 'high'时,maxLevel不是所加载的最高,就很容易加载不出下一个层级,导致无法知道nodeMaxLevel
  49568. if(this.testMaxNodeLevelDone ) return
  49569. //if(this.nodeMaxLevel > this.nodeMaxLevelPredict.min )return
  49570. if( this.nodeMaxLevel==0 )return true
  49571. if(camera.type == "OrthographicCamera" || this.testMaxNodeCount < 50){
  49572. if(!Potree.Utils.isInsideFrustum(this.bound, camera)){
  49573. return true
  49574. }
  49575. }else if( !viewer.atDatasets.includes(this))return true //否则老远就count++
  49576. let levels = this.visibleNodes.map(e=>e.getLevel());
  49577. let actMaxLevel = Math.max.apply(null, levels); //实际加载到的最高的node level
  49578. if(actMaxLevel < this.maxLevel)return true// 还没加载到能加载到的最高。 但在细节设置较低时,排除作用微弱。
  49579. //尝试加载出更高级的level
  49580. let old = this.maxLevel;
  49581. this.maxLevel = 12;
  49582. //var visibleNodes1 = this.visibleNodes.map(e=>e.getLevel())
  49583. //console.log('visibleNodes1',visibleNodes1)
  49584. Potree.updatePointClouds([this], viewer.scene.getActiveCamera(), viewer.mainViewport.resolution );
  49585. //不在camera可视范围内还是加载不出来。即使临时修改位置
  49586. var visibleNodes2 = this.visibleNodes.map(e=>e.getLevel());
  49587. //console.log('visibleNodes2',visibleNodes2)
  49588. this.maxLevel = old;
  49589. this.testMaxNodeCount ++;
  49590. viewer.testMaxNodeCount ++;
  49591. //console.log('testMaxNodeCount', this.dataset_id, this.testMaxNodeCount, 'nodeMaxLevel', this.nodeMaxLevel )
  49592. if( this.testMaxNodeCount == Potree.config.testNodeCount1 ){//差不多等当前所在数据集nodeMaxLevel加载出来
  49593. this.changePointSize(); //重新更新一下大小。因之前用的是nodeMaxLevelPredict (防止刚开始因nodeMaxLevel没涨完,导致过大的点云突然出现
  49594. }
  49595. if(this.testMaxNodeCount > 100){
  49596. console.log('testMaxNodeLevel次数超出,强制结束:',this.dataset_id, this.nodeMaxLevel, this.nodeMaxLevelPredict.min);
  49597. this.testMaxNodeLevelDone = 'moreThanMaxCount';
  49598. return; //在可以看见点云的情况下,超时,有可能是预测的max是错的
  49599. }
  49600. if(this.nodeMaxLevel < this.nodeMaxLevelPredict.min) return true //仍需要继续testMaxNodeLevel
  49601. this.testMaxNodeCount2 ++; // 已经> this.nodeMaxLevelPredict.min 后,开始计数。因为min可能低于真实nodeMaxLevel所以要再试几次
  49602. /* if(this.name == 'SS-t-CWmVgzP4XU'){
  49603. console.log('SS-t-CWmVgzP4XU count++')
  49604. } */
  49605. if(this.testMaxNodeCount2 < 50) return true //再试几次 ( 主要是细节调得低时需要多测几次才加载到
  49606. this.testMaxNodeLevelDone = true;
  49607. }
  49608. updateMatrixWorld(force){//add
  49609. super.updateMatrixWorld(force);
  49610. this.matrixWorldInverse = this.matrixWorld.clone().invert();
  49611. }
  49612. setPointLevel(){
  49613. var pointDensity = Potree.settings.pointDensity;
  49614. var config = Potree.config.pointDensity[pointDensity];
  49615. if(!config)return
  49616. /* if(this.testingMaxLevel){
  49617. this.maxLevel = 12;//先加载到最大的直到测试完毕。由于5个level为一组来加载,所以如果写4最高能加载到5,如果写5最高能加载到下一个级别的最高也就是10
  49618. //console.log('maxLevel: '+e.maxLevel + ' testingMaxLevel中 ' )
  49619. }else{ */
  49620. let percent = config.percentByUser && Potree.settings.UserDensityPercent != void 0 ? Potree.settings.UserDensityPercent : config.maxLevelPercent;
  49621. this.maxLevel = Math.round( percent * this.nodeMaxLevel);
  49622. //console.log('maxLevel: '+e.maxLevel + ', density : '+Potree.settings.pointDensity, ", percent :"+percent);
  49623. if(Potree.settings.sizeFitToLevel){
  49624. this.changePointSize();
  49625. }
  49626. this.changePointOpacity();
  49627. //}
  49628. viewer.dispatchEvent('content_changed');
  49629. }
  49630. //预测可能的nodeMaxLevel:
  49631. predictNodeMaxLevel(){//预测maxNodeLevel。 可能只适用于我们相机拍的点云
  49632. //let spacing = {min:0.005, max:0.014};//最小节的两点间的距离 ,获得方法:spacing / Math.pow(2, nodeMaxLevel)。 目前观测的我们自己拍的这个数值的范围大概是这样
  49633. let spacing = {min:0.006, max:0.0082}; //0.006743906065821648 0.0080347936
  49634. let min = Math.log2(this.material.spacing / spacing.max);
  49635. let max = Math.log2(this.material.spacing / spacing.min);
  49636. //console.log('predictNodeMaxLevel:', this.name , min, max )
  49637. return {min, max}
  49638. }
  49639. getHighestNodeSpacing(){
  49640. return this.material.spacing / Math.pow(2, this.nodeMaxLevel) //前提是这个nodeMaxLevel是准确的
  49641. }
  49642. updateMaterial (material, visibleNodes, camera, renderer, resolution) {//改
  49643. material.fov = camera.fov * (Math.PI / 180);
  49644. /* material.screenWidth = renderer.domElement.clientWidth;
  49645. material.screenHeight = renderer.domElement.clientHeight; */
  49646. material.resolution = resolution;
  49647. material.spacing = this.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  49648. material.near = camera.near;
  49649. material.far = camera.far;
  49650. material.uniforms.octreeSize.value = this.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  49651. }
  49652. pick(viewer, viewport, camera, ray, params = {}){//改
  49653. let renderer = viewer.renderer;
  49654. let pRenderer = viewer.pRenderer;
  49655. viewer.addTimeMark('pick','start');
  49656. let getVal = (a, b) => a != void 0 ? a : b;
  49657. let pickWindowSize_ = MathUtils$1.clamp( Math.round((1.1-this.maxLevel/this.nodeMaxLevel)*80), 5, 100);
  49658. let pickWindowSize = getVal(params.pickWindowSize, pickWindowSize_ ); /* 65 */ //拾取像素边长,越小越精准,但点云稀疏的话可能容易出现识别不到的情况。 另外左下侧会有缝隙无法识别到,缝隙大小和这个值有关//突然发现pickWindowSize在一百以内的变化对pick费时影响甚微,1和100差1毫秒不到,但400时会多4毫秒
  49659. if(camera.type == 'OrthographicCamera'){
  49660. var cameraDir = new Vector3(0,0,-1).applyQuaternion(camera.quaternion);
  49661. pickWindowSize *= 4; //pointsize比较大时截取太小会没多少点可以选
  49662. }
  49663. let pickOutsideClipRegion = getVal(params.pickOutsideClipRegion, false);
  49664. let size = viewport ? viewport.resolution : renderer.getSize(new Vector2());
  49665. let width = Math.ceil(getVal(params.width, size.width)); //renderTarget大小。影响识别精度
  49666. let height = Math.ceil(getVal(params.height, size.height));
  49667. let screenshot = ()=>{
  49668. if(window.testScreen){
  49669. let dataUrl = Potree.Utils.renderTargetToDataUrl(pickState.renderTarget, width, height, renderer);
  49670. Common.downloadFile(dataUrl, 'screenshot.jpg'); //为什么图片上不是只有pickWindowSize区域有颜色??
  49671. window.testScreen = 0;
  49672. }
  49673. };
  49674. let pointSizeType = getVal(params.pointSizeType, this.material.pointSizeType);
  49675. let pointSize = getVal(params.pointSize, this.material.size);
  49676. let nodes = this.nodesOnRay(this.visibleNodes, ray);
  49677. if (nodes.length === 0) {
  49678. return null;
  49679. }
  49680. //console.log('nodes.length != 0', this.name)
  49681. if (!this.pickState) {
  49682. let scene = new Scene();
  49683. let material = new ExtendPointCloudMaterial();
  49684. material.activeAttributeName = "indices";
  49685. let renderTarget = new WebGLRenderTarget(
  49686. 1, 1,
  49687. { minFilter: LinearFilter,
  49688. magFilter: NearestFilter,
  49689. format: RGBAFormat }
  49690. );
  49691. this.pickState = {
  49692. renderTarget: renderTarget,
  49693. material: material,
  49694. scene: scene
  49695. };
  49696. };
  49697. let pickState = this.pickState;
  49698. let pickMaterial = pickState.material;
  49699. { // update pick material
  49700. pickMaterial.pointSizeType = pointSizeType;
  49701. //pickMaterial.shape = this.material.shape;
  49702. pickMaterial.shape = Potree.PointShape.PARABOLOID;
  49703. pickMaterial.uniforms.uFilterReturnNumberRange.value = this.material.uniforms.uFilterReturnNumberRange.value;
  49704. pickMaterial.uniforms.uFilterNumberOfReturnsRange.value = this.material.uniforms.uFilterNumberOfReturnsRange.value;
  49705. pickMaterial.uniforms.uFilterGPSTimeClipRange.value = this.material.uniforms.uFilterGPSTimeClipRange.value;
  49706. pickMaterial.uniforms.uFilterPointSourceIDClipRange.value = this.material.uniforms.uFilterPointSourceIDClipRange.value;
  49707. pickMaterial.activeAttributeName = "indices";
  49708. pickMaterial.size = pointSize;
  49709. pickMaterial.uniforms.minSize.value = this.material.uniforms.minSize.value;
  49710. pickMaterial.uniforms.maxSize.value = this.material.uniforms.maxSize.value;
  49711. pickMaterial.classification = this.material.classification;
  49712. pickMaterial.recomputeClassification();
  49713. //pickClipped判断转移到上一层函数
  49714. let {bigClipInBox,clipBoxes_in,clipBoxes_out} = this.material;
  49715. pickMaterial.setClipBoxes(bigClipInBox, clipBoxes_in, clipBoxes_out, []);
  49716. this.updateMaterial(pickMaterial, nodes, camera, renderer, new Vector2(width, height));
  49717. }
  49718. pickState.renderTarget.setSize(width, height); //仅绘制屏幕大小的,而不乘以devicePixelRatio
  49719. let pixelPos = new Vector2(params.x, params.y);
  49720. let gl = renderer.getContext();
  49721. gl.enable(gl.SCISSOR_TEST);
  49722. gl.scissor( //规定渲染范围,只渲染一小块
  49723. parseInt(pixelPos.x - (pickWindowSize - 1) / 2),
  49724. parseInt(pixelPos.y - (pickWindowSize - 1) / 2),
  49725. parseInt(pickWindowSize), parseInt(pickWindowSize));
  49726. renderer.state.buffers.depth.setTest(pickMaterial.depthTest);
  49727. renderer.state.buffers.depth.setMask(pickMaterial.depthWrite);
  49728. renderer.state.setBlending(NoBlending);
  49729. { // RENDER
  49730. renderer.setRenderTarget(pickState.renderTarget);
  49731. gl.clearColor(0, 0, 0, 0);
  49732. renderer.clear(true, true, true);
  49733. let tmp = this.material;
  49734. this.material = pickMaterial;
  49735. pRenderer.renderOctree(this, nodes, camera, pickState.renderTarget);
  49736. screenshot();
  49737. this.material = tmp;
  49738. }
  49739. let clamp = (number, min, max) => Math.min(Math.max(min, number), max);
  49740. let x = parseInt(clamp(pixelPos.x - (pickWindowSize - 1) / 2, 0, width));
  49741. let y = parseInt(clamp(pixelPos.y - (pickWindowSize - 1) / 2, 0, height));
  49742. /* let w = parseInt(Math.min(x + pickWindowSize, width) - x);
  49743. let h = parseInt(Math.min(y + pickWindowSize, height) - y); */
  49744. let pixelCount = pickWindowSize * pickWindowSize;//w * h;
  49745. let buffer = new Uint8Array(4 * pixelCount);
  49746. //w<pickWindowSize会报错
  49747. gl.readPixels(x, y, pickWindowSize, pickWindowSize, gl.RGBA, gl.UNSIGNED_BYTE, buffer); //这句花费最多时间 pc:2-4, 即使只有1*1像素
  49748. renderer.setRenderTarget(null);
  49749. renderer.state.reset();
  49750. renderer.setScissorTest(false);
  49751. gl.disable(gl.SCISSOR_TEST);
  49752. let pixels = buffer;
  49753. let ibuffer = new Uint32Array(buffer.buffer); //四个数整合成一个
  49754. // console.log(pixels.join(','))
  49755. // find closest hit inside pixelWindow boundaries
  49756. let min = Number.MAX_VALUE;
  49757. let hits = [], hits2 = [], rSquare;
  49758. if(!params.all){
  49759. let r = MathUtils$1.clamp(Math.floor(pickWindowSize / 2),1, 40);
  49760. rSquare = r * r;
  49761. }
  49762. for (let u = 0; u < pickWindowSize; u++) {
  49763. for (let v = 0; v < pickWindowSize; v++) {
  49764. let offset = (u + v * pickWindowSize);
  49765. let distance = Math.pow(u - (pickWindowSize - 1) / 2, 2) + Math.pow(v - (pickWindowSize - 1) / 2, 2);
  49766. let pcIndex = pixels[4 * offset + 3];//nodes index(第四位)
  49767. pixels[4 * offset + 3] = 0; //去除nodes index后剩下的是index(前三位)
  49768. let pIndex = ibuffer[offset]; //index
  49769. if(!(pcIndex === 0 && pIndex === 0) && (pcIndex !== undefined) && (pIndex !== undefined)){
  49770. let hit = {
  49771. pIndex: pIndex,
  49772. pcIndex: pcIndex,
  49773. distanceToCenter: distance
  49774. };
  49775. if(params.all){
  49776. hits.push(hit);
  49777. }else {
  49778. if(hits.length > 0){//最后选取的是最靠近鼠标的那个pick
  49779. if(distance < hits[0].distanceToCenter){
  49780. hits[0] = hit;
  49781. }
  49782. }else {
  49783. hits.push(hit);
  49784. }
  49785. if(distance < rSquare) hits2.push(hit); //add
  49786. }
  49787. }
  49788. }
  49789. }
  49790. if(!params.all){
  49791. if(hits2.length){//add
  49792. hits = hits2;
  49793. }
  49794. }
  49795. // { // DEBUG: show panel with pick image
  49796. // let img = Utils.pixelsArrayToImage(buffer, w, h);
  49797. // let screenshot = img.src;
  49798. // if(!this.debugDIV){
  49799. // this.debugDIV = $(`
  49800. // <div id="pickDebug"
  49801. // style="position: absolute;
  49802. // right: 400px; width: 300px;
  49803. // bottom: 44px; width: 300px;
  49804. // z-index: 1000;
  49805. // "></div>`);
  49806. // $(document.body).append(this.debugDIV);
  49807. // }
  49808. // this.debugDIV.empty();
  49809. // this.debugDIV.append($(`<img src="${screenshot}"
  49810. // style="transform: scaleY(-1); width: 300px"/>`));
  49811. // //$(this.debugWindow.document).append($(`<img src="${screenshot}"/>`));
  49812. // //this.debugWindow.document.write('<img src="'+screenshot+'"/>');
  49813. // }
  49814. for(let hit of hits){
  49815. let point = {};
  49816. if (!nodes[hit.pcIndex]) {
  49817. return null;
  49818. }
  49819. let node = nodes[hit.pcIndex];
  49820. let pc = node.sceneNode;
  49821. let geometry = node.geometryNode.geometry;
  49822. for(let attributeName in geometry.attributes){
  49823. let attribute = geometry.attributes[attributeName];
  49824. if (attributeName === 'position') {
  49825. let x = attribute.array[3 * hit.pIndex + 0];
  49826. let y = attribute.array[3 * hit.pIndex + 1];
  49827. let z = attribute.array[3 * hit.pIndex + 2];
  49828. let position = new Vector3(x, y, z);
  49829. position.applyMatrix4( pc.matrixWorld );
  49830. point[attributeName] = position;
  49831. //add
  49832. if(!params.all){
  49833. if(camera.type == 'OrthographicCamera'){
  49834. let vec = new Vector3().subVectors(position, camera.position);
  49835. hit.disSquare = vec.projectOnVector( cameraDir ).lengthSq(); //只考虑到相机的垂直距离
  49836. }else {
  49837. hit.disSquare = camera.position.distanceToSquared(position);
  49838. }
  49839. }
  49840. } else if (attributeName === 'indices') {
  49841. } else {
  49842. let values = attribute.array.slice(attribute.itemSize * hit.pIndex, attribute.itemSize * (hit.pIndex + 1)) ;
  49843. if(attribute.potree){
  49844. const {scale, offset} = attribute.potree;
  49845. values = values.map(v => v / scale + offset);
  49846. }
  49847. point[attributeName] = values;
  49848. //debugger;
  49849. //if (values.itemSize === 1) {
  49850. // point[attribute.name] = values.array[hit.pIndex];
  49851. //} else {
  49852. // let value = [];
  49853. // for (let j = 0; j < values.itemSize; j++) {
  49854. // value.push(values.array[values.itemSize * hit.pIndex + j]);
  49855. // }
  49856. // point[attribute.name] = value;
  49857. //}
  49858. }
  49859. }
  49860. hit.point = point;
  49861. }
  49862. viewer.addTimeMark('pick','end');
  49863. if(params.all){
  49864. return hits.map(hit => hit.point);
  49865. }else {
  49866. if(hits.length === 0){
  49867. return null;
  49868. }else {
  49869. //为了防止透过点云缝隙,选到后排的点云,将选取的位置离相机的距离考虑进去。倾向选择离相机近、且离鼠标位置近的点。(否则按照原方案只选离鼠标位置最近的,可能从高楼不小心走到下层,导航选点也是)
  49870. let sorted1 = hits.sort( (a, b) => a.disSquare - b.disSquare ).slice();
  49871. let nearest = sorted1[0]; //return nearest.point; //直接用最近点 在点云稀疏时不太跟手,如地面上,最近点往往在鼠标下方
  49872. let r;
  49873. if(camera.type != 'OrthographicCamera'){
  49874. let ratio = 0.1; //系数越大越不跟手,但更容易pick近处的。 (当pick的点较远时,获取框内的点距离可能差别很大,就要所以除以disSquare)
  49875. r = rSquare/Math.max(nearest.disSquare,0.001) * ratio;
  49876. }else {
  49877. r = 10; //大一点才能pick到表面的点,但太大了有时不跟手,且总容易吸附到近点
  49878. }
  49879. hits.forEach( hit=>{
  49880. let disDiff = hit.disSquare - nearest.disSquare; //和最近点的偏差
  49881. hit.disDiff = disDiff;
  49882. hit.score = -hit.distanceToCenter - disDiff * r;
  49883. });
  49884. let sorted2 = hits.sort( (a, b) => b.score - a.score );
  49885. //console.log(sorted2[0].point.position.z )
  49886. return sorted2[0].point;
  49887. }
  49888. }
  49889. }
  49890. // 设置点大小
  49891. changePointSize(num, sizeFitToLevel) {
  49892. let size, nodeMaxLevel;
  49893. if(this.material.pointSizeType != PointSizeType.ATTENUATED){
  49894. num && (size = num / Potree.config.material.realPointSize / 1.3);
  49895. }else {
  49896. let num_ = num;
  49897. if (num_ == void 0) {
  49898. num_ = this.temp.pointSize;
  49899. } else {
  49900. this.temp.pointSize = num_;
  49901. }
  49902. num_ = num_ / (Potree.config.material.realPointSize / Potree.config.material.pointSize); //兼容
  49903. num_ = Math.pow(num_, 1.05) * 6;
  49904. nodeMaxLevel = this.testMaxNodeCount >= Potree.config.testNodeCount1 ? this.nodeMaxLevel : this.nodeMaxLevelPredict.max; //防止刚开始因nodeMaxLevel没涨完,导致过大的点云突然出现
  49905. if(sizeFitToLevel || Potree.settings.sizeFitToLevel){//按照点云质量来调整的版本: 近似将pointSizeType换成ADAPTIVE
  49906. let str = this.temp.pointSize+':'+this.maxLevel+':'+ nodeMaxLevel;
  49907. let value = this.temp.sizeFitToLevel[str]; //储存。防止每次渲染(反复切换density)都要算。
  49908. if(value){
  49909. size = value;
  49910. }else {
  49911. let base = this.material.spacing / Math.pow(2, this.maxLevel); //点云大小在level为0时设置为spacing,每长一级,大小就除以2. (不同场景还是会有偏差)
  49912. base *= nodeMaxLevel > 0 ? Math.max(0.1, Math.pow(this.maxLevel / nodeMaxLevel, 1.4)) : 0.1; //低质量的缩小点,因为视觉上看太大了。navvis是不铺满的,我们也留一点缝隙(但是ortho是不用缩小的,如果能分开判断就好了)
  49913. size = base * 5 * num_;/* * window.devicePixelRatio */
  49914. //在t-8BCqxQAr93 会议室 和 t-e2Kb2iU 隧道 两个场景里调节,因为它们的spacing相差较大,观察会议室墙壁的龟裂程度
  49915. this.temp.sizeFitToLevel[str] = size;
  49916. }
  49917. }else {
  49918. /* let base = 0.007; */ let base = this.material.spacing / Math.pow(2, nodeMaxLevel); //点云大小在level为0时设置为spacing,每长一级,大小就除以2
  49919. //base的数值理论上应该是右侧算出来的,但发现有的场景nodeMaxLevel和nodeMaxLevelPredict差别较大的点云显示也过大,而直接换成固定值反而可以适应所有场景。该固定值来源于 getHighestNodeSpacing 最小值,修改了下。(会不会是我们的相机其实该值是固定的,根据该值算出的spacing才是有误差的? 如果换了相机是否要改值?)
  49920. //2022-12-21又换回非固定值。因为有的场景如SS-t-t01myDqnfE的两个数据集密集程度差别很大,应该将稀疏点云的大小设置的大些。 但是这样的缺点是两个数据集因相接处有大有小无法融合。
  49921. size = base * 5 * num_; /* * window.devicePixelRatio */
  49922. }
  49923. }
  49924. //console.log('changePointSize:' + this.dataset_id + ' , num: ' + (num && num.toPrecision(3)) + ' , size: ' + size.toPrecision(3), 'nodeMaxLevel', nodeMaxLevel.toPrecision(3), 'testMaxNodeCount',this.testMaxNodeCount /* this.material.spacing */)
  49925. if(size){
  49926. if(Potree.settings.sortCloudMat){//被废弃,不给material分组了
  49927. this.size = size;this.material.size = size;
  49928. }else {
  49929. this.material.size = size;
  49930. }
  49931. }
  49932. viewer.dispatchEvent('content_changed');
  49933. }
  49934. // 设置点透明度
  49935. changePointOpacity(num, canMoreThanOne) {
  49936. //num:0-1 navvis用的是亮度
  49937. if (num == void 0) {
  49938. num = this.temp.pointOpacity;
  49939. } else {
  49940. this.temp.pointOpacity = num;
  49941. }
  49942. if(Potree.settings.notAdditiveBlending){
  49943. return this.material.opacity = num
  49944. }
  49945. let opacity;
  49946. if (num == 1) {
  49947. opacity = 1;
  49948. } else {
  49949. let str = (Potree.settings.sizeFitToLevel?'sizeFit:':'')+ (canMoreThanOne ? 'canMoreThanOne:':'') +this.temp.pointOpacity+':'+this.maxLevel+':'+this.nodeMaxLevel;
  49950. let value = this.temp.opacity[str]; //储存。防止每次渲染(反复切换density)都要算。
  49951. if(value){
  49952. opacity = value;
  49953. }else {
  49954. if(Potree.settings.sizeFitToLevel){//按照点云质量来调整的版本:
  49955. let base = this.material.spacing / Math.pow(1.5, this.maxLevel); //随着level提高,点云重叠几率增多
  49956. let minBase = this.material.spacing / Math.pow(1.5, this.nodeMaxLevel);
  49957. let ratio = Math.min(1 / base, 1 / minBase / 3); //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
  49958. opacity = base * ratio * num;
  49959. if(!canMoreThanOne){
  49960. opacity = MathUtils$1.clamp(opacity, 0, 0.999); //到1就不透明了(可能出现一段一样)
  49961. }
  49962. }else {
  49963. let base = this.material.spacing / Math.pow(1.8, this.maxLevel);
  49964. let minBase = this.material.spacing / Math.pow(1.8, this.nodeMaxLevel);
  49965. //console.log(1 / base, 1 / minBase / 6)
  49966. let ratio = Math.min(1 / base, 1 / minBase / 6); //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
  49967. opacity = base * ratio * num;
  49968. if(!canMoreThanOne){
  49969. opacity = MathUtils$1.clamp(opacity, 0, 0.999); //到1就不透明了(可能出现一段一样)
  49970. }
  49971. }
  49972. this.temp.opacity[str] = opacity;
  49973. }
  49974. //缺点:防止颜色过亮主要是相机离远时,当在漫游点处由于离点云太近,可能会导致高质量点云看起来很暗。
  49975. }
  49976. //console.log('changePointOpacity ' + this.dataset_id + ', num : ' + num + ' , opacity : ' + this.material.opacity) //检查是否做到了低质量时num==opacity,中质量opacity稍小于num,高质量更小
  49977. if(Potree.settings.sortCloudMat){
  49978. this.opacity = opacity; this.material.opacity = opacity;
  49979. }else {
  49980. this.material.opacity = opacity;
  49981. }
  49982. viewer.dispatchEvent('content_changed');
  49983. }
  49984. updateBound(){
  49985. var boundingBox_ = this.pcoGeometry.tightBoundingBox.clone().applyMatrix4(this.matrixWorld);//tightBoundingBox是点云原始的bound,但经过(绕z)旋转后bound有所改变,比之前体积更大。
  49986. this.bound = boundingBox_;
  49987. this.bound2 = this.getBoundWithPanos();
  49988. }
  49989. getBoundWithPanos(){//确保panoBound在内的bound
  49990. let bound = this.bound.clone();
  49991. this.panos.forEach(pano=>{
  49992. let panoBound = new Box3;
  49993. panoBound.expandByPoint(pano.position);
  49994. panoBound.expandByVector(new Vector3(1,1,1));//give pano a margin
  49995. bound.union(panoBound);
  49996. });
  49997. return bound
  49998. }
  49999. getPanosBound(){//仅由所有pano构成的bound
  50000. if(this.panos.length > 0){
  50001. let minSize = new Vector3(1,1,1);
  50002. this.panosBound = math.getBoundByPoints(this.panos.map(e=>e.position), minSize);
  50003. }else {
  50004. this.panosBound = null;
  50005. }
  50006. }
  50007. getUnrotBoundPoint(type){//获取没有旋转的tightBounding的水平四个点
  50008. //如果alighment支持任意轴旋转,水平面上看到的可能就是六边形了,失去意义,到时候不能用这个。也可以若只绕z旋转, 使用tightBoundingBox,否则bound
  50009. let bound = this.pcoGeometry.tightBoundingBox;
  50010. if(type == 'all'){
  50011. return [new Vector3(bound.min.x, bound.min.y, bound.min.z),
  50012. new Vector3(bound.max.x, bound.min.y, bound.min.z),
  50013. new Vector3(bound.max.x, bound.max.y,bound.min.z),
  50014. new Vector3(bound.min.x, bound.max.y,bound.min.z),
  50015. new Vector3(bound.min.x, bound.min.y, bound.max.z),
  50016. new Vector3(bound.max.x, bound.min.y, bound.max.z),
  50017. new Vector3(bound.max.x, bound.max.y,bound.max.z),
  50018. new Vector3(bound.min.x, bound.max.y,bound.max.z),
  50019. ].map(e=>e.applyMatrix4(this.matrixWorld))
  50020. }else
  50021. return [new Vector3(bound.min.x, bound.min.y,0),
  50022. new Vector3(bound.max.x, bound.min.y,0),
  50023. new Vector3(bound.max.x, bound.max.y,0),
  50024. new Vector3(bound.min.x, bound.max.y,0),
  50025. ].map(e=>e.applyMatrix4(this.matrixWorld))
  50026. }
  50027. getVolume(){
  50028. /* var points = this.getUnrotBoundPoint() -----在只绕z轴旋转时这么写也行
  50029. var area = Math.abs(math.getArea(points))
  50030. return area * (this.bound.max.z - this.bound.min.z) */
  50031. let bound = this.pcoGeometry.tightBoundingBox.clone();
  50032. let size = bound.getSize(new Vector3);
  50033. return size.x * size.y * size.z
  50034. }
  50035. ifContainsPoint(pos){//pos是否坐落于tightBound内
  50036. /* if(!this.bound || !this.bound.containsPoint(pos))return ---这样写也行
  50037. var points = this.getUnrotBoundPoint()
  50038. return math.isPointInArea(points, null, pos) */
  50039. //要把tightBoundingBox想象成一个volumeBox
  50040. let box = this.pcoGeometry.tightBoundingBox;
  50041. let center = box.getCenter(new Vector3);
  50042. let size = box.getSize(new Vector3);
  50043. let boxMatrix = new Matrix4().setPosition(center.x,center.y,center.z);
  50044. boxMatrix.scale(size);
  50045. boxMatrix.premultiply(this.matrixWorld);
  50046. return Potree.Utils.isIntersectBox(pos, boxMatrix)
  50047. }
  50048. intersectBox(boxWorldMatrix){
  50049. let boxM = boxWorldMatrix.clone().premultiply(this.matrixWorld.clone().invert()); //box乘上点云逆矩阵 (因为点云的忽略掉其matrixWorld, 为了保持相对位置不变,box要左乘matrixWorld的逆)(因第一个参数bound不好变形,第二个参数box可以)
  50050. return Potree.Utils.isIntersectBox(this.pcoGeometry.tightBoundingBox, boxM)
  50051. }
  50052. }
  50053. class ProfileData {
  50054. constructor (profile) {
  50055. this.profile = profile;
  50056. this.segments = [];
  50057. this.boundingBox = new Box3();
  50058. for (let i = 0; i < profile.points.length - 1; i++) {
  50059. let start = profile.points[i];
  50060. let end = profile.points[i + 1];
  50061. let startGround = new Vector3(start.x, start.y, 0);
  50062. let endGround = new Vector3(end.x, end.y, 0);
  50063. let center = new Vector3().addVectors(endGround, startGround).multiplyScalar(0.5);
  50064. let length = startGround.distanceTo(endGround);
  50065. let side = new Vector3().subVectors(endGround, startGround).normalize();
  50066. let up = new Vector3(0, 0, 1);
  50067. let forward = new Vector3().crossVectors(side, up).normalize();
  50068. let N = forward;
  50069. let cutPlane = new Plane().setFromNormalAndCoplanarPoint(N, startGround);
  50070. let halfPlane = new Plane().setFromNormalAndCoplanarPoint(side, center);
  50071. let segment = {
  50072. start: start,
  50073. end: end,
  50074. cutPlane: cutPlane,
  50075. halfPlane: halfPlane,
  50076. length: length,
  50077. points: new Points$1()
  50078. };
  50079. this.segments.push(segment);
  50080. }
  50081. }
  50082. size () {
  50083. let size = 0;
  50084. for (let segment of this.segments) {
  50085. size += segment.points.numPoints;
  50086. }
  50087. return size;
  50088. }
  50089. };
  50090. class ProfileRequest {
  50091. constructor (pointcloud, profile, maxDepth, callback) {
  50092. this.pointcloud = pointcloud;
  50093. this.profile = profile;
  50094. this.maxDepth = maxDepth || Number.MAX_VALUE;
  50095. this.callback = callback;
  50096. this.temporaryResult = new ProfileData(this.profile);
  50097. this.pointsServed = 0;
  50098. this.highestLevelServed = 0;
  50099. this.priorityQueue = new BinaryHeap(function (x) { return 1 / x.weight; });
  50100. this.initialize();
  50101. }
  50102. initialize () {
  50103. this.priorityQueue.push({node: this.pointcloud.pcoGeometry.root, weight: Infinity});
  50104. };
  50105. // traverse the node and add intersecting descendants to queue
  50106. traverse (node) {
  50107. let stack = [];
  50108. for (let i = 0; i < 8; i++) {
  50109. let child = node.children[i];
  50110. if (child && this.pointcloud.nodeIntersectsProfile(child, this.profile)) {
  50111. stack.push(child);
  50112. }
  50113. }
  50114. while (stack.length > 0) {
  50115. let node = stack.pop();
  50116. let weight = node.boundingSphere.radius;
  50117. this.priorityQueue.push({node: node, weight: weight});
  50118. // add children that intersect the cutting plane
  50119. if (node.level < this.maxDepth) {
  50120. for (let i = 0; i < 8; i++) {
  50121. let child = node.children[i];
  50122. if (child && this.pointcloud.nodeIntersectsProfile(child, this.profile)) {
  50123. stack.push(child);
  50124. }
  50125. }
  50126. }
  50127. }
  50128. }
  50129. update(){
  50130. if(!this.updateGeneratorInstance){
  50131. this.updateGeneratorInstance = this.updateGenerator();
  50132. }
  50133. let result = this.updateGeneratorInstance.next();
  50134. if(result.done){
  50135. this.updateGeneratorInstance = null;
  50136. }
  50137. }
  50138. * updateGenerator(){
  50139. // load nodes in queue
  50140. // if hierarchy expands, also load nodes from expanded hierarchy
  50141. // once loaded, add data to this.points and remove node from queue
  50142. // only evaluate 1-50 nodes per frame to maintain responsiveness
  50143. let start = performance.now();
  50144. let maxNodesPerUpdate = 1;
  50145. let intersectedNodes = [];
  50146. for (let i = 0; i < Math.min(maxNodesPerUpdate, this.priorityQueue.size()); i++) {
  50147. let element = this.priorityQueue.pop();
  50148. let node = element.node;
  50149. if(node.level > this.maxDepth){
  50150. continue;
  50151. }
  50152. if (node.loaded) {
  50153. // add points to result
  50154. intersectedNodes.push(node);
  50155. exports.lru.touch(node);
  50156. this.highestLevelServed = Math.max(node.getLevel(), this.highestLevelServed);
  50157. var geom = node.pcoGeometry;
  50158. var hierarchyStepSize = geom ? geom.hierarchyStepSize : 1;
  50159. var doTraverse = node.getLevel() === 0 ||
  50160. (node.level % hierarchyStepSize === 0 && node.hasChildren);
  50161. if (doTraverse) {
  50162. this.traverse(node);
  50163. }
  50164. } else {
  50165. node.load();
  50166. this.priorityQueue.push(element);
  50167. }
  50168. }
  50169. if (intersectedNodes.length > 0) {
  50170. for(let done of this.getPointsInsideProfile(intersectedNodes, this.temporaryResult)){
  50171. if(!done){
  50172. //console.log("updateGenerator yields");
  50173. yield false;
  50174. }
  50175. }
  50176. if (this.temporaryResult.size() > 100) {
  50177. this.pointsServed += this.temporaryResult.size();
  50178. this.callback.onProgress({request: this, points: this.temporaryResult});
  50179. this.temporaryResult = new ProfileData(this.profile);
  50180. }
  50181. }
  50182. if (this.priorityQueue.size() === 0) {
  50183. // we're done! inform callback and remove from pending requests
  50184. if (this.temporaryResult.size() > 0) {
  50185. this.pointsServed += this.temporaryResult.size();
  50186. this.callback.onProgress({request: this, points: this.temporaryResult});
  50187. this.temporaryResult = new ProfileData(this.profile);
  50188. }
  50189. this.callback.onFinish({request: this});
  50190. let index = this.pointcloud.profileRequests.indexOf(this);
  50191. if (index >= 0) {
  50192. this.pointcloud.profileRequests.splice(index, 1);
  50193. }
  50194. }
  50195. yield true;
  50196. };
  50197. * getAccepted(numPoints, node, matrix, segment, segmentDir, points, totalMileage){
  50198. let checkpoint = performance.now();
  50199. let accepted = new Uint32Array(numPoints);
  50200. let mileage = new Float64Array(numPoints);
  50201. let acceptedPositions = new Float32Array(numPoints * 3);
  50202. let numAccepted = 0;
  50203. let pos = new Vector3();
  50204. let svp = new Vector3();
  50205. let view = new Float32Array(node.geometry.attributes.position.array);
  50206. for (let i = 0; i < numPoints; i++) {
  50207. pos.set(
  50208. view[i * 3 + 0],
  50209. view[i * 3 + 1],
  50210. view[i * 3 + 2]);
  50211. pos.applyMatrix4(matrix);
  50212. let distance = Math.abs(segment.cutPlane.distanceToPoint(pos));
  50213. let centerDistance = Math.abs(segment.halfPlane.distanceToPoint(pos));
  50214. if (distance < this.profile.width / 2 && centerDistance < segment.length / 2) {
  50215. svp.subVectors(pos, segment.start);
  50216. let localMileage = segmentDir.dot(svp);
  50217. accepted[numAccepted] = i;
  50218. mileage[numAccepted] = localMileage + totalMileage;
  50219. points.boundingBox.expandByPoint(pos);
  50220. pos.sub(this.pointcloud.position);
  50221. acceptedPositions[3 * numAccepted + 0] = pos.x;
  50222. acceptedPositions[3 * numAccepted + 1] = pos.y;
  50223. acceptedPositions[3 * numAccepted + 2] = pos.z;
  50224. numAccepted++;
  50225. }
  50226. if((i % 1000) === 0){
  50227. let duration = performance.now() - checkpoint;
  50228. if(duration > 4){
  50229. //console.log(`getAccepted yield after ${duration}ms`);
  50230. yield false;
  50231. checkpoint = performance.now();
  50232. }
  50233. }
  50234. }
  50235. accepted = accepted.subarray(0, numAccepted);
  50236. mileage = mileage.subarray(0, numAccepted);
  50237. acceptedPositions = acceptedPositions.subarray(0, numAccepted * 3);
  50238. //let end = performance.now();
  50239. //let duration = end - start;
  50240. //console.log("accepted duration ", duration)
  50241. //console.log(`getAccepted finished`);
  50242. yield [accepted, mileage, acceptedPositions];
  50243. }
  50244. * getPointsInsideProfile(nodes, target){
  50245. let checkpoint = performance.now();
  50246. let totalMileage = 0;
  50247. let pointsProcessed = 0;
  50248. for (let segment of target.segments) {
  50249. for (let node of nodes) {
  50250. let numPoints = node.numPoints;
  50251. let geometry = node.geometry;
  50252. if(!numPoints){
  50253. continue;
  50254. }
  50255. { // skip if current node doesn't intersect current segment
  50256. let bbWorld = node.boundingBox.clone().applyMatrix4(this.pointcloud.matrixWorld);
  50257. let bsWorld = bbWorld.getBoundingSphere(new Sphere());
  50258. let start = new Vector3(segment.start.x, segment.start.y, bsWorld.center.z);
  50259. let end = new Vector3(segment.end.x, segment.end.y, bsWorld.center.z);
  50260. let closest = new Line3(start, end).closestPointToPoint(bsWorld.center, true, new Vector3());
  50261. let distance = closest.distanceTo(bsWorld.center);
  50262. let intersects = (distance < (bsWorld.radius + target.profile.width));
  50263. if(!intersects){
  50264. continue;
  50265. }
  50266. }
  50267. //{// DEBUG
  50268. // console.log(node.name);
  50269. // let boxHelper = new Potree.Box3Helper(node.getBoundingBox());
  50270. // boxHelper.matrixAutoUpdate = false;
  50271. // boxHelper.matrix.copy(viewer.scene.pointclouds[0].matrixWorld);
  50272. // viewer.scene.scene.add(boxHelper);
  50273. //}
  50274. let sv = new Vector3().subVectors(segment.end, segment.start).setZ(0);
  50275. let segmentDir = sv.clone().normalize();
  50276. let points = new Points$1();
  50277. let nodeMatrix = new Matrix4().makeTranslation(...node.boundingBox.min.toArray());
  50278. let matrix = new Matrix4().multiplyMatrices(
  50279. this.pointcloud.matrixWorld, nodeMatrix);
  50280. pointsProcessed = pointsProcessed + numPoints;
  50281. let accepted = null;
  50282. let mileage = null;
  50283. let acceptedPositions = null;
  50284. for(let result of this.getAccepted(numPoints, node, matrix, segment, segmentDir, points,totalMileage)){
  50285. if(!result){
  50286. let duration = performance.now() - checkpoint;
  50287. //console.log(`getPointsInsideProfile yield after ${duration}ms`);
  50288. yield false;
  50289. checkpoint = performance.now();
  50290. }else {
  50291. [accepted, mileage, acceptedPositions] = result;
  50292. }
  50293. }
  50294. let duration = performance.now() - checkpoint;
  50295. if(duration > 4){
  50296. //console.log(`getPointsInsideProfile yield after ${duration}ms`);
  50297. yield false;
  50298. checkpoint = performance.now();
  50299. }
  50300. points.data.position = acceptedPositions;
  50301. let relevantAttributes = Object.keys(geometry.attributes).filter(a => !["position", "indices"].includes(a));
  50302. for(let attributeName of relevantAttributes){
  50303. let attribute = geometry.attributes[attributeName];
  50304. let numElements = attribute.array.length / numPoints;
  50305. if(numElements !== parseInt(numElements)){
  50306. debugger;
  50307. }
  50308. let Type = attribute.array.constructor;
  50309. let filteredBuffer = new Type(numElements * accepted.length);
  50310. let source = attribute.array;
  50311. let target = filteredBuffer;
  50312. for(let i = 0; i < accepted.length; i++){
  50313. let index = accepted[i];
  50314. let start = index * numElements;
  50315. let end = start + numElements;
  50316. let sub = source.subarray(start, end);
  50317. target.set(sub, i * numElements);
  50318. }
  50319. points.data[attributeName] = filteredBuffer;
  50320. }
  50321. points.data['mileage'] = mileage;
  50322. points.numPoints = accepted.length;
  50323. segment.points.add(points);
  50324. }
  50325. totalMileage += segment.length;
  50326. }
  50327. for (let segment of target.segments) {
  50328. target.boundingBox.union(segment.points.boundingBox);
  50329. }
  50330. //console.log(`getPointsInsideProfile finished`);
  50331. yield true;
  50332. };
  50333. finishLevelThenCancel () {
  50334. if (this.cancelRequested) {
  50335. return;
  50336. }
  50337. this.maxDepth = this.highestLevelServed;
  50338. this.cancelRequested = true;
  50339. //console.log(`maxDepth: ${this.maxDepth}`);
  50340. };
  50341. cancel () {
  50342. this.callback.onCancel();
  50343. this.priorityQueue = new BinaryHeap(function (x) { return 1 / x.weight; });
  50344. let index = this.pointcloud.profileRequests.indexOf(this);
  50345. if (index >= 0) {
  50346. this.pointcloud.profileRequests.splice(index, 1);
  50347. }
  50348. };
  50349. }
  50350. class WorkerPool{
  50351. constructor(){
  50352. this.workers = {};
  50353. }
  50354. getWorker(url){
  50355. if (!this.workers[url]){
  50356. this.workers[url] = [];
  50357. }
  50358. if (this.workers[url].length === 0){
  50359. let worker = new Worker(url);
  50360. this.workers[url].push(worker);
  50361. }
  50362. let worker = this.workers[url].pop();
  50363. return worker;
  50364. }
  50365. returnWorker(url, worker){
  50366. this.workers[url].push(worker);
  50367. }
  50368. };
  50369. function createPointcloudData(pointcloud) {
  50370. let material = pointcloud.material;
  50371. let ranges = [];
  50372. for(let [name, value] of material.ranges){
  50373. ranges.push({
  50374. name: name,
  50375. value: value,
  50376. });
  50377. }
  50378. if(typeof material.elevationRange[0] === "number"){
  50379. ranges.push({
  50380. name: "elevationRange",
  50381. value: material.elevationRange,
  50382. });
  50383. }
  50384. if(typeof material.intensityRange[0] === "number"){
  50385. ranges.push({
  50386. name: "intensityRange",
  50387. value: material.intensityRange,
  50388. });
  50389. }
  50390. let pointSizeTypeName = Object.entries(Potree.PointSizeType).find(e => e[1] === material.pointSizeType)[0];
  50391. let jsonMaterial = {
  50392. activeAttributeName: material.activeAttributeName,
  50393. ranges: ranges,
  50394. size: material.size,
  50395. minSize: material.minSize,
  50396. pointSizeType: pointSizeTypeName,
  50397. matcap: material.matcap,
  50398. };
  50399. const pcdata = {
  50400. name: pointcloud.name,
  50401. url: pointcloud.pcoGeometry.url,
  50402. position: pointcloud.position.toArray(),
  50403. rotation: pointcloud.rotation.toArray(),
  50404. scale: pointcloud.scale.toArray(),
  50405. material: jsonMaterial,
  50406. };
  50407. return pcdata;
  50408. }
  50409. function createProfileData(profile){
  50410. const data = {
  50411. uuid: profile.uuid,
  50412. name: profile.name,
  50413. points: profile.points.map(p => p.toArray()),
  50414. height: profile.height,
  50415. width: profile.width,
  50416. };
  50417. return data;
  50418. }
  50419. function createVolumeData(volume){
  50420. const data = {
  50421. uuid: volume.uuid,
  50422. type: volume.constructor.name,
  50423. name: volume.name,
  50424. position: volume.position.toArray(),
  50425. rotation: volume.rotation.toArray(),
  50426. scale: volume.scale.toArray(),
  50427. visible: volume.visible,
  50428. clip: volume.clip,
  50429. };
  50430. return data;
  50431. }
  50432. function createCameraAnimationData(animation){
  50433. const controlPoints = animation.controlPoints.map( cp => {
  50434. const cpdata = {
  50435. position: cp.position.toArray(),
  50436. target: cp.target.toArray(),
  50437. };
  50438. return cpdata;
  50439. });
  50440. const data = {
  50441. uuid: animation.uuid,
  50442. name: animation.name,
  50443. duration: animation.duration,
  50444. t: animation.t,
  50445. curveType: animation.curveType,
  50446. visible: animation.visible,
  50447. controlPoints: controlPoints,
  50448. };
  50449. return data;
  50450. }
  50451. function createMeasurementData(measurement){
  50452. const data = {
  50453. uuid: measurement.uuid,
  50454. name: measurement.name,
  50455. points: measurement.points.map(p => p.position.toArray()),
  50456. showDistances: measurement.showDistances,
  50457. showCoordinates: measurement.showCoordinates,
  50458. showArea: measurement.showArea,
  50459. closed: measurement.closed,
  50460. showAngles: measurement.showAngles,
  50461. showHeight: measurement.showHeight,
  50462. showCircle: measurement.showCircle,
  50463. showAzimuth: measurement.showAzimuth,
  50464. showEdges: measurement.showEdges,
  50465. color: measurement.color.toArray(),
  50466. };
  50467. return data;
  50468. }
  50469. function createOrientedImagesData(images){
  50470. const data = {
  50471. cameraParamsPath: images.cameraParamsPath,
  50472. imageParamsPath: images.imageParamsPath,
  50473. };
  50474. return data;
  50475. }
  50476. function createGeopackageData(geopackage){
  50477. const data = {
  50478. path: geopackage.path,
  50479. };
  50480. return data;
  50481. }
  50482. function createAnnotationData(annotation){
  50483. const data = {
  50484. uuid: annotation.uuid,
  50485. title: annotation.title.toString(),
  50486. description: annotation.description,
  50487. position: annotation.position.toArray(),
  50488. offset: annotation.offset.toArray(),
  50489. children: [],
  50490. };
  50491. if(annotation.cameraPosition){
  50492. data.cameraPosition = annotation.cameraPosition.toArray();
  50493. }
  50494. if(annotation.cameraTarget){
  50495. data.cameraTarget = annotation.cameraTarget.toArray();
  50496. }
  50497. if(typeof annotation.radius !== "undefined"){
  50498. data.radius = annotation.radius;
  50499. }
  50500. return data;
  50501. }
  50502. function createAnnotationsData(viewer){
  50503. const map = new Map();
  50504. viewer.scene.annotations.traverseDescendants(a => {
  50505. const aData = createAnnotationData(a);
  50506. map.set(a, aData);
  50507. });
  50508. for(const [annotation, data] of map){
  50509. for(const child of annotation.children){
  50510. const childData = map.get(child);
  50511. data.children.push(childData);
  50512. }
  50513. }
  50514. const annotations = viewer.scene.annotations.children.map(a => map.get(a));
  50515. return annotations;
  50516. }
  50517. function createSettingsData(viewer){
  50518. return {
  50519. pointBudget: viewer.getPointBudget(),
  50520. fov: viewer.getFOV(),
  50521. edlEnabled: viewer.getEDLEnabled(),
  50522. edlRadius: viewer.getEDLRadius(),
  50523. edlStrength: viewer.getEDLStrength(),
  50524. background: viewer.getBackground(),
  50525. minNodeSize: viewer.getMinNodeSize(),
  50526. showBoundingBoxes: viewer.getShowBoundingBox(),
  50527. };
  50528. }
  50529. function createSceneContentData(viewer){
  50530. const data = [];
  50531. const potreeObjects = [];
  50532. viewer.scene.scene.traverse(node => {
  50533. if(node.potree){
  50534. potreeObjects.push(node);
  50535. }
  50536. });
  50537. for(const object of potreeObjects){
  50538. if(object.potree.file){
  50539. const saveObject = {
  50540. file: object.potree.file,
  50541. };
  50542. data.push(saveObject);
  50543. }
  50544. }
  50545. return data;
  50546. }
  50547. function createViewData(viewer){
  50548. const view = viewer.scene.view;
  50549. const data = {
  50550. position: view.position.toArray(),
  50551. target: view.getPivot().toArray(),
  50552. };
  50553. return data;
  50554. }
  50555. function createClassificationData(viewer){
  50556. const classifications = viewer.classifications;
  50557. const data = classifications;
  50558. return data;
  50559. }
  50560. function saveProject(viewer) {
  50561. const scene = viewer.scene;
  50562. const data = {
  50563. type: "Potree",
  50564. version: 1.7,
  50565. settings: createSettingsData(viewer),
  50566. view: createViewData(viewer),
  50567. classification: createClassificationData(viewer),
  50568. pointclouds: scene.pointclouds.map(createPointcloudData),
  50569. measurements: scene.measurements.map(createMeasurementData),
  50570. volumes: scene.volumes.map(createVolumeData),
  50571. cameraAnimations: scene.cameraAnimations.map(createCameraAnimationData),
  50572. profiles: scene.profiles.map(createProfileData),
  50573. annotations: createAnnotationsData(viewer),
  50574. orientedImages: scene.orientedImages.map(createOrientedImagesData),
  50575. geopackages: scene.geopackages.map(createGeopackageData),
  50576. // objects: createSceneContentData(viewer),
  50577. };
  50578. return data;
  50579. }
  50580. class ControlPoint{
  50581. constructor(){
  50582. this.position = new Vector3(0, 0, 0);
  50583. this.target = new Vector3(0, 0, 0);
  50584. this.positionHandle = null;
  50585. this.targetHandle = null;
  50586. }
  50587. };
  50588. class CameraAnimation$1 extends EventDispatcher$1{
  50589. constructor(viewer){
  50590. super();
  50591. this.viewer = viewer;
  50592. this.selectedElement = null;
  50593. this.controlPoints = [];
  50594. this.uuid = MathUtils$1.generateUUID();
  50595. this.node = new Object3D();
  50596. this.node.name = "camera animation";
  50597. this.viewer.scene.scene.add(this.node);
  50598. this.frustum = this.createFrustum();
  50599. this.node.add(this.frustum);
  50600. this.name = "Camera Animation";
  50601. this.duration = 5;
  50602. this.t = 0;
  50603. // "centripetal", "chordal", "catmullrom"
  50604. this.curveType = "centripetal";
  50605. this.visible = true;
  50606. this.createUpdateHook();
  50607. this.createPath();
  50608. }
  50609. static defaultFromView(viewer){
  50610. const animation = new CameraAnimation$1(viewer);
  50611. const camera = viewer.scene.getActiveCamera();
  50612. const target = viewer.scene.view.getPivot();
  50613. const cpCenter = new Vector3(
  50614. 0.3 * camera.position.x + 0.7 * target.x,
  50615. 0.3 * camera.position.y + 0.7 * target.y,
  50616. 0.3 * camera.position.z + 0.7 * target.z,
  50617. );
  50618. const targetCenter = new Vector3(
  50619. 0.05 * camera.position.x + 0.95 * target.x,
  50620. 0.05 * camera.position.y + 0.95 * target.y,
  50621. 0.05 * camera.position.z + 0.95 * target.z,
  50622. );
  50623. const r = camera.position.distanceTo(target) * 0.3;
  50624. //const dir = target.clone().sub(camera.position).normalize();
  50625. const angle = Utils.computeAzimuth(camera.position, target);
  50626. const n = 5;
  50627. for(let i = 0; i < n; i++){
  50628. let u = 1.5 * Math.PI * (i / n) + angle;
  50629. const dx = r * Math.cos(u);
  50630. const dy = r * Math.sin(u);
  50631. const cpPos = [
  50632. cpCenter.x + dx,
  50633. cpCenter.y + dy,
  50634. cpCenter.z,
  50635. ];
  50636. const targetPos = [
  50637. targetCenter.x + dx * 0.1,
  50638. targetCenter.y + dy * 0.1,
  50639. targetCenter.z,
  50640. ];
  50641. const cp = animation.createControlPoint();
  50642. cp.position.set(...cpPos);
  50643. cp.target.set(...targetPos);
  50644. }
  50645. return animation;
  50646. }
  50647. createUpdateHook(){
  50648. const viewer = this.viewer;
  50649. viewer.addEventListener("update", () => {
  50650. const camera = viewer.scene.getActiveCamera();
  50651. const {width, height} = viewer.renderer.getSize(new Vector2());
  50652. this.node.visible = this.visible;
  50653. for(const cp of this.controlPoints){
  50654. { // position
  50655. const projected = cp.position.clone().project(camera);
  50656. const visible = this.visible && (projected.z < 1 && projected.z > -1);
  50657. if(visible){
  50658. const x = width * (projected.x * 0.5 + 0.5);
  50659. const y = height - height * (projected.y * 0.5 + 0.5);
  50660. cp.positionHandle.svg.style.left = x - cp.positionHandle.svg.clientWidth / 2;
  50661. cp.positionHandle.svg.style.top = y - cp.positionHandle.svg.clientHeight / 2;
  50662. cp.positionHandle.svg.style.display = "";
  50663. }else {
  50664. cp.positionHandle.svg.style.display = "none";
  50665. }
  50666. }
  50667. { // target
  50668. const projected = cp.target.clone().project(camera);
  50669. const visible = this.visible && (projected.z < 1 && projected.z > -1);
  50670. if(visible){
  50671. const x = width * (projected.x * 0.5 + 0.5);
  50672. const y = height - height * (projected.y * 0.5 + 0.5);
  50673. cp.targetHandle.svg.style.left = x - cp.targetHandle.svg.clientWidth / 2;
  50674. cp.targetHandle.svg.style.top = y - cp.targetHandle.svg.clientHeight / 2;
  50675. cp.targetHandle.svg.style.display = "";
  50676. }else {
  50677. cp.targetHandle.svg.style.display = "none";
  50678. }
  50679. }
  50680. }
  50681. this.line.material.resolution.set(width, height);
  50682. this.updatePath();
  50683. { // frustum
  50684. const frame = this.at(this.t);
  50685. const frustum = this.frustum;
  50686. frustum.position.copy(frame.position);
  50687. frustum.lookAt(...frame.target.toArray());
  50688. frustum.scale.set(20, 20, 20);
  50689. frustum.material.resolution.set(width, height);
  50690. }
  50691. });
  50692. }
  50693. createControlPoint(index){
  50694. if(index === undefined){
  50695. index = this.controlPoints.length;
  50696. }
  50697. const cp = new ControlPoint();
  50698. if(this.controlPoints.length >= 2 && index === 0){
  50699. const cp1 = this.controlPoints[0];
  50700. const cp2 = this.controlPoints[1];
  50701. const dir = cp1.position.clone().sub(cp2.position).multiplyScalar(0.5);
  50702. cp.position.copy(cp1.position).add(dir);
  50703. const tDir = cp1.target.clone().sub(cp2.target).multiplyScalar(0.5);
  50704. cp.target.copy(cp1.target).add(tDir);
  50705. }else if(this.controlPoints.length >= 2 && index === this.controlPoints.length){
  50706. const cp1 = this.controlPoints[this.controlPoints.length - 2];
  50707. const cp2 = this.controlPoints[this.controlPoints.length - 1];
  50708. const dir = cp2.position.clone().sub(cp1.position).multiplyScalar(0.5);
  50709. cp.position.copy(cp1.position).add(dir);
  50710. const tDir = cp2.target.clone().sub(cp1.target).multiplyScalar(0.5);
  50711. cp.target.copy(cp2.target).add(tDir);
  50712. }else if(this.controlPoints.length >= 2){
  50713. const cp1 = this.controlPoints[index - 1];
  50714. const cp2 = this.controlPoints[index];
  50715. cp.position.copy(cp1.position.clone().add(cp2.position).multiplyScalar(0.5));
  50716. cp.target.copy(cp1.target.clone().add(cp2.target).multiplyScalar(0.5));
  50717. }
  50718. // cp.position.copy(viewer.scene.view.position);
  50719. // cp.target.copy(viewer.scene.view.getPivot());
  50720. cp.positionHandle = this.createHandle(cp.position);
  50721. cp.targetHandle = this.createHandle(cp.target);
  50722. this.controlPoints.splice(index, 0, cp);
  50723. this.dispatchEvent({
  50724. type: "controlpoint_added",
  50725. controlpoint: cp,
  50726. });
  50727. return cp;
  50728. }
  50729. removeControlPoint(cp){
  50730. this.controlPoints = this.controlPoints.filter(_cp => _cp !== cp);
  50731. this.dispatchEvent({
  50732. type: "controlpoint_removed",
  50733. controlpoint: cp,
  50734. });
  50735. cp.positionHandle.svg.remove();
  50736. cp.targetHandle.svg.remove();
  50737. // TODO destroy cp
  50738. }
  50739. createPath(){
  50740. { // position
  50741. const geometry = new LineGeometry();
  50742. let material = new LineMaterial({
  50743. color: 0x00ff00,
  50744. dashSize: 5,
  50745. gapSize: 2,
  50746. linewidth: 2,
  50747. resolution: new Vector2(1000, 1000),
  50748. });
  50749. const line = new Line2(geometry, material);
  50750. this.line = line;
  50751. this.node.add(line);
  50752. }
  50753. { // target
  50754. const geometry = new LineGeometry();
  50755. let material = new LineMaterial({
  50756. color: 0x0000ff,
  50757. dashSize: 5,
  50758. gapSize: 2,
  50759. linewidth: 2,
  50760. resolution: new Vector2(1000, 1000),
  50761. });
  50762. const line = new Line2(geometry, material);
  50763. this.targetLine = line;
  50764. this.node.add(line);
  50765. }
  50766. }
  50767. createFrustum(){
  50768. const f = 0.3;
  50769. const positions = [
  50770. 0, 0, 0,
  50771. -f, -f, +1,
  50772. 0, 0, 0,
  50773. f, -f, +1,
  50774. 0, 0, 0,
  50775. f, f, +1,
  50776. 0, 0, 0,
  50777. -f, f, +1,
  50778. -f, -f, +1,
  50779. f, -f, +1,
  50780. f, -f, +1,
  50781. f, f, +1,
  50782. f, f, +1,
  50783. -f, f, +1,
  50784. -f, f, +1,
  50785. -f, -f, +1,
  50786. ];
  50787. const geometry = new LineGeometry();
  50788. geometry.setPositions(positions);
  50789. geometry.verticesNeedUpdate = true;
  50790. geometry.computeBoundingSphere();
  50791. let material = new LineMaterial({
  50792. color: 0xff0000,
  50793. linewidth: 2,
  50794. resolution: new Vector2(1000, 1000),
  50795. });
  50796. const line = new Line2(geometry, material);
  50797. line.computeLineDistances();
  50798. return line;
  50799. }
  50800. updatePath(){
  50801. { // positions
  50802. const positions = this.controlPoints.map(cp => cp.position);
  50803. const first = positions[0];
  50804. const curve = new CatmullRomCurve3(positions);
  50805. curve.curveType = this.curveType;
  50806. const n = 100;
  50807. const curvePositions = [];
  50808. for(let k = 0; k <= n; k++){
  50809. const t = k / n;
  50810. const position = curve.getPoint(t).sub(first);
  50811. curvePositions.push(position.x, position.y, position.z);
  50812. }
  50813. this.line.geometry.setPositions(curvePositions);
  50814. this.line.geometry.verticesNeedUpdate = true;
  50815. this.line.geometry.computeBoundingSphere();
  50816. this.line.position.copy(first);
  50817. this.line.computeLineDistances();
  50818. this.cameraCurve = curve;
  50819. }
  50820. { // targets
  50821. const positions = this.controlPoints.map(cp => cp.target);
  50822. const first = positions[0];
  50823. const curve = new CatmullRomCurve3(positions);
  50824. curve.curveType = this.curveType;
  50825. const n = 100;
  50826. const curvePositions = [];
  50827. for(let k = 0; k <= n; k++){
  50828. const t = k / n;
  50829. const position = curve.getPoint(t).sub(first);
  50830. curvePositions.push(position.x, position.y, position.z);
  50831. }
  50832. this.targetLine.geometry.setPositions(curvePositions);
  50833. this.targetLine.geometry.verticesNeedUpdate = true;
  50834. this.targetLine.geometry.computeBoundingSphere();
  50835. this.targetLine.position.copy(first);
  50836. this.targetLine.computeLineDistances();
  50837. this.targetCurve = curve;
  50838. }
  50839. }
  50840. at(t){
  50841. if(t > 1){
  50842. t = 1;
  50843. }else if(t < 0){
  50844. t = 0;
  50845. }
  50846. const camPos = this.cameraCurve.getPointAt(t);
  50847. const target = this.targetCurve.getPointAt(t);
  50848. const frame = {
  50849. position: camPos,
  50850. target: target,
  50851. };
  50852. return frame;
  50853. }
  50854. set(t){
  50855. this.t = t;
  50856. }
  50857. createHandle(vector){
  50858. const svgns = "http://www.w3.org/2000/svg";
  50859. const svg = document.createElementNS(svgns, "svg");
  50860. svg.setAttribute("width", "2em");
  50861. svg.setAttribute("height", "2em");
  50862. svg.setAttribute("position", "absolute");
  50863. svg.style.left = "50px";
  50864. svg.style.top = "50px";
  50865. svg.style.position = "absolute";
  50866. svg.style.zIndex = "10000";
  50867. const circle = document.createElementNS(svgns, 'circle');
  50868. circle.setAttributeNS(null, 'cx', "1em");
  50869. circle.setAttributeNS(null, 'cy', "1em");
  50870. circle.setAttributeNS(null, 'r', "0.5em");
  50871. circle.setAttributeNS(null, 'style', 'fill: red; stroke: black; stroke-width: 0.2em;' );
  50872. svg.appendChild(circle);
  50873. const element = this.viewer.renderer.domElement.parentElement;
  50874. element.appendChild(svg);
  50875. const startDrag = (evt) => {
  50876. this.selectedElement = svg;
  50877. document.addEventListener("mousemove", drag);
  50878. };
  50879. const endDrag = (evt) => {
  50880. this.selectedElement = null;
  50881. document.removeEventListener("mousemove", drag);
  50882. };
  50883. const drag = (evt) => {
  50884. if (this.selectedElement) {
  50885. evt.preventDefault();
  50886. const rect = viewer.renderer.domElement.getBoundingClientRect();
  50887. const x = evt.clientX - rect.x;
  50888. const y = evt.clientY - rect.y;
  50889. const {width, height} = this.viewer.renderer.getSize(new Vector2());
  50890. const camera = this.viewer.scene.getActiveCamera();
  50891. //const cp = this.controlPoints.find(cp => cp.handle.svg === svg);
  50892. const projected = vector.clone().project(camera);
  50893. projected.x = ((x / width) - 0.5) / 0.5;
  50894. projected.y = (-(y - height) / height - 0.5) / 0.5;
  50895. const unprojected = projected.clone().unproject(camera);
  50896. vector.set(unprojected.x, unprojected.y, unprojected.z);
  50897. }
  50898. };
  50899. svg.addEventListener('mousedown', startDrag);
  50900. svg.addEventListener('mouseup', endDrag);
  50901. const handle = {
  50902. svg: svg,
  50903. };
  50904. return handle;
  50905. }
  50906. setVisible(visible){
  50907. this.node.visible = visible;
  50908. const display = visible ? "" : "none";
  50909. for(const cp of this.controlPoints){
  50910. cp.positionHandle.svg.style.display = display;
  50911. cp.targetHandle.svg.style.display = display;
  50912. }
  50913. this.visible = visible;
  50914. }
  50915. setDuration(duration){
  50916. this.duration = duration;
  50917. }
  50918. getDuration(duration){
  50919. return this.duration;
  50920. }
  50921. play(){
  50922. const tStart = performance.now();
  50923. const duration = this.duration;
  50924. const originalyVisible = this.visible;
  50925. this.setVisible(false);
  50926. const onUpdate = (delta) => {
  50927. let tNow = performance.now();
  50928. let elapsed = (tNow - tStart) / 1000;
  50929. let t = elapsed / duration;
  50930. this.set(t);
  50931. const frame = this.at(t);
  50932. viewer.scene.view.position.copy(frame.position);
  50933. viewer.scene.view.lookAt(frame.target);
  50934. if(t > 1){
  50935. this.setVisible(originalyVisible);
  50936. this.viewer.removeEventListener("update", onUpdate);
  50937. }
  50938. };
  50939. this.viewer.addEventListener("update", onUpdate);
  50940. }
  50941. }
  50942. function loadPointCloud(viewer, data){
  50943. let loadMaterial = (target) => {
  50944. if(data.material){
  50945. if(data.material.activeAttributeName != null){
  50946. target.activeAttributeName = data.material.activeAttributeName;
  50947. }
  50948. if(data.material.ranges != null){
  50949. for(let range of data.material.ranges){
  50950. if(range.name === "elevationRange"){
  50951. target.elevationRange = range.value;
  50952. }else if(range.name === "intensityRange"){
  50953. target.intensityRange = range.value;
  50954. }else {
  50955. target.setRange(range.name, range.value);
  50956. }
  50957. }
  50958. }
  50959. if(data.material.size != null){
  50960. target.size = data.material.size;
  50961. }
  50962. if(data.material.minSize != null){
  50963. target.minSize = data.material.minSize;
  50964. }
  50965. if(data.material.pointSizeType != null){
  50966. target.pointSizeType = PointSizeType[data.material.pointSizeType];
  50967. }
  50968. if(data.material.matcap != null){
  50969. target.matcap = data.material.matcap;
  50970. }
  50971. }else if(data.activeAttributeName != null){
  50972. target.activeAttributeName = data.activeAttributeName;
  50973. }else {
  50974. // no material data
  50975. }
  50976. };
  50977. const promise = new Promise((resolve) => {
  50978. const names = viewer.scene.pointclouds.map(p => p.name);
  50979. const alreadyExists = names.includes(data.name);
  50980. if(alreadyExists){
  50981. resolve();
  50982. return;
  50983. }
  50984. Potree.loadPointCloud(data.url, data.name, (e) => {
  50985. const {pointcloud} = e;
  50986. pointcloud.position.set(...data.position);
  50987. pointcloud.rotation.set(...data.rotation);
  50988. pointcloud.scale.set(...data.scale);
  50989. loadMaterial(pointcloud.material);
  50990. viewer.scene.addPointCloud(pointcloud);
  50991. resolve(pointcloud);
  50992. });
  50993. });
  50994. return promise;
  50995. }
  50996. function loadMeasurement(viewer, data){
  50997. const duplicate = viewer.scene.measurements.find(measure => measure.uuid === data.uuid);
  50998. if(duplicate){
  50999. return;
  51000. }
  51001. const measure = new Measure();
  51002. measure.uuid = data.uuid;
  51003. measure.name = data.name;
  51004. measure.showDistances = data.showDistances;
  51005. measure.showCoordinates = data.showCoordinates;
  51006. measure.showArea = data.showArea;
  51007. measure.closed = data.closed;
  51008. measure.showAngles = data.showAngles;
  51009. measure.showHeight = data.showHeight;
  51010. measure.showCircle = data.showCircle;
  51011. measure.showAzimuth = data.showAzimuth;
  51012. measure.showEdges = data.showEdges;
  51013. // color
  51014. for(const point of data.points){
  51015. const pos = new Vector3(...point);
  51016. measure.addMarker(pos);
  51017. }
  51018. viewer.scene.addMeasurement(measure);
  51019. }
  51020. function loadVolume(viewer, data){
  51021. const duplicate = viewer.scene.volumes.find(volume => volume.uuid === data.uuid);
  51022. if(duplicate){
  51023. return;
  51024. }
  51025. let volume = new Potree[data.type];
  51026. volume.uuid = data.uuid;
  51027. volume.name = data.name;
  51028. volume.position.set(...data.position);
  51029. volume.rotation.set(...data.rotation);
  51030. volume.scale.set(...data.scale);
  51031. volume.visible = data.visible;
  51032. volume.clip = data.clip;
  51033. viewer.scene.addVolume(volume);
  51034. }
  51035. function loadCameraAnimation(viewer, data){
  51036. const duplicate = viewer.scene.cameraAnimations.find(a => a.uuid === data.uuid);
  51037. if(duplicate){
  51038. return;
  51039. }
  51040. const animation = new CameraAnimation$1(viewer);
  51041. animation.uuid = data.uuid;
  51042. animation.name = data.name;
  51043. animation.duration = data.duration;
  51044. animation.t = data.t;
  51045. animation.curveType = data.curveType;
  51046. animation.visible = data.visible;
  51047. animation.controlPoints = [];
  51048. for(const cpdata of data.controlPoints){
  51049. const cp = animation.createControlPoint();
  51050. cp.position.set(...cpdata.position);
  51051. cp.target.set(...cpdata.target);
  51052. }
  51053. viewer.scene.addCameraAnimation(animation);
  51054. }
  51055. function loadOrientedImages(viewer, images){
  51056. const {cameraParamsPath, imageParamsPath} = images;
  51057. const duplicate = viewer.scene.orientedImages.find(i => i.imageParamsPath === imageParamsPath);
  51058. if(duplicate){
  51059. return;
  51060. }
  51061. Potree.OrientedImageLoader.load(cameraParamsPath, imageParamsPath, viewer).then( images => {
  51062. viewer.scene.addOrientedImages(images);
  51063. });
  51064. }
  51065. function loadGeopackage(viewer, geopackage){
  51066. const path = geopackage.path;
  51067. const duplicate = viewer.scene.geopackages.find(i => i.path === path);
  51068. if(duplicate){
  51069. return;
  51070. }
  51071. const projection = viewer.getProjection();
  51072. proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
  51073. proj4.defs("pointcloud", projection);
  51074. const transform = proj4("WGS84", "pointcloud");
  51075. const params = {
  51076. transform: transform,
  51077. };
  51078. Potree.GeoPackageLoader.loadUrl(path, params).then(data => {
  51079. viewer.scene.addGeopackage(data);
  51080. });
  51081. }
  51082. function loadSettings(viewer, data){
  51083. if(!data){
  51084. return;
  51085. }
  51086. viewer.setPointBudget(data.pointBudget);
  51087. viewer.setFOV(data.fov);
  51088. viewer.setEDLEnabled(data.edlEnabled);
  51089. viewer.setEDLRadius(data.edlRadius);
  51090. viewer.setEDLStrength(data.edlStrength);
  51091. viewer.setBackground(data.background);
  51092. viewer.setMinNodeSize(data.minNodeSize);
  51093. viewer.setShowBoundingBox(data.showBoundingBoxes);
  51094. }
  51095. function loadView(viewer, view){
  51096. viewer.scene.view.position.set(...view.position);
  51097. viewer.scene.view.lookAt(...view.target);
  51098. }
  51099. function loadAnnotationItem(item){
  51100. const annotation = new Annotation({
  51101. position: item.position,
  51102. title: item.title,
  51103. cameraPosition: item.cameraPosition,
  51104. cameraTarget: item.cameraTarget,
  51105. });
  51106. annotation.description = item.description;
  51107. annotation.uuid = item.uuid;
  51108. if(item.offset){
  51109. annotation.offset.set(...item.offset);
  51110. }
  51111. return annotation;
  51112. }
  51113. function loadAnnotations(viewer, data){
  51114. if(!data){
  51115. return;
  51116. }
  51117. const findDuplicate = (item) => {
  51118. let duplicate = null;
  51119. viewer.scene.annotations.traverse( a => {
  51120. if(a.uuid === item.uuid){
  51121. duplicate = a;
  51122. }
  51123. });
  51124. return duplicate;
  51125. };
  51126. const traverse = (item, parent) => {
  51127. const duplicate = findDuplicate(item);
  51128. if(duplicate){
  51129. return;
  51130. }
  51131. const annotation = loadAnnotationItem(item);
  51132. for(const childItem of item.children){
  51133. traverse(childItem, annotation);
  51134. }
  51135. parent.add(annotation);
  51136. };
  51137. for(const item of data){
  51138. traverse(item, viewer.scene.annotations);
  51139. }
  51140. }
  51141. function loadProfile(viewer, data){
  51142. const {name, points} = data;
  51143. const duplicate = viewer.scene.profiles.find(profile => profile.uuid === data.uuid);
  51144. if(duplicate){
  51145. return;
  51146. }
  51147. let profile = new Potree.Profile();
  51148. profile.name = name;
  51149. profile.uuid = data.uuid;
  51150. profile.setWidth(data.width);
  51151. for(const point of points){
  51152. profile.addMarker(new Vector3(...point));
  51153. }
  51154. viewer.scene.addProfile(profile);
  51155. }
  51156. function loadClassification(viewer, data){
  51157. if(!data){
  51158. return;
  51159. }
  51160. const classifications = data;
  51161. viewer.setClassifications(classifications);
  51162. }
  51163. async function loadProject(viewer, data){
  51164. if(data.type !== "Potree"){
  51165. console.error("not a valid Potree project");
  51166. return;
  51167. }
  51168. loadSettings(viewer, data.settings);
  51169. loadView(viewer, data.view);
  51170. const pointcloudPromises = [];
  51171. for(const pointcloud of data.pointclouds){
  51172. const promise = loadPointCloud(viewer, pointcloud);
  51173. pointcloudPromises.push(promise);
  51174. }
  51175. for(const measure of data.measurements){
  51176. loadMeasurement(viewer, measure);
  51177. }
  51178. for(const volume of data.volumes){
  51179. loadVolume(viewer, volume);
  51180. }
  51181. for(const animation of data.cameraAnimations){
  51182. loadCameraAnimation(viewer, animation);
  51183. }
  51184. for(const profile of data.profiles){
  51185. loadProfile(viewer, profile);
  51186. }
  51187. if(data.orientedImages){
  51188. for(const images of data.orientedImages){
  51189. loadOrientedImages(viewer, images);
  51190. }
  51191. }
  51192. loadAnnotations(viewer, data.annotations);
  51193. loadClassification(viewer, data.classification);
  51194. // need to load at least one point cloud that defines the scene projection,
  51195. // before we can load stuff in other projections such as geopackages
  51196. //await Promise.any(pointcloudPromises); // (not yet supported)
  51197. Utils.waitAny(pointcloudPromises).then( () => {
  51198. if(data.geopackages){
  51199. for(const geopackage of data.geopackages){
  51200. loadGeopackage(viewer, geopackage);
  51201. }
  51202. }
  51203. });
  51204. await Promise.all(pointcloudPromises);
  51205. }
  51206. //
  51207. // Algorithm by Christian Boucheny
  51208. // shader code taken and adapted from CloudCompare
  51209. //
  51210. // see
  51211. // https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL
  51212. // http://www.kitware.com/source/home/post/9
  51213. // https://tel.archives-ouvertes.fr/tel-00438464/document p. 115+ (french)
  51214. class EyeDomeLightingMaterial extends RawShaderMaterial{//base
  51215. constructor(parameters = {}){
  51216. super();
  51217. let uniforms = {
  51218. screenWidth: { type: 'f', value: 0 },
  51219. screenHeight: { type: 'f', value: 0 },
  51220. edlStrength: { type: 'f', value: 1.0 },
  51221. uNear: { type: 'f', value: 1.0 },
  51222. uFar: { type: 'f', value: 1.0 },
  51223. radius: { type: 'f', value: 1.0 },
  51224. neighbours: { type: '2fv', value: [] },
  51225. depthMap: { type: 't', value: null },
  51226. uEDLColor: { type: 't', value: null },
  51227. uEDLDepth: { type: 't', value: null },
  51228. opacity: { type: 'f', value: 1.0 },
  51229. uProj: { type: "Matrix4fv", value: [] },
  51230. };
  51231. this.setValues({
  51232. uniforms: uniforms,
  51233. vertexShader: this.getDefines() + Shaders['edl.vs'],
  51234. fragmentShader: this.getDefines() + Shaders['edl.fs'],
  51235. lights: false
  51236. });
  51237. this.neighbourCount = 8;
  51238. }
  51239. getDefines() {
  51240. let defines = '';
  51241. defines += '#define NEIGHBOUR_COUNT ' + this.neighbourCount + '\n';
  51242. return defines;
  51243. }
  51244. updateShaderSource() {
  51245. let vs = this.getDefines() + Shaders['edl.vs'];
  51246. let fs = this.getDefines() + Shaders['edl.fs'];
  51247. this.setValues({
  51248. vertexShader: vs,
  51249. fragmentShader: fs
  51250. });
  51251. this.uniforms.neighbours.value = this.neighbours;
  51252. this.needsUpdate = true;
  51253. }
  51254. get neighbourCount(){
  51255. return this._neighbourCount;
  51256. }
  51257. set neighbourCount(value){
  51258. if (this._neighbourCount !== value) {//周围八个格子
  51259. this._neighbourCount = value;
  51260. this.neighbours = new Float32Array(this._neighbourCount * 2);
  51261. for (let c = 0; c < this._neighbourCount; c++) {
  51262. this.neighbours[2 * c + 0] = Math.cos(2 * c * Math.PI / this._neighbourCount);
  51263. this.neighbours[2 * c + 1] = Math.sin(2 * c * Math.PI / this._neighbourCount);
  51264. }
  51265. this.updateShaderSource();
  51266. }
  51267. }
  51268. }
  51269. /**
  51270. * laslaz code taken and adapted from plas.io js-laslaz
  51271. * http://plas.io/
  51272. * https://github.com/verma/plasio
  51273. *
  51274. * Thanks to Uday Verma and Howard Butler
  51275. *
  51276. */
  51277. class LasLazLoader {
  51278. constructor (version, extension) {
  51279. if (typeof (version) === 'string') {
  51280. this.version = new Version(version);
  51281. } else {
  51282. this.version = version;
  51283. }
  51284. this.extension = extension;
  51285. }
  51286. static progressCB () {
  51287. }
  51288. load (node) {
  51289. if (node.loaded) {
  51290. return;
  51291. }
  51292. let url = node.getURL();
  51293. if (this.version.equalOrHigher('1.4')) {
  51294. url += `.${this.extension}`;
  51295. }
  51296. let xhr = XHRFactory.createXMLHttpRequest();
  51297. xhr.open('GET', url, true);
  51298. xhr.responseType = 'arraybuffer';
  51299. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  51300. xhr.onreadystatechange = () => {
  51301. if (xhr.readyState === 4) {
  51302. if (xhr.status === 200 || xhr.status === 0) {
  51303. let buffer = xhr.response;
  51304. this.parse(node, buffer);
  51305. } else {
  51306. console.log('Failed to load file! HTTP status: ' + xhr.status + ', file: ' + url);
  51307. }
  51308. }
  51309. };
  51310. xhr.send(null);
  51311. }
  51312. async parse(node, buffer){
  51313. let lf = new LASFile(buffer);
  51314. let handler = new LasLazBatcher(node);
  51315. try{
  51316. await lf.open();
  51317. lf.isOpen = true;
  51318. }catch(e){
  51319. console.log("failed to open file. :(");
  51320. return;
  51321. }
  51322. let header = await lf.getHeader();
  51323. let skip = 1;
  51324. let totalRead = 0;
  51325. let totalToRead = (skip <= 1 ? header.pointsCount : header.pointsCount / skip);
  51326. let hasMoreData = true;
  51327. while(hasMoreData){
  51328. let data = await lf.readData(1000 * 1000, 0, skip);
  51329. handler.push(new LASDecoder(data.buffer,
  51330. header.pointsFormatId,
  51331. header.pointsStructSize,
  51332. data.count,
  51333. header.scale,
  51334. header.offset,
  51335. header.mins, header.maxs));
  51336. totalRead += data.count;
  51337. LasLazLoader.progressCB(totalRead / totalToRead);
  51338. hasMoreData = data.hasMoreData;
  51339. }
  51340. header.totalRead = totalRead;
  51341. header.versionAsString = lf.versionAsString;
  51342. header.isCompressed = lf.isCompressed;
  51343. LasLazLoader.progressCB(1);
  51344. try{
  51345. await lf.close();
  51346. lf.isOpen = false;
  51347. }catch(e){
  51348. console.error("failed to close las/laz file!!!");
  51349. throw e;
  51350. }
  51351. }
  51352. handle (node, url) {
  51353. }
  51354. };
  51355. class LasLazBatcher{
  51356. constructor (node) {
  51357. this.node = node;
  51358. }
  51359. push (lasBuffer) {
  51360. const workerPath = Potree.scriptPath + '/workers/LASDecoderWorker.js';
  51361. const worker = Potree.workerPool.getWorker(workerPath);
  51362. const node = this.node;
  51363. const pointAttributes = node.pcoGeometry.pointAttributes;
  51364. worker.onmessage = (e) => {
  51365. let geometry = new BufferGeometry();
  51366. let numPoints = lasBuffer.pointsCount;
  51367. let positions = new Float32Array(e.data.position);
  51368. let colors = new Uint8Array(e.data.color);
  51369. let intensities = new Float32Array(e.data.intensity);
  51370. let classifications = new Uint8Array(e.data.classification);
  51371. let returnNumbers = new Uint8Array(e.data.returnNumber);
  51372. let numberOfReturns = new Uint8Array(e.data.numberOfReturns);
  51373. let pointSourceIDs = new Uint16Array(e.data.pointSourceID);
  51374. let indices = new Uint8Array(e.data.indices);
  51375. geometry.setAttribute('position', new BufferAttribute(positions, 3));
  51376. geometry.setAttribute('color', new BufferAttribute(colors, 4, true));
  51377. geometry.setAttribute('intensity', new BufferAttribute(intensities, 1));
  51378. geometry.setAttribute('classification', new BufferAttribute(classifications, 1));
  51379. geometry.setAttribute('return number', new BufferAttribute(returnNumbers, 1));
  51380. geometry.setAttribute('number of returns', new BufferAttribute(numberOfReturns, 1));
  51381. geometry.setAttribute('source id', new BufferAttribute(pointSourceIDs, 1));
  51382. geometry.setAttribute('indices', new BufferAttribute(indices, 4));
  51383. geometry.attributes.indices.normalized = true;
  51384. for(const key in e.data.ranges){
  51385. const range = e.data.ranges[key];
  51386. const attribute = pointAttributes.attributes.find(a => a.name === key);
  51387. attribute.range[0] = Math.min(attribute.range[0], range[0]);
  51388. attribute.range[1] = Math.max(attribute.range[1], range[1]);
  51389. }
  51390. let tightBoundingBox = new Box3(
  51391. new Vector3().fromArray(e.data.tightBoundingBox.min),
  51392. new Vector3().fromArray(e.data.tightBoundingBox.max)
  51393. );
  51394. geometry.boundingBox = this.node.boundingBox;
  51395. this.node.tightBoundingBox = tightBoundingBox;
  51396. this.node.geometry = geometry;
  51397. this.node.numPoints = numPoints;
  51398. this.node.loaded = true;
  51399. this.node.loading = false;
  51400. Potree.numNodesLoading--;
  51401. this.node.mean = new Vector3(...e.data.mean);
  51402. Potree.workerPool.returnWorker(workerPath, worker);
  51403. };
  51404. let message = {
  51405. buffer: lasBuffer.arrayb,
  51406. numPoints: lasBuffer.pointsCount,
  51407. pointSize: lasBuffer.pointSize,
  51408. pointFormatID: 2,
  51409. scale: lasBuffer.scale,
  51410. offset: lasBuffer.offset,
  51411. mins: lasBuffer.mins,
  51412. maxs: lasBuffer.maxs
  51413. };
  51414. worker.postMessage(message, [message.buffer]);
  51415. };
  51416. }
  51417. function parseAttributes(cloudjs){
  51418. let version = new Version(cloudjs.version);
  51419. const replacements = {
  51420. "COLOR_PACKED": "rgba",
  51421. "RGBA": "rgba",
  51422. "INTENSITY": "intensity",
  51423. "CLASSIFICATION": "classification",
  51424. "GPS_TIME": "gps-time",
  51425. };
  51426. const replaceOldNames = (old) => {
  51427. if(replacements[old]){
  51428. return replacements[old];
  51429. }else {
  51430. return old;
  51431. }
  51432. };
  51433. const pointAttributes = [];
  51434. if(version.upTo('1.7')){
  51435. for(let attributeName of cloudjs.pointAttributes){
  51436. const oldAttribute = PointAttribute[attributeName];
  51437. const attribute = {
  51438. name: oldAttribute.name,
  51439. size: oldAttribute.byteSize,
  51440. elements: oldAttribute.numElements,
  51441. elementSize: oldAttribute.byteSize / oldAttribute.numElements,
  51442. type: oldAttribute.type.name,
  51443. description: "",
  51444. };
  51445. pointAttributes.push(attribute);
  51446. }
  51447. }else {
  51448. pointAttributes.push(...cloudjs.pointAttributes);
  51449. }
  51450. {
  51451. const attributes = new PointAttributes();
  51452. const typeConversion = {
  51453. int8: PointAttributeTypes.DATA_TYPE_INT8,
  51454. int16: PointAttributeTypes.DATA_TYPE_INT16,
  51455. int32: PointAttributeTypes.DATA_TYPE_INT32,
  51456. int64: PointAttributeTypes.DATA_TYPE_INT64,
  51457. uint8: PointAttributeTypes.DATA_TYPE_UINT8,
  51458. uint16: PointAttributeTypes.DATA_TYPE_UINT16,
  51459. uint32: PointAttributeTypes.DATA_TYPE_UINT32,
  51460. uint64: PointAttributeTypes.DATA_TYPE_UINT64,
  51461. double: PointAttributeTypes.DATA_TYPE_DOUBLE,
  51462. float: PointAttributeTypes.DATA_TYPE_FLOAT,
  51463. };
  51464. for(let jsAttribute of pointAttributes){
  51465. if(jsAttribute.name == void 0){ //add 有的是这个,也有的不是(点云编辑页的)
  51466. var attribute_ = PointAttribute[jsAttribute];
  51467. attributes.add(attribute_);
  51468. continue;
  51469. }
  51470. const name = replaceOldNames(jsAttribute.name);
  51471. const type = typeConversion[jsAttribute.type];
  51472. const numElements = jsAttribute.elements;
  51473. const description = jsAttribute.description;
  51474. const attribute = new PointAttribute(name, type, numElements);
  51475. attributes.add(attribute);
  51476. }
  51477. {
  51478. // check if it has normals
  51479. let hasNormals =
  51480. pointAttributes.find(a => a.name === "NormalX") !== undefined &&
  51481. pointAttributes.find(a => a.name === "NormalY") !== undefined &&
  51482. pointAttributes.find(a => a.name === "NormalZ") !== undefined;
  51483. if(hasNormals){
  51484. let vector = {
  51485. name: "NORMAL",
  51486. attributes: ["NormalX", "NormalY", "NormalZ"],
  51487. };
  51488. attributes.addVector(vector);
  51489. }
  51490. }
  51491. return attributes;
  51492. }
  51493. }
  51494. function lasLazAttributes(fMno){
  51495. const attributes = new PointAttributes();
  51496. attributes.add(PointAttribute.POSITION_CARTESIAN);
  51497. attributes.add(new PointAttribute("rgba", PointAttributeTypes.DATA_TYPE_UINT8, 4));
  51498. attributes.add(new PointAttribute("intensity", PointAttributeTypes.DATA_TYPE_UINT16, 1));
  51499. attributes.add(new PointAttribute("classification", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  51500. attributes.add(new PointAttribute("gps-time", PointAttributeTypes.DATA_TYPE_DOUBLE, 1));
  51501. attributes.add(new PointAttribute("number of returns", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  51502. attributes.add(new PointAttribute("return number", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  51503. attributes.add(new PointAttribute("source id", PointAttributeTypes.DATA_TYPE_UINT16, 1));
  51504. //attributes.add(new PointAttribute("pointSourceID", PointAttributeTypes.DATA_TYPE_INT8, 4));
  51505. return attributes;
  51506. }
  51507. class POCLoader {
  51508. static load(url, timeStamp, callback){ //add timeStamp
  51509. try {
  51510. let pco = new PointCloudOctreeGeometry();
  51511. pco.timeStamp = timeStamp;
  51512. let startLoad = (realUrl)=>{
  51513. pco.realUrl = realUrl;
  51514. let xhr = XHRFactory.createXMLHttpRequest();
  51515. xhr.open('GET', realUrl /* +'?m='+timeStamp */, true);
  51516. xhr.onreadystatechange = function () {
  51517. if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 0)) {
  51518. let fMno = JSON.parse(xhr.responseText);
  51519. let version = new Version(fMno.version);
  51520. // assume octreeDir is absolute if it starts with http
  51521. if (fMno.octreeDir.indexOf('http') === 0) {
  51522. pco.octreeDir = fMno.octreeDir;
  51523. } else {
  51524. pco.octreeDir = url + '/../' + fMno.octreeDir;
  51525. }
  51526. pco.spacing = fMno.spacing;
  51527. pco.hierarchyStepSize = fMno.hierarchyStepSize;
  51528. pco.pointAttributes = fMno.pointAttributes;
  51529. let min = new Vector3(fMno.boundingBox.lx, fMno.boundingBox.ly, fMno.boundingBox.lz);
  51530. let max = new Vector3(fMno.boundingBox.ux, fMno.boundingBox.uy, fMno.boundingBox.uz);
  51531. let boundingBox = new Box3(min, max);
  51532. let tightBoundingBox = boundingBox.clone();
  51533. if (fMno.tightBoundingBox) {//这个才是真实的bounding,前面那个bounding的size是个正方体,似乎取了最长边作为边长
  51534. tightBoundingBox.min.copy(new Vector3(fMno.tightBoundingBox.lx, fMno.tightBoundingBox.ly, fMno.tightBoundingBox.lz));
  51535. tightBoundingBox.max.copy(new Vector3(fMno.tightBoundingBox.ux, fMno.tightBoundingBox.uy, fMno.tightBoundingBox.uz));
  51536. }
  51537. let offset = min.clone(); //将成为点云的position,被我用作旋转中心(但在点云中不那么居中,navvis也是这样, 这样可能是为了让模型在这数据的bounding上)
  51538. boundingBox.min.sub(offset); //点云的真实坐标的min都是0,0,0吗(我看案例是,因绕角落旋转,也就是原点)
  51539. boundingBox.max.sub(offset);
  51540. tightBoundingBox.min.sub(offset);
  51541. tightBoundingBox.max.sub(offset);
  51542. //改
  51543. //pco.projection = fMno.projection || "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs ",
  51544. //"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" //给地图
  51545. pco.boundingBox = boundingBox;
  51546. pco.tightBoundingBox = tightBoundingBox;
  51547. pco.boundingSphere = boundingBox.getBoundingSphere(new Sphere());
  51548. pco.tightBoundingSphere = tightBoundingBox.getBoundingSphere(new Sphere());
  51549. pco.offset = offset;
  51550. if (fMno.pointAttributes === 'LAS') {
  51551. pco.loader = new LasLazLoader(fMno.version, "las");
  51552. pco.pointAttributes = lasLazAttributes(fMno);
  51553. } else if (fMno.pointAttributes === 'LAZ') {
  51554. pco.loader = new LasLazLoader(fMno.version, "laz");
  51555. pco.pointAttributes = lasLazAttributes(fMno);
  51556. } else {
  51557. pco.loader = new BinaryLoader(fMno.version, boundingBox, fMno.scale);
  51558. pco.pointAttributes = parseAttributes(fMno);
  51559. }
  51560. let nodes = {};
  51561. { // load root
  51562. let name = 'r';
  51563. let root = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
  51564. root.level = 0;
  51565. root.hasChildren = true;
  51566. root.spacing = pco.spacing;
  51567. if (version.upTo('1.5')) {
  51568. root.numPoints = fMno.hierarchy[0][1];
  51569. } else {
  51570. root.numPoints = 0;
  51571. }
  51572. pco.root = root;
  51573. pco.root.load();
  51574. nodes[name] = root;
  51575. }
  51576. // load remaining hierarchy
  51577. if (version.upTo('1.4')) {
  51578. for (let i = 1; i < fMno.hierarchy.length; i++) {
  51579. let name = fMno.hierarchy[i][0];
  51580. let numPoints = fMno.hierarchy[i][1];
  51581. let index = parseInt(name.charAt(name.length - 1));
  51582. let parentName = name.substring(0, name.length - 1);
  51583. let parentNode = nodes[parentName];
  51584. let level = name.length - 1;
  51585. //let boundingBox = POCLoader.createChildAABB(parentNode.boundingBox, index);
  51586. let boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
  51587. let node = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
  51588. node.level = level;
  51589. node.numPoints = numPoints;
  51590. node.spacing = pco.spacing / Math.pow(2, level);
  51591. parentNode.addChild(node);
  51592. nodes[name] = node;
  51593. }
  51594. }
  51595. pco.nodes = nodes;
  51596. callback(pco);
  51597. }
  51598. };
  51599. xhr.send(null);
  51600. };
  51601. Potree.getRealUrl(url, startLoad);
  51602. } catch (e) {
  51603. console.log("loading failed: '" + url + "'");
  51604. console.log(e);
  51605. callback();
  51606. }
  51607. }
  51608. loadPointAttributes(mno){
  51609. let fpa = mno.pointAttributes;
  51610. let pa = new PointAttributes();
  51611. for (let i = 0; i < fpa.length; i++) {
  51612. let pointAttribute = PointAttribute[fpa[i]];
  51613. pa.add(pointAttribute);
  51614. }
  51615. return pa;
  51616. }
  51617. createChildAABB(aabb, index){
  51618. let min = aabb.min.clone();
  51619. let max = aabb.max.clone();
  51620. let size = new Vector3().subVectors(max, min);
  51621. if ((index & 0b0001) > 0) {
  51622. min.z += size.z / 2;
  51623. } else {
  51624. max.z -= size.z / 2;
  51625. }
  51626. if ((index & 0b0010) > 0) {
  51627. min.y += size.y / 2;
  51628. } else {
  51629. max.y -= size.y / 2;
  51630. }
  51631. if ((index & 0b0100) > 0) {
  51632. min.x += size.x / 2;
  51633. } else {
  51634. max.x -= size.x / 2;
  51635. }
  51636. return new Box3(min, max);
  51637. }
  51638. }
  51639. class OctreeGeometry{
  51640. constructor(){
  51641. this.url = null;
  51642. this.spacing = 0;
  51643. this.boundingBox = null;
  51644. this.root = null;
  51645. this.pointAttributes = null;
  51646. this.loader = null;
  51647. }
  51648. };
  51649. class OctreeGeometryNode{
  51650. constructor(name, octreeGeometry, boundingBox){
  51651. this.id = OctreeGeometryNode.IDCount++;
  51652. this.name = name;
  51653. this.index = parseInt(name.charAt(name.length - 1));
  51654. this.octreeGeometry = octreeGeometry;
  51655. this.boundingBox = boundingBox;
  51656. this.boundingSphere = boundingBox.getBoundingSphere(new Sphere());
  51657. this.children = {};
  51658. this.numPoints = 0;
  51659. this.level = null;
  51660. this.oneTimeDisposeHandlers = [];
  51661. }
  51662. isGeometryNode(){
  51663. return true;
  51664. }
  51665. getLevel(){
  51666. return this.level;
  51667. }
  51668. isTreeNode(){
  51669. return false;
  51670. }
  51671. isLoaded(){
  51672. return this.loaded;
  51673. }
  51674. getBoundingSphere(){
  51675. return this.boundingSphere;
  51676. }
  51677. getBoundingBox(){
  51678. return this.boundingBox;
  51679. }
  51680. getChildren(){
  51681. let children = [];
  51682. for (let i = 0; i < 8; i++) {
  51683. if (this.children[i]) {
  51684. children.push(this.children[i]);
  51685. }
  51686. }
  51687. return children;
  51688. }
  51689. getBoundingBox(){
  51690. return this.boundingBox;
  51691. }
  51692. load(){
  51693. if (Potree.numNodesLoading >= Potree.maxNodesLoading) {
  51694. return;
  51695. }
  51696. this.octreeGeometry.loader.load(this);
  51697. }
  51698. getNumPoints(){
  51699. return this.numPoints;
  51700. }
  51701. dispose(){
  51702. if (this.geometry && this.parent != null) {
  51703. this.geometry.dispose();
  51704. this.geometry = null;
  51705. this.loaded = false;
  51706. // this.dispatchEvent( { type: 'dispose' } );
  51707. for (let i = 0; i < this.oneTimeDisposeHandlers.length; i++) {
  51708. let handler = this.oneTimeDisposeHandlers[i];
  51709. handler();
  51710. }
  51711. this.oneTimeDisposeHandlers = [];
  51712. }
  51713. }
  51714. };
  51715. OctreeGeometryNode.IDCount = 0;
  51716. // let loadedNodes = new Set();
  51717. class NodeLoader{
  51718. constructor(url){
  51719. this.url = url;
  51720. }
  51721. async load(node){
  51722. if(node.loaded || node.loading){
  51723. return;
  51724. }
  51725. node.loading = true;
  51726. Potree.numNodesLoading++;
  51727. // console.log(node.name, node.numPoints);
  51728. // if(loadedNodes.has(node.name)){
  51729. // // debugger;
  51730. // }
  51731. // loadedNodes.add(node.name);
  51732. try{
  51733. if(node.nodeType === 2){
  51734. await this.loadHierarchy(node);
  51735. }
  51736. let {byteOffset, byteSize} = node;
  51737. let urlOctree = `${this.url}/../octree.bin`;
  51738. let first = byteOffset;
  51739. let last = byteOffset + byteSize - 1n;
  51740. let buffer;
  51741. if(byteSize === 0n){
  51742. buffer = new ArrayBuffer(0);
  51743. console.warn(`loaded node with 0 bytes: ${node.name}`);
  51744. }else {
  51745. let response = await fetch(urlOctree, {
  51746. headers: {
  51747. 'content-type': 'multipart/byteranges',
  51748. 'Range': `bytes=${first}-${last}`,
  51749. },
  51750. });
  51751. buffer = await response.arrayBuffer();
  51752. }
  51753. let workerPath;
  51754. if(this.metadata.encoding === "BROTLI"){
  51755. workerPath = Potree.scriptPath + '/workers/2.0/DecoderWorker_brotli.js';
  51756. }else {
  51757. workerPath = Potree.scriptPath + '/workers/2.0/DecoderWorker.js';
  51758. }
  51759. let worker = Potree.workerPool.getWorker(workerPath);
  51760. worker.onmessage = function (e) {
  51761. let data = e.data;
  51762. let buffers = data.attributeBuffers;
  51763. Potree.workerPool.returnWorker(workerPath, worker);
  51764. let geometry = new BufferGeometry();
  51765. for(let property in buffers){
  51766. let buffer = buffers[property].buffer;
  51767. if(property === "position"){
  51768. geometry.setAttribute('position', new BufferAttribute(new Float32Array(buffer), 3));
  51769. }else if(property === "rgba"){
  51770. geometry.setAttribute('rgba', new BufferAttribute(new Uint8Array(buffer), 4, true));
  51771. }else if(property === "NORMAL"){
  51772. //geometry.setAttribute('rgba', new THREE.BufferAttribute(new Uint8Array(buffer), 4, true));
  51773. geometry.setAttribute('normal', new BufferAttribute(new Float32Array(buffer), 3));
  51774. }else if (property === "INDICES") {
  51775. let bufferAttribute = new BufferAttribute(new Uint8Array(buffer), 4);
  51776. bufferAttribute.normalized = true;
  51777. geometry.setAttribute('indices', bufferAttribute);
  51778. }else {
  51779. const bufferAttribute = new BufferAttribute(new Float32Array(buffer), 1);
  51780. let batchAttribute = buffers[property].attribute;
  51781. bufferAttribute.potree = {
  51782. offset: buffers[property].offset,
  51783. scale: buffers[property].scale,
  51784. preciseBuffer: buffers[property].preciseBuffer,
  51785. range: batchAttribute.range,
  51786. };
  51787. geometry.setAttribute(property, bufferAttribute);
  51788. }
  51789. }
  51790. // indices ??
  51791. node.density = data.density;
  51792. node.geometry = geometry;
  51793. node.loaded = true;
  51794. node.loading = false;
  51795. Potree.numNodesLoading--;
  51796. };
  51797. let pointAttributes = node.octreeGeometry.pointAttributes;
  51798. let scale = node.octreeGeometry.scale;
  51799. let box = node.boundingBox;
  51800. let min = node.octreeGeometry.offset.clone().add(box.min);
  51801. let size = box.max.clone().sub(box.min);
  51802. let max = min.clone().add(size);
  51803. let numPoints = node.numPoints;
  51804. let offset = node.octreeGeometry.loader.offset;
  51805. let message = {
  51806. name: node.name,
  51807. buffer: buffer,
  51808. pointAttributes: pointAttributes,
  51809. scale: scale,
  51810. min: min,
  51811. max: max,
  51812. size: size,
  51813. offset: offset,
  51814. numPoints: numPoints
  51815. };
  51816. worker.postMessage(message, [message.buffer]);
  51817. }catch(e){
  51818. node.loaded = false;
  51819. node.loading = false;
  51820. Potree.numNodesLoading--;
  51821. console.log(`failed to load ${node.name}`);
  51822. console.log(e);
  51823. console.log(`trying again!`);
  51824. }
  51825. }
  51826. parseHierarchy(node, buffer){
  51827. let view = new DataView(buffer);
  51828. let tStart = performance.now();
  51829. let bytesPerNode = 22;
  51830. let numNodes = buffer.byteLength / bytesPerNode;
  51831. let octree = node.octreeGeometry;
  51832. // let nodes = [node];
  51833. let nodes = new Array(numNodes);
  51834. nodes[0] = node;
  51835. let nodePos = 1;
  51836. for(let i = 0; i < numNodes; i++){
  51837. let current = nodes[i];
  51838. let type = view.getUint8(i * bytesPerNode + 0);
  51839. let childMask = view.getUint8(i * bytesPerNode + 1);
  51840. let numPoints = view.getUint32(i * bytesPerNode + 2, true);
  51841. let byteOffset = view.getBigInt64(i * bytesPerNode + 6, true);
  51842. let byteSize = view.getBigInt64(i * bytesPerNode + 14, true);
  51843. // if(byteSize === 0n){
  51844. // // debugger;
  51845. // }
  51846. if(current.nodeType === 2){
  51847. // replace proxy with real node
  51848. current.byteOffset = byteOffset;
  51849. current.byteSize = byteSize;
  51850. current.numPoints = numPoints;
  51851. }else if(type === 2){
  51852. // load proxy
  51853. current.hierarchyByteOffset = byteOffset;
  51854. current.hierarchyByteSize = byteSize;
  51855. current.numPoints = numPoints;
  51856. }else {
  51857. // load real node
  51858. current.byteOffset = byteOffset;
  51859. current.byteSize = byteSize;
  51860. current.numPoints = numPoints;
  51861. }
  51862. if(current.byteSize === 0n){
  51863. // workaround for issue #1125
  51864. // some inner nodes erroneously report >0 points even though have 0 points
  51865. // however, they still report a byteSize of 0, so based on that we now set node.numPoints to 0
  51866. current.numPoints = 0;
  51867. }
  51868. current.nodeType = type;
  51869. if(current.nodeType === 2){
  51870. continue;
  51871. }
  51872. for(let childIndex = 0; childIndex < 8; childIndex++){
  51873. let childExists = ((1 << childIndex) & childMask) !== 0;
  51874. if(!childExists){
  51875. continue;
  51876. }
  51877. let childName = current.name + childIndex;
  51878. let childAABB = createChildAABB(current.boundingBox, childIndex);
  51879. let child = new OctreeGeometryNode(childName, octree, childAABB);
  51880. child.name = childName;
  51881. child.spacing = current.spacing / 2;
  51882. child.level = current.level + 1;
  51883. current.children[childIndex] = child;
  51884. child.parent = current;
  51885. // nodes.push(child);
  51886. nodes[nodePos] = child;
  51887. nodePos++;
  51888. }
  51889. // if((i % 500) === 0){
  51890. // yield;
  51891. // }
  51892. }
  51893. let duration = (performance.now() - tStart);
  51894. // if(duration > 20){
  51895. // let msg = `duration: ${duration}ms, numNodes: ${numNodes}`;
  51896. // console.log(msg);
  51897. // }
  51898. }
  51899. async loadHierarchy(node){
  51900. let {hierarchyByteOffset, hierarchyByteSize} = node;
  51901. let hierarchyPath = `${this.url}/../hierarchy.bin`;
  51902. let first = hierarchyByteOffset;
  51903. let last = first + hierarchyByteSize - 1n;
  51904. let response = await fetch(hierarchyPath, {
  51905. headers: {
  51906. 'content-type': 'multipart/byteranges',
  51907. 'Range': `bytes=${first}-${last}`,
  51908. },
  51909. });
  51910. let buffer = await response.arrayBuffer();
  51911. this.parseHierarchy(node, buffer);
  51912. // let promise = new Promise((resolve) => {
  51913. // let generator = this.parseHierarchy(node, buffer);
  51914. // let repeatUntilDone = () => {
  51915. // let result = generator.next();
  51916. // if(result.done){
  51917. // resolve();
  51918. // }else{
  51919. // requestAnimationFrame(repeatUntilDone);
  51920. // }
  51921. // };
  51922. // repeatUntilDone();
  51923. // });
  51924. // await promise;
  51925. }
  51926. }
  51927. let tmpVec3 = new Vector3();
  51928. function createChildAABB(aabb, index){
  51929. let min = aabb.min.clone();
  51930. let max = aabb.max.clone();
  51931. let size = tmpVec3.subVectors(max, min);
  51932. if ((index & 0b0001) > 0) {
  51933. min.z += size.z / 2;
  51934. } else {
  51935. max.z -= size.z / 2;
  51936. }
  51937. if ((index & 0b0010) > 0) {
  51938. min.y += size.y / 2;
  51939. } else {
  51940. max.y -= size.y / 2;
  51941. }
  51942. if ((index & 0b0100) > 0) {
  51943. min.x += size.x / 2;
  51944. } else {
  51945. max.x -= size.x / 2;
  51946. }
  51947. return new Box3(min, max);
  51948. }
  51949. let typenameTypeattributeMap = {
  51950. "double": PointAttributeTypes.DATA_TYPE_DOUBLE,
  51951. "float": PointAttributeTypes.DATA_TYPE_FLOAT,
  51952. "int8": PointAttributeTypes.DATA_TYPE_INT8,
  51953. "uint8": PointAttributeTypes.DATA_TYPE_UINT8,
  51954. "int16": PointAttributeTypes.DATA_TYPE_INT16,
  51955. "uint16": PointAttributeTypes.DATA_TYPE_UINT16,
  51956. "int32": PointAttributeTypes.DATA_TYPE_INT32,
  51957. "uint32": PointAttributeTypes.DATA_TYPE_UINT32,
  51958. "int64": PointAttributeTypes.DATA_TYPE_INT64,
  51959. "uint64": PointAttributeTypes.DATA_TYPE_UINT64,
  51960. };
  51961. class OctreeLoader{
  51962. static parseAttributes(jsonAttributes){
  51963. let attributes = new PointAttributes();
  51964. let replacements = {
  51965. "rgb": "rgba",
  51966. };
  51967. for (const jsonAttribute of jsonAttributes) {
  51968. let {name, description, size, numElements, elementSize, min, max} = jsonAttribute;
  51969. let type = typenameTypeattributeMap[jsonAttribute.type];
  51970. let potreeAttributeName = replacements[name] ? replacements[name] : name;
  51971. let attribute = new PointAttribute(potreeAttributeName, type, numElements);
  51972. if(numElements === 1){
  51973. attribute.range = [min[0], max[0]];
  51974. }else {
  51975. attribute.range = [min, max];
  51976. }
  51977. if (name === "gps-time") { // HACK: Guard against bad gpsTime range in metadata, see potree/potree#909
  51978. if (attribute.range[0] === attribute.range[1]) {
  51979. attribute.range[1] += 1;
  51980. }
  51981. }
  51982. attribute.initialRange = attribute.range;
  51983. attributes.add(attribute);
  51984. }
  51985. {
  51986. // check if it has normals
  51987. let hasNormals =
  51988. attributes.attributes.find(a => a.name === "NormalX") !== undefined &&
  51989. attributes.attributes.find(a => a.name === "NormalY") !== undefined &&
  51990. attributes.attributes.find(a => a.name === "NormalZ") !== undefined;
  51991. if(hasNormals){
  51992. let vector = {
  51993. name: "NORMAL",
  51994. attributes: ["NormalX", "NormalY", "NormalZ"],
  51995. };
  51996. attributes.addVector(vector);
  51997. }
  51998. }
  51999. return attributes;
  52000. }
  52001. static async load(url){
  52002. let response = await fetch(url);
  52003. let metadata = await response.json();
  52004. let attributes = OctreeLoader.parseAttributes(metadata.attributes);
  52005. let loader = new NodeLoader(url);
  52006. loader.metadata = metadata;
  52007. loader.attributes = attributes;
  52008. loader.scale = metadata.scale;
  52009. loader.offset = metadata.offset;
  52010. let octree = new OctreeGeometry();
  52011. octree.url = url;
  52012. octree.spacing = metadata.spacing;
  52013. octree.scale = metadata.scale;
  52014. // let aPosition = metadata.attributes.find(a => a.name === "position");
  52015. // octree
  52016. let min = new Vector3(...metadata.boundingBox.min);
  52017. let max = new Vector3(...metadata.boundingBox.max);
  52018. let boundingBox = new Box3(min, max);
  52019. let offset = min.clone();
  52020. boundingBox.min.sub(offset);
  52021. boundingBox.max.sub(offset);
  52022. octree.projection = metadata.projection;
  52023. octree.boundingBox = boundingBox;
  52024. octree.tightBoundingBox = boundingBox.clone();
  52025. octree.boundingSphere = boundingBox.getBoundingSphere(new Sphere());
  52026. octree.tightBoundingSphere = boundingBox.getBoundingSphere(new Sphere());
  52027. octree.offset = offset;
  52028. octree.pointAttributes = OctreeLoader.parseAttributes(metadata.attributes);
  52029. octree.loader = loader;
  52030. let root = new OctreeGeometryNode("r", octree, boundingBox);
  52031. root.level = 0;
  52032. root.nodeType = 2;
  52033. root.hierarchyByteOffset = 0n;
  52034. root.hierarchyByteSize = BigInt(metadata.hierarchy.firstChunkSize);
  52035. root.hasChildren = false;
  52036. root.spacing = octree.spacing;
  52037. root.byteOffset = 0;
  52038. octree.root = root;
  52039. loader.load(root);
  52040. let result = {
  52041. geometry: octree,
  52042. };
  52043. return result;
  52044. }
  52045. };
  52046. /**
  52047. * @author Connor Manning
  52048. */
  52049. class EptLoader {
  52050. static async load(file, callback) {
  52051. let response = await fetch(file);
  52052. let json = await response.json();
  52053. let url = file.substr(0, file.lastIndexOf('ept.json'));
  52054. let geometry = new Potree.PointCloudEptGeometry(url, json);
  52055. let root = new Potree.PointCloudEptGeometryNode(geometry);
  52056. geometry.root = root;
  52057. geometry.root.load();
  52058. callback(geometry);
  52059. }
  52060. };
  52061. class EptBinaryLoader {
  52062. extension() {
  52063. return '.bin';
  52064. }
  52065. workerPath() {
  52066. return Potree.scriptPath + '/workers/EptBinaryDecoderWorker.js';
  52067. }
  52068. load(node) {
  52069. if (node.loaded) return;
  52070. let url = node.url() + this.extension();
  52071. let xhr = XHRFactory.createXMLHttpRequest();
  52072. xhr.open('GET', url, true);
  52073. xhr.responseType = 'arraybuffer';
  52074. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  52075. xhr.onreadystatechange = () => {
  52076. if (xhr.readyState === 4) {
  52077. if (xhr.status === 200) {
  52078. let buffer = xhr.response;
  52079. this.parse(node, buffer);
  52080. } else {
  52081. console.log('Failed ' + url + ': ' + xhr.status);
  52082. }
  52083. }
  52084. };
  52085. try {
  52086. xhr.send(null);
  52087. }
  52088. catch (e) {
  52089. console.log('Failed request: ' + e);
  52090. }
  52091. }
  52092. parse(node, buffer) {
  52093. let workerPath = this.workerPath();
  52094. let worker = Potree.workerPool.getWorker(workerPath);
  52095. worker.onmessage = function(e) {
  52096. let g = new BufferGeometry();
  52097. let numPoints = e.data.numPoints;
  52098. let position = new Float32Array(e.data.position);
  52099. g.setAttribute('position', new BufferAttribute(position, 3));
  52100. let indices = new Uint8Array(e.data.indices);
  52101. g.setAttribute('indices', new BufferAttribute(indices, 4));
  52102. if (e.data.color) {
  52103. let color = new Uint8Array(e.data.color);
  52104. g.setAttribute('color', new BufferAttribute(color, 4, true));
  52105. }
  52106. if (e.data.intensity) {
  52107. let intensity = new Float32Array(e.data.intensity);
  52108. g.setAttribute('intensity',
  52109. new BufferAttribute(intensity, 1));
  52110. }
  52111. if (e.data.classification) {
  52112. let classification = new Uint8Array(e.data.classification);
  52113. g.setAttribute('classification',
  52114. new BufferAttribute(classification, 1));
  52115. }
  52116. if (e.data.returnNumber) {
  52117. let returnNumber = new Uint8Array(e.data.returnNumber);
  52118. g.setAttribute('return number',
  52119. new BufferAttribute(returnNumber, 1));
  52120. }
  52121. if (e.data.numberOfReturns) {
  52122. let numberOfReturns = new Uint8Array(e.data.numberOfReturns);
  52123. g.setAttribute('number of returns',
  52124. new BufferAttribute(numberOfReturns, 1));
  52125. }
  52126. if (e.data.pointSourceId) {
  52127. let pointSourceId = new Uint16Array(e.data.pointSourceId);
  52128. g.setAttribute('source id',
  52129. new BufferAttribute(pointSourceId, 1));
  52130. }
  52131. g.attributes.indices.normalized = true;
  52132. let tightBoundingBox = new Box3(
  52133. new Vector3().fromArray(e.data.tightBoundingBox.min),
  52134. new Vector3().fromArray(e.data.tightBoundingBox.max)
  52135. );
  52136. node.doneLoading(
  52137. g,
  52138. tightBoundingBox,
  52139. numPoints,
  52140. new Vector3(...e.data.mean));
  52141. Potree.workerPool.returnWorker(workerPath, worker);
  52142. };
  52143. let toArray = (v) => [v.x, v.y, v.z];
  52144. let message = {
  52145. buffer: buffer,
  52146. schema: node.ept.schema,
  52147. scale: node.ept.eptScale,
  52148. offset: node.ept.eptOffset,
  52149. mins: toArray(node.key.b.min)
  52150. };
  52151. worker.postMessage(message, [message.buffer]);
  52152. }
  52153. };
  52154. /**
  52155. * laslaz code taken and adapted from plas.io js-laslaz
  52156. * http://plas.io/
  52157. * https://github.com/verma/plasio
  52158. *
  52159. * Thanks to Uday Verma and Howard Butler
  52160. *
  52161. */
  52162. class EptLaszipLoader {
  52163. load(node) {
  52164. if (node.loaded) return;
  52165. let url = node.url() + '.laz';
  52166. let xhr = XHRFactory.createXMLHttpRequest();
  52167. xhr.open('GET', url, true);
  52168. xhr.responseType = 'arraybuffer';
  52169. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  52170. xhr.onreadystatechange = () => {
  52171. if (xhr.readyState === 4) {
  52172. if (xhr.status === 200) {
  52173. let buffer = xhr.response;
  52174. this.parse(node, buffer);
  52175. } else {
  52176. console.log('Failed ' + url + ': ' + xhr.status);
  52177. }
  52178. }
  52179. };
  52180. xhr.send(null);
  52181. }
  52182. async parse(node, buffer){
  52183. let lf = new LASFile(buffer);
  52184. let handler = new EptLazBatcher(node);
  52185. try{
  52186. await lf.open();
  52187. lf.isOpen = true;
  52188. const header = await lf.getHeader();
  52189. {
  52190. let i = 0;
  52191. let toArray = (v) => [v.x, v.y, v.z];
  52192. let mins = toArray(node.key.b.min);
  52193. let maxs = toArray(node.key.b.max);
  52194. let hasMoreData = true;
  52195. while(hasMoreData){
  52196. const data = await lf.readData(1000000, 0, 1);
  52197. let d = new LASDecoder(
  52198. data.buffer,
  52199. header.pointsFormatId,
  52200. header.pointsStructSize,
  52201. data.count,
  52202. header.scale,
  52203. header.offset,
  52204. mins,
  52205. maxs);
  52206. d.extraBytes = header.extraBytes;
  52207. d.pointsFormatId = header.pointsFormatId;
  52208. handler.push(d);
  52209. i += data.count;
  52210. hasMoreData = data.hasMoreData;
  52211. }
  52212. header.totalRead = i;
  52213. header.versionAsString = lf.versionAsString;
  52214. header.isCompressed = lf.isCompressed;
  52215. await lf.close();
  52216. lf.isOpen = false;
  52217. }
  52218. }catch(err){
  52219. console.error('Error reading LAZ:', err);
  52220. if (lf.isOpen) {
  52221. await lf.close();
  52222. lf.isOpen = false;
  52223. }
  52224. throw err;
  52225. }
  52226. }
  52227. };
  52228. class EptLazBatcher {
  52229. constructor(node) { this.node = node; }
  52230. push(las) {
  52231. let workerPath = Potree.scriptPath +
  52232. '/workers/EptLaszipDecoderWorker.js';
  52233. let worker = Potree.workerPool.getWorker(workerPath);
  52234. worker.onmessage = (e) => {
  52235. let g = new BufferGeometry();
  52236. let numPoints = las.pointsCount;
  52237. let positions = new Float32Array(e.data.position);
  52238. let colors = new Uint8Array(e.data.color);
  52239. let intensities = new Float32Array(e.data.intensity);
  52240. let classifications = new Uint8Array(e.data.classification);
  52241. let returnNumbers = new Uint8Array(e.data.returnNumber);
  52242. let numberOfReturns = new Uint8Array(e.data.numberOfReturns);
  52243. let pointSourceIDs = new Uint16Array(e.data.pointSourceID);
  52244. let indices = new Uint8Array(e.data.indices);
  52245. let gpsTime = new Float32Array(e.data.gpsTime);
  52246. g.setAttribute('position',
  52247. new BufferAttribute(positions, 3));
  52248. g.setAttribute('rgba',
  52249. new BufferAttribute(colors, 4, true));
  52250. g.setAttribute('intensity',
  52251. new BufferAttribute(intensities, 1));
  52252. g.setAttribute('classification',
  52253. new BufferAttribute(classifications, 1));
  52254. g.setAttribute('return number',
  52255. new BufferAttribute(returnNumbers, 1));
  52256. g.setAttribute('number of returns',
  52257. new BufferAttribute(numberOfReturns, 1));
  52258. g.setAttribute('source id',
  52259. new BufferAttribute(pointSourceIDs, 1));
  52260. g.setAttribute('indices',
  52261. new BufferAttribute(indices, 4));
  52262. g.setAttribute('gpsTime',
  52263. new BufferAttribute(gpsTime, 1));
  52264. this.node.gpsTime = e.data.gpsMeta;
  52265. g.attributes.indices.normalized = true;
  52266. let tightBoundingBox = new Box3(
  52267. new Vector3().fromArray(e.data.tightBoundingBox.min),
  52268. new Vector3().fromArray(e.data.tightBoundingBox.max)
  52269. );
  52270. this.node.doneLoading(
  52271. g,
  52272. tightBoundingBox,
  52273. numPoints,
  52274. new Vector3(...e.data.mean));
  52275. Potree.workerPool.returnWorker(workerPath, worker);
  52276. };
  52277. let message = {
  52278. buffer: las.arrayb,
  52279. numPoints: las.pointsCount,
  52280. pointSize: las.pointSize,
  52281. pointFormatID: las.pointsFormatId,
  52282. scale: las.scale,
  52283. offset: las.offset,
  52284. mins: las.mins,
  52285. maxs: las.maxs
  52286. };
  52287. worker.postMessage(message, [message.buffer]);
  52288. };
  52289. };
  52290. class EptZstandardLoader extends EptBinaryLoader {
  52291. extension() {
  52292. return '.zst';
  52293. }
  52294. workerPath() {
  52295. return Potree.scriptPath + '/workers/EptZstandardDecoderWorker.js';
  52296. }
  52297. };
  52298. class ShapefileLoader{
  52299. constructor(){
  52300. this.transform = null;
  52301. }
  52302. async load(path){
  52303. const matLine = new LineMaterial( {
  52304. color: 0xff0000,
  52305. linewidth: 3, // in pixels
  52306. resolution: new Vector2(1000, 1000),
  52307. dashed: false
  52308. } );
  52309. const features = await this.loadShapefileFeatures(path);
  52310. const node = new Object3D();
  52311. for(const feature of features){
  52312. const fnode = this.featureToSceneNode(feature, matLine);
  52313. node.add(fnode);
  52314. }
  52315. let setResolution = (x, y) => {
  52316. matLine.resolution.set(x, y);
  52317. };
  52318. const result = {
  52319. features: features,
  52320. node: node,
  52321. setResolution: setResolution,
  52322. };
  52323. return result;
  52324. }
  52325. featureToSceneNode(feature, matLine){
  52326. let geometry = feature.geometry;
  52327. let color = new Color(1, 1, 1);
  52328. let transform = this.transform;
  52329. if(transform === null){
  52330. transform = {forward: (v) => v};
  52331. }
  52332. if(feature.geometry.type === "Point"){
  52333. let sg = new SphereGeometry(1, 18, 18);
  52334. let sm = new MeshNormalMaterial();
  52335. let s = new Mesh(sg, sm);
  52336. let [long, lat] = geometry.coordinates;
  52337. let pos = transform.forward([long, lat]);
  52338. s.position.set(...pos, 20);
  52339. s.scale.set(10, 10, 10);
  52340. return s;
  52341. }else if(geometry.type === "LineString"){
  52342. let coordinates = [];
  52343. let min = new Vector3(Infinity, Infinity, Infinity);
  52344. for(let i = 0; i < geometry.coordinates.length; i++){
  52345. let [long, lat] = geometry.coordinates[i];
  52346. let pos = transform.forward([long, lat]);
  52347. min.x = Math.min(min.x, pos[0]);
  52348. min.y = Math.min(min.y, pos[1]);
  52349. min.z = Math.min(min.z, 20);
  52350. coordinates.push(...pos, 20);
  52351. if(i > 0 && i < geometry.coordinates.length - 1){
  52352. coordinates.push(...pos, 20);
  52353. }
  52354. }
  52355. for(let i = 0; i < coordinates.length; i += 3){
  52356. coordinates[i+0] -= min.x;
  52357. coordinates[i+1] -= min.y;
  52358. coordinates[i+2] -= min.z;
  52359. }
  52360. const lineGeometry = new LineGeometry();
  52361. lineGeometry.setPositions( coordinates );
  52362. const line = new Line2( lineGeometry, matLine );
  52363. line.computeLineDistances();
  52364. line.scale.set( 1, 1, 1 );
  52365. line.position.copy(min);
  52366. return line;
  52367. }else if(geometry.type === "Polygon"){
  52368. for(let pc of geometry.coordinates){
  52369. let coordinates = [];
  52370. let min = new Vector3(Infinity, Infinity, Infinity);
  52371. for(let i = 0; i < pc.length; i++){
  52372. let [long, lat] = pc[i];
  52373. let pos = transform.forward([long, lat]);
  52374. min.x = Math.min(min.x, pos[0]);
  52375. min.y = Math.min(min.y, pos[1]);
  52376. min.z = Math.min(min.z, 20);
  52377. coordinates.push(...pos, 20);
  52378. if(i > 0 && i < pc.length - 1){
  52379. coordinates.push(...pos, 20);
  52380. }
  52381. }
  52382. for(let i = 0; i < coordinates.length; i += 3){
  52383. coordinates[i+0] -= min.x;
  52384. coordinates[i+1] -= min.y;
  52385. coordinates[i+2] -= min.z;
  52386. }
  52387. const lineGeometry = new LineGeometry();
  52388. lineGeometry.setPositions( coordinates );
  52389. const line = new Line2( lineGeometry, matLine );
  52390. line.computeLineDistances();
  52391. line.scale.set( 1, 1, 1 );
  52392. line.position.copy(min);
  52393. return line;
  52394. }
  52395. }else {
  52396. console.log("unhandled feature: ", feature);
  52397. }
  52398. }
  52399. async loadShapefileFeatures(file){
  52400. let features = [];
  52401. let source = await shapefile.open(file);
  52402. while(true){
  52403. let result = await source.read();
  52404. if (result.done) {
  52405. break;
  52406. }
  52407. if (result.value && result.value.type === 'Feature' && result.value.geometry !== undefined) {
  52408. features.push(result.value);
  52409. }
  52410. }
  52411. return features;
  52412. }
  52413. };
  52414. const defaultColors = {
  52415. "landuse": [0.5, 0.5, 0.5],
  52416. "natural": [0.0, 1.0, 0.0],
  52417. "places": [1.0, 0.0, 1.0],
  52418. "points": [0.0, 1.0, 1.0],
  52419. "roads": [1.0, 1.0, 0.0],
  52420. "waterways": [0.0, 0.0, 1.0],
  52421. "default": [0.9, 0.6, 0.1],
  52422. };
  52423. function getColor(feature){
  52424. let color = defaultColors[feature];
  52425. if(!color){
  52426. color = defaultColors["default"];
  52427. }
  52428. return color;
  52429. }
  52430. class Geopackage$1{
  52431. constructor(){
  52432. this.path = null;
  52433. this.node = null;
  52434. }
  52435. };
  52436. class GeoPackageLoader{
  52437. constructor(){
  52438. }
  52439. static async loadUrl(url, params){
  52440. await Promise.all([
  52441. Utils.loadScript(`${Potree.scriptPath}/lazylibs/geopackage/geopackage.js`),
  52442. Utils.loadScript(`${Potree.scriptPath}/lazylibs/sql.js/sql-wasm.js`),
  52443. ]);
  52444. const result = await fetch(url);
  52445. const buffer = await result.arrayBuffer();
  52446. params = params || {};
  52447. params.source = url;
  52448. return GeoPackageLoader.loadBuffer(buffer, params);
  52449. }
  52450. static async loadBuffer(buffer, params){
  52451. await Promise.all([
  52452. Utils.loadScript(`${Potree.scriptPath}/lazylibs/geopackage/geopackage.js`),
  52453. Utils.loadScript(`${Potree.scriptPath}/lazylibs/sql.js/sql-wasm.js`),
  52454. ]);
  52455. params = params || {};
  52456. const resolver = async (resolve) => {
  52457. let transform = params.transform;
  52458. if(!transform){
  52459. transform = {forward: (arg) => arg};
  52460. }
  52461. const wasmPath = `${Potree.scriptPath}/lazylibs/sql.js/sql-wasm.wasm`;
  52462. const SQL = await initSqlJs({ locateFile: filename => wasmPath});
  52463. const u8 = new Uint8Array(buffer);
  52464. const data = await geopackage.open(u8);
  52465. window.data = data;
  52466. const geopackageNode = new Object3D();
  52467. geopackageNode.name = params.source;
  52468. geopackageNode.potree = {
  52469. source: params.source,
  52470. };
  52471. const geo = new Geopackage$1();
  52472. geo.path = params.source;
  52473. geo.node = geopackageNode;
  52474. const tables = data.getTables();
  52475. for(const table of tables.features){
  52476. const dao = data.getFeatureDao(table);
  52477. let boundingBox = dao.getBoundingBox();
  52478. boundingBox = boundingBox.projectBoundingBox(dao.projection, 'EPSG:4326');
  52479. const geoJson = data.queryForGeoJSONFeaturesInTable(table, boundingBox);
  52480. const matLine = new LineMaterial( {
  52481. color: new Color().setRGB(...getColor(table)),
  52482. linewidth: 2,
  52483. resolution: new Vector2(1000, 1000),
  52484. dashed: false
  52485. } );
  52486. const node = new Object3D();
  52487. node.name = table;
  52488. geo.node.add(node);
  52489. for(const [index, feature] of Object.entries(geoJson)){
  52490. //const featureNode = GeoPackageLoader.featureToSceneNode(feature, matLine, transform);
  52491. const featureNode = GeoPackageLoader.featureToSceneNode(feature, matLine, dao.projection, transform);
  52492. node.add(featureNode);
  52493. }
  52494. }
  52495. resolve(geo);
  52496. };
  52497. return new Promise(resolver);
  52498. }
  52499. static featureToSceneNode(feature, matLine, geopackageProjection, transform){
  52500. let geometry = feature.geometry;
  52501. let color = new Color(1, 1, 1);
  52502. if(feature.geometry.type === "Point"){
  52503. let sg = new SphereGeometry(1, 18, 18);
  52504. let sm = new MeshNormalMaterial();
  52505. let s = new Mesh(sg, sm);
  52506. let [long, lat] = geometry.coordinates;
  52507. let pos = transform.forward(geopackageProjection.forward([long, lat]));
  52508. s.position.set(...pos, 20);
  52509. s.scale.set(10, 10, 10);
  52510. return s;
  52511. }else if(geometry.type === "LineString"){
  52512. let coordinates = [];
  52513. let min = new Vector3(Infinity, Infinity, Infinity);
  52514. for(let i = 0; i < geometry.coordinates.length; i++){
  52515. let [long, lat] = geometry.coordinates[i];
  52516. let pos = transform.forward(geopackageProjection.forward([long, lat]));
  52517. min.x = Math.min(min.x, pos[0]);
  52518. min.y = Math.min(min.y, pos[1]);
  52519. min.z = Math.min(min.z, 20);
  52520. coordinates.push(...pos, 20);
  52521. if(i > 0 && i < geometry.coordinates.length - 1){
  52522. coordinates.push(...pos, 20);
  52523. }
  52524. }
  52525. for(let i = 0; i < coordinates.length; i += 3){
  52526. coordinates[i+0] -= min.x;
  52527. coordinates[i+1] -= min.y;
  52528. coordinates[i+2] -= min.z;
  52529. }
  52530. const lineGeometry = new LineGeometry();
  52531. lineGeometry.setPositions( coordinates );
  52532. const line = new Line2( lineGeometry, matLine );
  52533. line.computeLineDistances();
  52534. line.scale.set( 1, 1, 1 );
  52535. line.position.copy(min);
  52536. return line;
  52537. }else if(geometry.type === "Polygon"){
  52538. for(let pc of geometry.coordinates){
  52539. let coordinates = [];
  52540. let min = new Vector3(Infinity, Infinity, Infinity);
  52541. for(let i = 0; i < pc.length; i++){
  52542. let [long, lat] = pc[i];
  52543. let pos = transform.forward(geopackageProjection.forward([long, lat]));
  52544. min.x = Math.min(min.x, pos[0]);
  52545. min.y = Math.min(min.y, pos[1]);
  52546. min.z = Math.min(min.z, 20);
  52547. coordinates.push(...pos, 20);
  52548. if(i > 0 && i < pc.length - 1){
  52549. coordinates.push(...pos, 20);
  52550. }
  52551. }
  52552. for(let i = 0; i < coordinates.length; i += 3){
  52553. coordinates[i+0] -= min.x;
  52554. coordinates[i+1] -= min.y;
  52555. coordinates[i+2] -= min.z;
  52556. }
  52557. const lineGeometry = new LineGeometry();
  52558. lineGeometry.setPositions( coordinates );
  52559. const line = new Line2( lineGeometry, matLine );
  52560. line.computeLineDistances();
  52561. line.scale.set( 1, 1, 1 );
  52562. line.position.copy(min);
  52563. return line;
  52564. }
  52565. }else {
  52566. console.log("unhandled feature: ", feature);
  52567. }
  52568. }
  52569. };
  52570. class ClipVolume extends Object3D{
  52571. constructor(args){
  52572. super();
  52573. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  52574. this.name = "clip_volume_" + this.constructor.counter;
  52575. let alpha = args.alpha || 0;
  52576. let beta = args.beta || 0;
  52577. let gamma = args.gamma || 0;
  52578. this.rotation.x = alpha;
  52579. this.rotation.y = beta;
  52580. this.rotation.z = gamma;
  52581. this.clipOffset = 0.001;
  52582. this.clipRotOffset = 1;
  52583. let boxGeometry = new BoxGeometry(1, 1, 1);
  52584. boxGeometry.computeBoundingBox();
  52585. let boxFrameGeometry = new Geometry();
  52586. {
  52587. // bottom
  52588. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  52589. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  52590. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  52591. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  52592. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  52593. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  52594. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  52595. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  52596. // top
  52597. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  52598. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  52599. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  52600. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  52601. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  52602. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  52603. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  52604. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  52605. // sides
  52606. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  52607. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  52608. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  52609. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  52610. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  52611. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  52612. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  52613. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  52614. boxFrameGeometry.colors.push(new Vector3(1, 1, 1));
  52615. }
  52616. let planeFrameGeometry = new Geometry();
  52617. {
  52618. // middle line
  52619. planeFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.0));
  52620. planeFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.0));
  52621. planeFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.0));
  52622. planeFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.0));
  52623. planeFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.0));
  52624. planeFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.0));
  52625. planeFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.0));
  52626. planeFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.0));
  52627. }
  52628. this.dimension = new Vector3(1, 1, 1);
  52629. this.material = new MeshBasicMaterial( {
  52630. color: 0x00ff00,
  52631. transparent: true,
  52632. opacity: 0.3,
  52633. depthTest: true,
  52634. depthWrite: false} );
  52635. this.box = new Mesh(boxGeometry, this.material);
  52636. this.box.geometry.computeBoundingBox();
  52637. this.boundingBox = this.box.geometry.boundingBox;
  52638. this.add(this.box);
  52639. this.frame = new LineSegments( boxFrameGeometry, new LineBasicMaterial({color: 0x000000}));
  52640. this.add(this.frame);
  52641. this.planeFrame = new LineSegments( planeFrameGeometry, new LineBasicMaterial({color: 0xff0000}));
  52642. this.add(this.planeFrame);
  52643. // set default thickness
  52644. this.setScaleZ(0.1);
  52645. // create local coordinate system
  52646. let createArrow = (name, direction, color) => {
  52647. let material = new MeshBasicMaterial({
  52648. color: color,
  52649. depthTest: false,
  52650. depthWrite: false});
  52651. let shaftGeometry = new Geometry();
  52652. shaftGeometry.vertices.push(new Vector3(0, 0, 0));
  52653. shaftGeometry.vertices.push(new Vector3(0, 1, 0));
  52654. let shaftMaterial = new LineBasicMaterial({
  52655. color: color,
  52656. depthTest: false,
  52657. depthWrite: false,
  52658. transparent: true
  52659. });
  52660. let shaft = new Line(shaftGeometry, shaftMaterial);
  52661. shaft.name = name + "_shaft";
  52662. let headGeometry = new CylinderGeometry(0, 0.04, 0.1, 10, 1, false);
  52663. let headMaterial = material;
  52664. let head = new Mesh(headGeometry, headMaterial);
  52665. head.name = name + "_head";
  52666. head.position.y = 1;
  52667. let arrow = new Object3D();
  52668. arrow.name = name;
  52669. arrow.add(shaft);
  52670. arrow.add(head);
  52671. return arrow;
  52672. };
  52673. this.arrowX = createArrow("arrow_x", new Vector3(1, 0, 0), 0xFF0000);
  52674. this.arrowY = createArrow("arrow_y", new Vector3(0, 1, 0), 0x00FF00);
  52675. this.arrowZ = createArrow("arrow_z", new Vector3(0, 0, 1), 0x0000FF);
  52676. this.arrowX.rotation.z = -Math.PI / 2;
  52677. this.arrowZ.rotation.x = Math.PI / 2;
  52678. this.arrowX.visible = false;
  52679. this.arrowY.visible = false;
  52680. this.arrowZ.visible = false;
  52681. this.add(this.arrowX);
  52682. this.add(this.arrowY);
  52683. this.add(this.arrowZ);
  52684. { // event listeners
  52685. this.addEventListener("ui_select", e => {
  52686. this.arrowX.visible = true;
  52687. this.arrowY.visible = true;
  52688. this.arrowZ.visible = true;
  52689. });
  52690. this.addEventListener("ui_deselect", e => {
  52691. this.arrowX.visible = false;
  52692. this.arrowY.visible = false;
  52693. this.arrowZ.visible = false;
  52694. });
  52695. this.addEventListener("select", e => {
  52696. let scene_header = $("#" + this.name + " .scene_header");
  52697. if(!scene_header.next().is(":visible")) {
  52698. scene_header.click();
  52699. }
  52700. });
  52701. this.addEventListener("deselect", e => {
  52702. let scene_header = $("#" + this.name + " .scene_header");
  52703. if(scene_header.next().is(":visible")) {
  52704. scene_header.click();
  52705. }
  52706. });
  52707. }
  52708. this.update();
  52709. };
  52710. setClipOffset(offset) {
  52711. this.clipOffset = offset;
  52712. }
  52713. setClipRotOffset(offset) {
  52714. this.clipRotOffset = offset;
  52715. }
  52716. setScaleX(x) {
  52717. this.box.scale.x = x;
  52718. this.frame.scale.x = x;
  52719. this.planeFrame.scale.x = x;
  52720. }
  52721. setScaleY(y) {
  52722. this.box.scale.y = y;
  52723. this.frame.scale.y = y;
  52724. this.planeFrame.scale.y = y;
  52725. }
  52726. setScaleZ(z) {
  52727. this.box.scale.z = z;
  52728. this.frame.scale.z = z;
  52729. this.planeFrame.scale.z = z;
  52730. }
  52731. offset(args) {
  52732. let cs = args.cs || null;
  52733. let axis = args.axis || null;
  52734. let dir = args.dir || null;
  52735. if(!cs || !axis || !dir) return;
  52736. if(axis === "x") {
  52737. if(cs === "local") {
  52738. this.position.add(this.localX.clone().multiplyScalar(dir * this.clipOffset));
  52739. } else if(cs === "global") {
  52740. this.position.x = this.position.x + dir * this.clipOffset;
  52741. }
  52742. }else if(axis === "y") {
  52743. if(cs === "local") {
  52744. this.position.add(this.localY.clone().multiplyScalar(dir * this.clipOffset));
  52745. } else if(cs === "global") {
  52746. this.position.y = this.position.y + dir * this.clipOffset;
  52747. }
  52748. }else if(axis === "z") {
  52749. if(cs === "local") {
  52750. this.position.add(this.localZ.clone().multiplyScalar(dir * this.clipOffset));
  52751. } else if(cs === "global") {
  52752. this.position.z = this.position.z + dir * this.clipOffset;
  52753. }
  52754. }
  52755. this.dispatchEvent({"type": "clip_volume_changed", "viewer": viewer, "volume": this});
  52756. }
  52757. rotate(args) {
  52758. let cs = args.cs || null;
  52759. let axis = args.axis || null;
  52760. let dir = args.dir || null;
  52761. if(!cs || !axis || !dir) return;
  52762. if(cs === "local") {
  52763. if(axis === "x") {
  52764. this.rotateOnAxis(new Vector3(1, 0, 0), dir * this.clipRotOffset * Math.PI / 180);
  52765. } else if(axis === "y") {
  52766. this.rotateOnAxis(new Vector3(0, 1, 0), dir * this.clipRotOffset * Math.PI / 180);
  52767. } else if(axis === "z") {
  52768. this.rotateOnAxis(new Vector3(0, 0, 1), dir * this.clipRotOffset * Math.PI / 180);
  52769. }
  52770. } else if(cs === "global") {
  52771. let rotaxis = new Vector4(1, 0, 0, 0);
  52772. if(axis === "y") {
  52773. rotaxis = new Vector4(0, 1, 0, 0);
  52774. } else if(axis === "z") {
  52775. rotaxis = new Vector4(0, 0, 1, 0);
  52776. }
  52777. this.updateMatrixWorld();
  52778. let invM = newthis.matrixWorld.clone().invert();
  52779. rotaxis = rotaxis.applyMatrix4(invM).normalize();
  52780. rotaxis = new Vector3(rotaxis.x, rotaxis.y, rotaxis.z);
  52781. this.rotateOnAxis(rotaxis, dir * this.clipRotOffset * Math.PI / 180);
  52782. }
  52783. this.updateLocalSystem();
  52784. this.dispatchEvent({"type": "clip_volume_changed", "viewer": viewer, "volume": this});
  52785. }
  52786. update(){
  52787. this.boundingBox = this.box.geometry.boundingBox;
  52788. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  52789. this.box.visible = false;
  52790. this.updateLocalSystem();
  52791. };
  52792. updateLocalSystem() {
  52793. // extract local coordinate axes
  52794. let rotQuat = this.getWorldQuaternion();
  52795. this.localX = new Vector3(1, 0, 0).applyQuaternion(rotQuat).normalize();
  52796. this.localY = new Vector3(0, 1, 0).applyQuaternion(rotQuat).normalize();
  52797. this.localZ = new Vector3(0, 0, 1).applyQuaternion(rotQuat).normalize();
  52798. }
  52799. raycast(raycaster, intersects){
  52800. let is = [];
  52801. this.box.raycast(raycaster, is);
  52802. if(is.length > 0){
  52803. let I = is[0];
  52804. intersects.push({
  52805. distance: I.distance,
  52806. object: this,
  52807. point: I.point.clone()
  52808. });
  52809. }
  52810. };
  52811. };
  52812. //这个文件只是clipping polygon的,没用到
  52813. class ClippingTool extends EventDispatcher$1{
  52814. constructor(viewer){
  52815. super();
  52816. this.viewer = viewer;
  52817. this.maxPolygonVertices = 8;
  52818. this.addEventListener("start_inserting_clipping_volume", e => {
  52819. this.viewer.dispatchEvent({
  52820. type: "cancel_insertions"
  52821. });
  52822. });
  52823. this.sceneMarker = new Scene();
  52824. this.sceneVolume = new Scene();
  52825. this.sceneVolume.name = "scene_clip_volume";
  52826. this.viewer.inputHandler.registerInteractiveScene(this.sceneVolume);
  52827. this.onRemove = e => {
  52828. this.sceneVolume.remove(e.volume);
  52829. };
  52830. this.onAdd = e => {
  52831. this.sceneVolume.add(e.volume);
  52832. };
  52833. this.viewer.inputHandler.addEventListener("delete", e => {
  52834. let volumes = e.selection.filter(e => (e instanceof ClipVolume));
  52835. volumes.forEach(e => this.viewer.scene.removeClipVolume(e));
  52836. let polyVolumes = e.selection.filter(e => (e instanceof PolygonClipVolume));
  52837. polyVolumes.forEach(e => this.viewer.scene.removePolygonClipVolume(e));
  52838. });
  52839. }
  52840. setScene(scene){
  52841. if(this.scene === scene){
  52842. return;
  52843. }
  52844. if(this.scene){
  52845. this.scene.removeEventListeners("clip_volume_added", this.onAdd);
  52846. this.scene.removeEventListeners("clip_volume_removed", this.onRemove);
  52847. this.scene.removeEventListeners("polygon_clip_volume_added", this.onAdd);
  52848. this.scene.removeEventListeners("polygon_clip_volume_removed", this.onRemove);
  52849. }
  52850. this.scene = scene;
  52851. this.scene.addEventListener("clip_volume_added", this.onAdd);
  52852. this.scene.addEventListener("clip_volume_removed", this.onRemove);
  52853. this.scene.addEventListener("polygon_clip_volume_added", this.onAdd);
  52854. this.scene.addEventListener("polygon_clip_volume_removed", this.onRemove);
  52855. }
  52856. startInsertion(args = {}) {
  52857. let type = args.type || null;
  52858. if(!type) return null;
  52859. let domElement = this.viewer.renderer.domElement;
  52860. let canvasSize = this.viewer.renderer.getSize(new Vector2());
  52861. let svg = $(`
  52862. <svg height="${canvasSize.height}" width="${canvasSize.width}" style="position:absolute; pointer-events: none">
  52863. <defs>
  52864. <marker id="diamond" markerWidth="24" markerHeight="24" refX="12" refY="12"
  52865. markerUnits="userSpaceOnUse">
  52866. <circle cx="12" cy="12" r="6" fill="white" stroke="black" stroke-width="3"/>
  52867. </marker>
  52868. </defs>
  52869. <polyline fill="none" stroke="black"
  52870. style="stroke:rgb(0, 0, 0);
  52871. stroke-width:6;"
  52872. stroke-dasharray="9, 6"
  52873. stroke-dashoffset="2"
  52874. />
  52875. <polyline fill="none" stroke="black"
  52876. style="stroke:rgb(255, 255, 255);
  52877. stroke-width:2;"
  52878. stroke-dasharray="5, 10"
  52879. marker-start="url(#diamond)"
  52880. marker-mid="url(#diamond)"
  52881. marker-end="url(#diamond)"
  52882. />
  52883. </svg>`);
  52884. $(domElement.parentElement).append(svg);
  52885. let polyClipVol = new PolygonClipVolume(this.viewer.scene.getActiveCamera().clone());
  52886. this.dispatchEvent({"type": "start_inserting_clipping_volume"});
  52887. this.viewer.scene.addPolygonClipVolume(polyClipVol);
  52888. this.sceneMarker.add(polyClipVol);
  52889. let cancel = {
  52890. callback: null
  52891. };
  52892. let insertionCallback = (e) => {
  52893. if(e.button === MOUSE.LEFT){
  52894. polyClipVol.addMarker();
  52895. // SVC Screen Line
  52896. svg.find("polyline").each((index, target) => {
  52897. let newPoint = svg[0].createSVGPoint();
  52898. newPoint.x = e.offsetX;
  52899. newPoint.y = e.offsetY;
  52900. let polyline = target.points.appendItem(newPoint);
  52901. });
  52902. if(polyClipVol.markers.length > this.maxPolygonVertices){
  52903. cancel.callback();
  52904. }
  52905. this.viewer.inputHandler.startDragging(
  52906. polyClipVol.markers[polyClipVol.markers.length - 1]);
  52907. }else if(e.button === MOUSE.RIGHT){
  52908. cancel.callback(e);
  52909. }
  52910. };
  52911. cancel.callback = e => {
  52912. //let first = svg.find("polyline")[0].points[0];
  52913. //svg.find("polyline").each((index, target) => {
  52914. // let newPoint = svg[0].createSVGPoint();
  52915. // newPoint.x = first.x;
  52916. // newPoint.y = first.y;
  52917. // let polyline = target.points.appendItem(newPoint);
  52918. //});
  52919. svg.remove();
  52920. if(polyClipVol.markers.length > 3) {
  52921. polyClipVol.removeLastMarker();
  52922. polyClipVol.initialized = true;
  52923. } else {
  52924. this.viewer.scene.removePolygonClipVolume(polyClipVol);
  52925. }
  52926. this.viewer.renderer.domElement.removeEventListener("mouseup", insertionCallback, true);
  52927. this.viewer.removeEventListener("cancel_insertions", cancel.callback);
  52928. this.viewer.inputHandler.enabled = true;
  52929. };
  52930. this.viewer.addEventListener("cancel_insertions", cancel.callback);
  52931. this.viewer.renderer.domElement.addEventListener("mouseup", insertionCallback , true);
  52932. this.viewer.inputHandler.enabled = false;
  52933. polyClipVol.addMarker();
  52934. this.viewer.inputHandler.startDragging(
  52935. polyClipVol.markers[polyClipVol.markers.length - 1]);
  52936. return polyClipVol;
  52937. }
  52938. update() {
  52939. }
  52940. };
  52941. var GeoTIFF = (function (exports) {
  52942. 'use strict';
  52943. const Endianness = new Enum({
  52944. LITTLE: "II",
  52945. BIG: "MM",
  52946. });
  52947. const Type = new Enum({
  52948. BYTE: {value: 1, bytes: 1},
  52949. ASCII: {value: 2, bytes: 1},
  52950. SHORT: {value: 3, bytes: 2},
  52951. LONG: {value: 4, bytes: 4},
  52952. RATIONAL: {value: 5, bytes: 8},
  52953. SBYTE: {value: 6, bytes: 1},
  52954. UNDEFINED: {value: 7, bytes: 1},
  52955. SSHORT: {value: 8, bytes: 2},
  52956. SLONG: {value: 9, bytes: 4},
  52957. SRATIONAL: {value: 10, bytes: 8},
  52958. FLOAT: {value: 11, bytes: 4},
  52959. DOUBLE: {value: 12, bytes: 8},
  52960. });
  52961. const Tag = new Enum({
  52962. IMAGE_WIDTH: 256,
  52963. IMAGE_HEIGHT: 257,
  52964. BITS_PER_SAMPLE: 258,
  52965. COMPRESSION: 259,
  52966. PHOTOMETRIC_INTERPRETATION: 262,
  52967. STRIP_OFFSETS: 273,
  52968. ORIENTATION: 274,
  52969. SAMPLES_PER_PIXEL: 277,
  52970. ROWS_PER_STRIP: 278,
  52971. STRIP_BYTE_COUNTS: 279,
  52972. X_RESOLUTION: 282,
  52973. Y_RESOLUTION: 283,
  52974. PLANAR_CONFIGURATION: 284,
  52975. RESOLUTION_UNIT: 296,
  52976. SOFTWARE: 305,
  52977. COLOR_MAP: 320,
  52978. SAMPLE_FORMAT: 339,
  52979. MODEL_PIXEL_SCALE: 33550, // [GeoTIFF] TYPE: double N: 3
  52980. MODEL_TIEPOINT: 33922, // [GeoTIFF] TYPE: double N: 6 * NUM_TIEPOINTS
  52981. GEO_KEY_DIRECTORY: 34735, // [GeoTIFF] TYPE: short N: >= 4
  52982. GEO_DOUBLE_PARAMS: 34736, // [GeoTIFF] TYPE: short N: variable
  52983. GEO_ASCII_PARAMS: 34737, // [GeoTIFF] TYPE: ascii N: variable
  52984. });
  52985. const typeMapping = new Map([
  52986. [Type.BYTE, Uint8Array],
  52987. [Type.ASCII, Uint8Array],
  52988. [Type.SHORT, Uint16Array],
  52989. [Type.LONG, Uint32Array],
  52990. [Type.RATIONAL, Uint32Array],
  52991. [Type.SBYTE, Int8Array],
  52992. [Type.UNDEFINED, Uint8Array],
  52993. [Type.SSHORT, Int16Array],
  52994. [Type.SLONG, Int32Array],
  52995. [Type.SRATIONAL, Int32Array],
  52996. [Type.FLOAT, Float32Array],
  52997. [Type.DOUBLE, Float64Array],
  52998. ]);
  52999. class IFDEntry{
  53000. constructor(tag, type, count, offset, value){
  53001. this.tag = tag;
  53002. this.type = type;
  53003. this.count = count;
  53004. this.offset = offset;
  53005. this.value = value;
  53006. }
  53007. }
  53008. class Image{
  53009. constructor(){
  53010. this.width = 0;
  53011. this.height = 0;
  53012. this.buffer = null;
  53013. this.metadata = [];
  53014. }
  53015. }
  53016. class Reader{
  53017. constructor(){
  53018. }
  53019. static read(data){
  53020. let endiannessTag = String.fromCharCode(...Array.from(data.slice(0, 2)));
  53021. let endianness = Endianness.fromValue(endiannessTag);
  53022. let tiffCheckTag = data.readUInt8(2);
  53023. if(tiffCheckTag !== 42){
  53024. throw new Error("not a valid tiff file");
  53025. }
  53026. let offsetToFirstIFD = data.readUInt32LE(4);
  53027. console.log("offsetToFirstIFD", offsetToFirstIFD);
  53028. let ifds = [];
  53029. let IFDsRead = false;
  53030. let currentIFDOffset = offsetToFirstIFD;
  53031. let i = 0;
  53032. while(IFDsRead || i < 100){
  53033. console.log("currentIFDOffset", currentIFDOffset);
  53034. let numEntries = data.readUInt16LE(currentIFDOffset);
  53035. let nextIFDOffset = data.readUInt32LE(currentIFDOffset + 2 + numEntries * 12);
  53036. console.log("next offset: ", currentIFDOffset + 2 + numEntries * 12);
  53037. let entryBuffer = data.slice(currentIFDOffset + 2, currentIFDOffset + 2 + 12 * numEntries);
  53038. for(let i = 0; i < numEntries; i++){
  53039. let tag = Tag.fromValue(entryBuffer.readUInt16LE(i * 12));
  53040. let type = Type.fromValue(entryBuffer.readUInt16LE(i * 12 + 2));
  53041. let count = entryBuffer.readUInt32LE(i * 12 + 4);
  53042. let offsetOrValue = entryBuffer.readUInt32LE(i * 12 + 8);
  53043. let valueBytes = type.bytes * count;
  53044. let value;
  53045. if(valueBytes <= 4){
  53046. value = offsetOrValue;
  53047. }else {
  53048. let valueBuffer = new Uint8Array(valueBytes);
  53049. valueBuffer.set(data.slice(offsetOrValue, offsetOrValue + valueBytes));
  53050. let ArrayType = typeMapping.get(type);
  53051. value = new ArrayType(valueBuffer.buffer);
  53052. if(type === Type.ASCII){
  53053. value = String.fromCharCode(...value);
  53054. }
  53055. }
  53056. let ifd = new IFDEntry(tag, type, count, offsetOrValue, value);
  53057. ifds.push(ifd);
  53058. }
  53059. console.log("nextIFDOffset", nextIFDOffset);
  53060. if(nextIFDOffset === 0){
  53061. break;
  53062. }
  53063. currentIFDOffset = nextIFDOffset;
  53064. i++;
  53065. }
  53066. let ifdForTag = (tag) => {
  53067. for(let entry of ifds){
  53068. if(entry.tag === tag){
  53069. return entry;
  53070. }
  53071. }
  53072. return null;
  53073. };
  53074. let width = ifdForTag(Tag.IMAGE_WIDTH, ifds).value;
  53075. let height = ifdForTag(Tag.IMAGE_HEIGHT, ifds).value;
  53076. let compression = ifdForTag(Tag.COMPRESSION, ifds).value;
  53077. let rowsPerStrip = ifdForTag(Tag.ROWS_PER_STRIP, ifds).value;
  53078. let ifdStripOffsets = ifdForTag(Tag.STRIP_OFFSETS, ifds);
  53079. let ifdStripByteCounts = ifdForTag(Tag.STRIP_BYTE_COUNTS, ifds);
  53080. let numStrips = Math.ceil(height / rowsPerStrip);
  53081. let stripByteCounts = [];
  53082. for(let i = 0; i < ifdStripByteCounts.count; i++){
  53083. let type = ifdStripByteCounts.type;
  53084. let offset = ifdStripByteCounts.offset + i * type.bytes;
  53085. let value;
  53086. if(type === Type.SHORT){
  53087. value = data.readUInt16LE(offset);
  53088. }else if(type === Type.LONG){
  53089. value = data.readUInt32LE(offset);
  53090. }
  53091. stripByteCounts.push(value);
  53092. }
  53093. let stripOffsets = [];
  53094. for(let i = 0; i < ifdStripOffsets.count; i++){
  53095. let type = ifdStripOffsets.type;
  53096. let offset = ifdStripOffsets.offset + i * type.bytes;
  53097. let value;
  53098. if(type === Type.SHORT){
  53099. value = data.readUInt16LE(offset);
  53100. }else if(type === Type.LONG){
  53101. value = data.readUInt32LE(offset);
  53102. }
  53103. stripOffsets.push(value);
  53104. }
  53105. let imageBuffer = new Uint8Array(width * height * 3);
  53106. let linesProcessed = 0;
  53107. for(let i = 0; i < numStrips; i++){
  53108. let stripOffset = stripOffsets[i];
  53109. let stripBytes = stripByteCounts[i];
  53110. let stripData = data.slice(stripOffset, stripOffset + stripBytes);
  53111. let lineBytes = width * 3;
  53112. for(let y = 0; y < rowsPerStrip; y++){
  53113. let line = stripData.slice(y * lineBytes, y * lineBytes + lineBytes);
  53114. imageBuffer.set(line, linesProcessed * lineBytes);
  53115. if(line.length === lineBytes){
  53116. linesProcessed++;
  53117. }else {
  53118. break;
  53119. }
  53120. }
  53121. }
  53122. console.log(`width: ${width}`);
  53123. console.log(`height: ${height}`);
  53124. console.log(`numStrips: ${numStrips}`);
  53125. console.log("stripByteCounts", stripByteCounts.join(", "));
  53126. console.log("stripOffsets", stripOffsets.join(", "));
  53127. let image = new Image();
  53128. image.width = width;
  53129. image.height = height;
  53130. image.buffer = imageBuffer;
  53131. image.metadata = ifds;
  53132. return image;
  53133. }
  53134. }
  53135. class Exporter{
  53136. constructor(){
  53137. }
  53138. static toTiffBuffer(image, params = {}){
  53139. let offsetToFirstIFD = 8;
  53140. let headerBuffer = new Uint8Array([0x49, 0x49, 42, 0, offsetToFirstIFD, 0, 0, 0]);
  53141. let [width, height] = [image.width, image.height];
  53142. let ifds = [
  53143. new IFDEntry(Tag.IMAGE_WIDTH, Type.SHORT, 1, null, width),
  53144. new IFDEntry(Tag.IMAGE_HEIGHT, Type.SHORT, 1, null, height),
  53145. new IFDEntry(Tag.BITS_PER_SAMPLE, Type.SHORT, 4, null, new Uint16Array([8, 8, 8, 8])),
  53146. new IFDEntry(Tag.COMPRESSION, Type.SHORT, 1, null, 1),
  53147. new IFDEntry(Tag.PHOTOMETRIC_INTERPRETATION, Type.SHORT, 1, null, 2),
  53148. new IFDEntry(Tag.ORIENTATION, Type.SHORT, 1, null, 1),
  53149. new IFDEntry(Tag.SAMPLES_PER_PIXEL, Type.SHORT, 1, null, 4),
  53150. new IFDEntry(Tag.ROWS_PER_STRIP, Type.LONG, 1, null, height),
  53151. new IFDEntry(Tag.STRIP_BYTE_COUNTS, Type.LONG, 1, null, width * height * 3),
  53152. new IFDEntry(Tag.PLANAR_CONFIGURATION, Type.SHORT, 1, null, 1),
  53153. new IFDEntry(Tag.RESOLUTION_UNIT, Type.SHORT, 1, null, 1),
  53154. new IFDEntry(Tag.SOFTWARE, Type.ASCII, 6, null, "......"),
  53155. new IFDEntry(Tag.STRIP_OFFSETS, Type.LONG, 1, null, null),
  53156. new IFDEntry(Tag.X_RESOLUTION, Type.RATIONAL, 1, null, new Uint32Array([1, 1])),
  53157. new IFDEntry(Tag.Y_RESOLUTION, Type.RATIONAL, 1, null, new Uint32Array([1, 1])),
  53158. ];
  53159. if(params.ifdEntries){
  53160. ifds.push(...params.ifdEntries);
  53161. }
  53162. let valueOffset = offsetToFirstIFD + 2 + ifds.length * 12 + 4;
  53163. // create 12 byte buffer for each ifd and variable length buffers for ifd values
  53164. let ifdEntryBuffers = new Map();
  53165. let ifdValueBuffers = new Map();
  53166. for(let ifd of ifds){
  53167. let entryBuffer = new ArrayBuffer(12);
  53168. let entryView = new DataView(entryBuffer);
  53169. let valueBytes = ifd.type.bytes * ifd.count;
  53170. entryView.setUint16(0, ifd.tag.value, true);
  53171. entryView.setUint16(2, ifd.type.value, true);
  53172. entryView.setUint32(4, ifd.count, true);
  53173. if(ifd.count === 1 && ifd.type.bytes <= 4){
  53174. entryView.setUint32(8, ifd.value, true);
  53175. }else {
  53176. entryView.setUint32(8, valueOffset, true);
  53177. let valueBuffer = new Uint8Array(ifd.count * ifd.type.bytes);
  53178. if(ifd.type === Type.ASCII){
  53179. valueBuffer.set(new Uint8Array(ifd.value.split("").map(c => c.charCodeAt(0))));
  53180. }else {
  53181. valueBuffer.set(new Uint8Array(ifd.value.buffer));
  53182. }
  53183. ifdValueBuffers.set(ifd.tag, valueBuffer);
  53184. valueOffset = valueOffset + valueBuffer.byteLength;
  53185. }
  53186. ifdEntryBuffers.set(ifd.tag, entryBuffer);
  53187. }
  53188. let imageBufferOffset = valueOffset;
  53189. new DataView(ifdEntryBuffers.get(Tag.STRIP_OFFSETS)).setUint32(8, imageBufferOffset, true);
  53190. let concatBuffers = (buffers) => {
  53191. let totalLength = buffers.reduce( (sum, buffer) => (sum + buffer.byteLength), 0);
  53192. let merged = new Uint8Array(totalLength);
  53193. let offset = 0;
  53194. for(let buffer of buffers){
  53195. merged.set(new Uint8Array(buffer), offset);
  53196. offset += buffer.byteLength;
  53197. }
  53198. return merged;
  53199. };
  53200. let ifdBuffer = concatBuffers([
  53201. new Uint16Array([ifds.length]),
  53202. ...ifdEntryBuffers.values(),
  53203. new Uint32Array([0])]);
  53204. let ifdValueBuffer = concatBuffers([...ifdValueBuffers.values()]);
  53205. let tiffBuffer = concatBuffers([
  53206. headerBuffer,
  53207. ifdBuffer,
  53208. ifdValueBuffer,
  53209. image.buffer
  53210. ]);
  53211. return {width: width, height: height, buffer: tiffBuffer};
  53212. }
  53213. }
  53214. exports.Tag = Tag;
  53215. exports.Type = Type;
  53216. exports.IFDEntry = IFDEntry;
  53217. exports.Image = Image;
  53218. exports.Reader = Reader;
  53219. exports.Exporter = Exporter;
  53220. return exports;
  53221. }({}));
  53222. class Message{
  53223. constructor(content){
  53224. this.content = content;
  53225. let closeIcon = `${exports.resourcePath}/icons/close.svg`;
  53226. this.element = $(`
  53227. <div class="potree_message">
  53228. <span name="content_container" style="flex-grow: 1; padding: 5px"></span>
  53229. <img name="close" src="${closeIcon}" class="button-icon" style="width: 16px; height: 16px;">
  53230. </div>`);
  53231. this.elClose = this.element.find("img[name=close]");
  53232. this.elContainer = this.element.find("span[name=content_container]");
  53233. if(typeof content === "string"){
  53234. this.elContainer.append($(`<span>${content}</span>`));
  53235. }else {
  53236. this.elContainer.append(content);
  53237. }
  53238. }
  53239. setMessage(content){
  53240. this.elContainer.empty();
  53241. if(typeof content === "string"){
  53242. this.elContainer.append($(`<span>${content}</span>`));
  53243. }else {
  53244. this.elContainer.append(content);
  53245. }
  53246. }
  53247. }
  53248. class PointCloudSM{
  53249. constructor(potreeRenderer){
  53250. this.potreeRenderer = potreeRenderer;
  53251. this.threeRenderer = this.potreeRenderer.threeRenderer;
  53252. this.target = new WebGLRenderTarget(2 * 1024, 2 * 1024, {
  53253. minFilter: LinearFilter,
  53254. magFilter: LinearFilter,
  53255. format: RGBAFormat,
  53256. type: FloatType
  53257. });
  53258. this.target.depthTexture = new DepthTexture();
  53259. this.target.depthTexture.type = UnsignedIntType;
  53260. //this.threeRenderer.setClearColor(0x000000, 1);
  53261. this.threeRenderer.setClearColor(0xff0000, 1);
  53262. //HACK? removed while moving to three.js 109
  53263. //this.threeRenderer.clearTarget(this.target, true, true, true);
  53264. {
  53265. const oldTarget = this.threeRenderer.getRenderTarget();
  53266. this.threeRenderer.setRenderTarget(this.target);
  53267. this.threeRenderer.clear(true, true, true);
  53268. this.threeRenderer.setRenderTarget(oldTarget);
  53269. }
  53270. }
  53271. setLight(light){
  53272. this.light = light;
  53273. let fov = (180 * light.angle) / Math.PI;
  53274. let aspect = light.shadow.mapSize.width / light.shadow.mapSize.height;
  53275. let near = 0.1;
  53276. let far = light.distance === 0 ? 10000 : light.distance;
  53277. this.camera = new PerspectiveCamera(fov, aspect, near, far);
  53278. this.camera.up.set(0, 0, 1);
  53279. this.camera.position.copy(light.position);
  53280. let target = new Vector3().subVectors(light.position, light.getWorldDirection(new Vector3()));
  53281. this.camera.lookAt(target);
  53282. this.camera.updateProjectionMatrix();
  53283. this.camera.updateMatrix();
  53284. this.camera.updateMatrixWorld();
  53285. this.camera.matrixWorldInverse.copy(this.camera.matrixWorld).invert();
  53286. }
  53287. setSize(width, height){
  53288. if(this.target.width !== width || this.target.height !== height){
  53289. this.target.dispose();
  53290. }
  53291. this.target.setSize(width, height);
  53292. }
  53293. render(scene, camera){
  53294. this.threeRenderer.setClearColor(0x000000, 1);
  53295. const oldTarget = this.threeRenderer.getRenderTarget();
  53296. this.threeRenderer.setRenderTarget(this.target);
  53297. this.threeRenderer.clear(true, true, true);
  53298. this.potreeRenderer.render(scene, this.camera, this.target, {});
  53299. this.threeRenderer.setRenderTarget(oldTarget);
  53300. }
  53301. }
  53302. class Label extends EventDispatcher{
  53303. constructor(o={}){
  53304. super();
  53305. this.position = o.pos;
  53306. this.text = o.text || '';
  53307. this.elem = $('<div class="hide"><a></a></div>');
  53308. o.className && this.elem.addClass(o.className);
  53309. this.elem.find('a').html(this.text);
  53310. $("#potree_labels").append(this.elem);
  53311. this.pos2d = new Vector3;
  53312. this.dom = o.dom || viewer.renderArea;
  53313. this.camera = o.camera || viewer.scene.getActiveCamera();
  53314. let update = (e)=>{
  53315. this.update(e);
  53316. };
  53317. viewer.addEventListener('camera_changed', update);
  53318. this.addEventListener('dispose', ()=>{
  53319. viewer.removeEventListener('camera_changed', update);
  53320. this.dispose();
  53321. });
  53322. }
  53323. update(){
  53324. if(!this.position || this.elem.hasClass('unvisible'))return
  53325. var p = Utils.getPos2d(this.position,this.camera,this.dom, viewer.mainViewport);
  53326. if(!p.trueSide){
  53327. this.elem.addClass("hide"); return;
  53328. }
  53329. this.elem.css({
  53330. left: p.pos.x +'px',
  53331. top: p.pos.y +'px'
  53332. });
  53333. this.elem.removeClass("hide");
  53334. this.pos2d = p.vector;
  53335. }
  53336. setVisible(visi){
  53337. if(!visi){
  53338. this.elem.addClass("unvisible");
  53339. }else {
  53340. this.elem.removeClass("unvisible");
  53341. this.update();
  53342. }
  53343. }
  53344. setText(text){
  53345. this.text = text || '';
  53346. this.elem.find('a').html(this.text);
  53347. }
  53348. setPos(pos){
  53349. this.position = pos;
  53350. }
  53351. dispose(){
  53352. this.elem.remove();
  53353. this.removeAllListeners();
  53354. }
  53355. }
  53356. const verticalLine = new Line3();
  53357. //控制点和边的合集。具有可以拖拽修改的功能,拖拽时能防止线相交。
  53358. class ctrlPolygon extends Object3D {
  53359. constructor (type, prop) {
  53360. super();
  53361. this.type = type;
  53362. this.maxMarkers = Number.MAX_SAFE_INTEGER;
  53363. this.transformData(prop);
  53364. for(let i in prop){
  53365. this[i] = prop[i];
  53366. }
  53367. if(this.atPlane && this.closed && this.dimension == '2d'){
  53368. this.areaPlane = this.createAreaPlane();
  53369. this.add(this.areaPlane);
  53370. }
  53371. //数据--刚开始一定是空的
  53372. this.points = [];
  53373. //mesh 不一定有
  53374. this.markers = [];
  53375. this.edges = [];
  53376. this.center;
  53377. }
  53378. initData(prop){
  53379. //开始加数据
  53380. if(Potree.settings.editType == 'merge'){ //融合页面没有地图,measure的不需要指定datasetId,每个点都有各自的datasetId,跟着各自的模型走
  53381. if(this.dataset_points){
  53382. this.dataset_points = this.dataset_points.map(e=>{
  53383. return e && new Vector3().copy(e)
  53384. });
  53385. prop.points = this.dataset_points.map((p,i)=>{
  53386. return Potree.Utils.datasetPosTransform({fromDataset:true, datasetId:this.points_datasets[i], position: p})
  53387. });
  53388. if(prop.points.some(e=>e == void 0)){
  53389. return false
  53390. }
  53391. }else {
  53392. this.dataset_points = [];
  53393. }
  53394. }
  53395. if(prop.points){
  53396. for(const p of prop.points){
  53397. const pos = new Vector3().copy(p);
  53398. this.addMarker({point:pos});
  53399. }
  53400. /* if(Potree.settings.editType != 'merge'){
  53401. if(this.datasetId != void 0){//初始化位置
  53402. if(this.dataset_points){
  53403. this.dataset_points = this.dataset_points.map(e=>{
  53404. return e && new THREE.Vector3().copy(e)
  53405. })
  53406. this.transformByPointcloud() //根据dataset_points生成points
  53407. }
  53408. }else{
  53409. if(prop.dataset_points && prop.dataset_points.some(e=>e != void 0)){
  53410. console.error('存在测量线的datasetId为空而dataset_points有值,请检查并删除:'+this.sid)//存在过的bug,原因未知,可能是后台处理dataset时替换的错误:http://192.168.0.21/index.php?m=bug&f=view&bugID=23601
  53411. console.log(this)
  53412. }
  53413. }
  53414. } */
  53415. this.getFacePlane();
  53416. this.getPoint2dInfo(this.points);
  53417. this.update({ifUpdateMarkers:true});
  53418. //this.dragChange(new THREE.Vector3().copy(prop.points[prop.points.length-1]), prop.points.length-1);
  53419. this.setSelected(false );
  53420. this.markers.forEach(marker=>{marker.dispatchEvent('addHoverEvent'); });
  53421. return true
  53422. }
  53423. }
  53424. addMarker(o={}){
  53425. var index = o.index == void 0 ? this.points.length : o.index; //要当第几个
  53426. this.points = [...this.points.slice(0,index), o.point, ...this.points.slice(index,this.points.length)];
  53427. //this.points.push(o.point);
  53428. if(o.marker){
  53429. this.add(o.marker);
  53430. this.markers = [...this.markers.slice(0,index), o.marker, ...this.markers.slice(index,this.markers.length)];
  53431. this.updateMarker(o.marker, o.point);
  53432. o.marker.addEventListener('drag', this.dragMarker.bind(this));
  53433. o.marker.addEventListener('drop', this.dropMarker.bind(this));
  53434. let addHoverEvent = (e)=>{
  53435. let mouseover = (e) => {
  53436. this.setMarkerSelected(e.object, 'hover', 'single');
  53437. viewer.dispatchEvent({
  53438. type : "CursorChange", action : "add", name:"markerMove"
  53439. });
  53440. };
  53441. let mouseleave = (e) => {
  53442. this.setMarkerSelected(e.object, 'unhover', 'single');
  53443. viewer.dispatchEvent({
  53444. type : "CursorChange", action : "remove", name:"markerMove"
  53445. });
  53446. };
  53447. o.marker.addEventListener('mouseover', mouseover);
  53448. o.marker.addEventListener('mouseleave', mouseleave);
  53449. o.marker.addEventListener('startDragging', (e)=>{//for mobile
  53450. this.setMarkerSelected(o.marker, 'hover', 'single');
  53451. });
  53452. o.marker.addEventListener('drop', (e)=>{//for mobile
  53453. this.setMarkerSelected(o.marker, 'unhover', 'single');
  53454. });
  53455. o.marker.removeEventListener('addHoverEvent',addHoverEvent);
  53456. };
  53457. o.marker.addEventListener('addHoverEvent',addHoverEvent);//当非isNew时才添加事件
  53458. if(!this.isNew){
  53459. o.marker.dispatchEvent('addHoverEvent');
  53460. }
  53461. }
  53462. if(o.edge){
  53463. this.add(o.edge);
  53464. this.edges = [...this.edges.slice(0,index), o.edge, ...this.edges.slice(index,this.edges.length)];
  53465. }
  53466. }
  53467. dragMarker(e){
  53468. var I, atMap;
  53469. if(e.hoverViewport != e.drag.dragViewport){//不能使用e.dragViewport,要使用drag中的,因为drag中存储的要一直继承下来,不因mouseup了而改变。
  53470. viewer.dispatchEvent({
  53471. type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
  53472. });
  53473. return
  53474. }
  53475. viewer.dispatchEvent({
  53476. type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
  53477. });
  53478. atMap = e.drag.dragViewport.name == 'mapViewport';
  53479. if(atMap && this.unableDragAtMap){
  53480. e.drag.object = null; //取消拖拽
  53481. return
  53482. }
  53483. e.drag.object.isDragging = true;
  53484. I = e.intersect && (/* e.intersect.orthoIntersect || */ e.intersect.location);
  53485. //记录数据集
  53486. //在三维中脱离点云(在map中拉到周围都没有点云的地方)的顶点,无法拖拽怎么办
  53487. if (I) {
  53488. let i = this.markers.indexOf(e.drag.object);
  53489. if (i !== -1) {
  53490. this.dragChange(I.clone(), i, atMap);
  53491. if(this.points_datasets){
  53492. if(e.intersect.pointcloud) this.points_datasets[i] = e.intersect.pointcloud.dataset_id;
  53493. else if(e.intersect.object) this.points_datasets[i] = e.intersect.object.dataset_id;
  53494. else this.points_datasets[i] = null;
  53495. }
  53496. }
  53497. this.editStateChange(true);
  53498. viewer.dispatchEvent({type:'dragMarker', object:this});
  53499. return true
  53500. }
  53501. };
  53502. dragChange(intersectPos, i, atMap){
  53503. let len = this.markers.length;
  53504. let oldPoint = this.points[i];
  53505. if(atMap){
  53506. intersectPos.setZ(oldPoint.z); //在地图上拖拽,不改变其高度。
  53507. }
  53508. let location = intersectPos.clone();
  53509. //console.log('dragMarker', oldPoint, intersectPos)
  53510. if(this.faceDirection && this.maxMarkers == 2 && len == 2){//add 固定方向的点不直接拖拽
  53511. var p1 = this.markers[0].position;
  53512. if(this.faceDirection == 'horizontal'){
  53513. var projectPos = location.clone().setZ(p1.z);
  53514. }else {
  53515. var projectPos = p1.clone().setZ(location.z);
  53516. }
  53517. //var p2 = p1.clone().add(this.direction)
  53518. //var projectPos = math.getFootPoint(location, p1, p2)
  53519. LineDraw.updateLine(this.guideLine, [location, projectPos]);
  53520. location = projectPos;
  53521. this.guideLine.visible = true;
  53522. }else if( len > 1 ){
  53523. var points = this.points.map(e=>e.clone());
  53524. points[i].copy(location); //算normal需要提前确认point
  53525. //若为定义了面朝向的矩形
  53526. if(this.faceDirection == 'horizontal'){
  53527. if(len == 2){
  53528. location.setZ(points[0].z);
  53529. }
  53530. if(!this.facePlane){//一个点就能确定面
  53531. this.facePlane = new Plane().setFromNormalAndCoplanarPoint( new Vector3(0,0,1), this.points[0] );
  53532. }
  53533. }else if(this.faceDirection == 'vertical'){//当有两个点时, 有两个方向的可能
  53534. if(len == 2){
  53535. if(this.isRect){
  53536. let vec = points[0].clone().sub(location);
  53537. if(Math.sqrt(vec.x*vec.x+vec.y*vec.y) > Math.abs(vec.z) ){//水平(高度差小于水平距离时)
  53538. location.setZ(points[0].z);
  53539. //this.cannotConfirmNormal = false;//能确定面为水平方向
  53540. }else {//垂直 (当两点一样时也属于这种)
  53541. location.setX(points[0].x);
  53542. location.setY(points[0].y);
  53543. //this.cannotConfirmNormal = true; //不能确定面,因第三点可绕着纵轴线自由移动
  53544. }
  53545. }
  53546. }else {
  53547. {//判断cannotConfirmNormal. 如果前几段都在竖直线上,就不能固定出面方向。
  53548. this.cannotConfirmNormal = true;
  53549. let max = this.isRect ? 1 : len-2;
  53550. for(let i=0;i<max;i++){
  53551. let p1 = points[i].clone();
  53552. let p2 = points[i+1].clone();
  53553. let vec = p1.sub(p2);
  53554. if(vec.x != 0 || vec.y != 0){
  53555. this.cannotConfirmNormal = false;
  53556. break;
  53557. }
  53558. }
  53559. }
  53560. if(!this.facePlane || this.cannotConfirmNormal){//三个点且为水平方向时,计算面
  53561. var points_ = points.map(e=>new Vector2(e.x,e.y));
  53562. var points2 = getDifferentPoint(points_, 2);
  53563. if(points2){
  53564. let normal = math.getNormal2d({p1:points2[0], p2:points2[1]});
  53565. normal = new Vector3(normal.x, normal.y, 0);
  53566. this.facePlane = new Plane().setFromNormalAndCoplanarPoint( normal, this.points[0] );
  53567. }
  53568. }
  53569. }
  53570. }
  53571. if(len > 2){
  53572. if(!this.faceDirection && this.showArea){
  53573. if(len == 3 || this.isRect) this.cannotConfirmNormal = true; //当第三个点固定后(有四个点时)才能固定面
  53574. if(!this.facePlane || this.cannotConfirmNormal){
  53575. var points3 = getDifferentPoint(points, 3);//只有找到三个不同的点算拥有面和area
  53576. if(points3){
  53577. this.facePlane = new Plane().setFromCoplanarPoints(...points3 );
  53578. }
  53579. }
  53580. }
  53581. if( this.facePlane && !this.cannotConfirmNormal ){//之后加的点一定要在面上
  53582. if(atMap){
  53583. //地图上用垂直线,得到和面的交点。
  53584. verticalLine.set(location.clone().setZ(100000), location.clone().setZ(-100000));//确保长度范围覆盖所有测量面
  53585. location = this.facePlane.intersectLine(verticalLine, new Vector3() );
  53586. if(!location) return;
  53587. }else {
  53588. location = this.facePlane.projectPoint(intersectPos, new Vector3() );
  53589. }
  53590. }
  53591. points[i].copy(location);//再copy确认一次
  53592. if(this.isRect){ //是矩形 (即使没有faceDirection也能执行)
  53593. //根据前两个点计算当前和下一个点
  53594. var p1 = points[(i-2+len)%len];
  53595. var p2 = points[(i-1+len)%len];
  53596. if(p1.equals(p2)){//意外情况:重复点两次 ( bug点,改了好多遍)
  53597. if(this.faceDirection == 'vertical'){
  53598. p2.add(new Vector3(0,0,0.0001));
  53599. }else {
  53600. p2.add(new Vector3(0,0.0001,0));
  53601. }
  53602. }
  53603. //p3 : location
  53604. var foot = math.getFootPoint(location, p1, p2);//p2 修改p2到垂足的位置
  53605. var vec = foot.clone().sub(location);
  53606. var p4 = p1.clone().sub(vec);
  53607. points[(i-1+len)%len].copy(foot);
  53608. points[(i+1)%len].copy(p4);
  53609. this.setPosition((i-1+len)%len, foot);//p2
  53610. this.setPosition((i+1)%len, p4);
  53611. }
  53612. /* let points2d;
  53613. if(this.facePlane){
  53614. var originPoint0 = points[0].clone()
  53615. var qua = math.getQuaBetween2Vector(this.facePlane.normal, new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,1));
  53616. points2d = points.map(e=>e.clone().applyQuaternion(qua))
  53617. } */
  53618. this.getPoint2dInfo(points);
  53619. var isIntersectSelf = this.atPlane && this.closed && !this.isRect && this.point2dInfo && this.intersectSelf(this.point2dInfo.points2d);//检测相交
  53620. this.isIntersectSelf = isIntersectSelf;
  53621. if(isIntersectSelf){//not-allowed
  53622. if(!this.isNew && isIntersectSelf == 'lastLine') this.isIntersectSelf = 'all'; //已经画好了就不用特别对待最后一条线
  53623. if(this.isIntersectSelf == 'lastLine'){
  53624. Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', false);
  53625. Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', false);
  53626. }else {
  53627. viewer.dispatchEvent({
  53628. type : "CursorChange", action : "add", name:"polygon_isIntersectSelf"
  53629. });
  53630. return
  53631. }
  53632. }
  53633. if(!this.isIntersectSelf){
  53634. this.areaPlane && Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', true);
  53635. this.areaLabel && Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', true);
  53636. }
  53637. if(!this.isIntersectSelf || this.isIntersectSelf == 'lastLine' ){
  53638. viewer.dispatchEvent({
  53639. type : "CursorChange", action : "remove", name:"polygon_isIntersectSelf"
  53640. });
  53641. }
  53642. }
  53643. var showGuideLine = len>1 && (this.faceDirection || len > 3);
  53644. if(showGuideLine && this.guideLine){
  53645. LineDraw.updateLine(this.guideLine, [intersectPos, location]);
  53646. this.guideLine.visible = true;
  53647. }
  53648. //console.log(this.points.map(e=>e.toArray()))
  53649. }
  53650. if(this.restrictArea){
  53651. let holes = this.restrictArea.holes.concat(this.restrictArea.parentHoles);
  53652. let holesPoints = holes.filter(e=>e!=this && e.points.length>2).map(e=>e.points);
  53653. if(!math.isPointInArea(this.restrictArea.points, holesPoints, location)){
  53654. viewer.dispatchEvent({
  53655. type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
  53656. });
  53657. this.isAtWrongPlace = true;
  53658. return
  53659. }
  53660. //就不处理相交线了。 有个缺点:floor上的hole可以限制room,但hole不受room限制,会导致room的marker被框在hole里而动不了。只能去调整hole了
  53661. }
  53662. viewer.dispatchEvent({
  53663. type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
  53664. });
  53665. this.isAtWrongPlace = false;
  53666. this.setPosition(i, location);
  53667. this.update();
  53668. this.dispatchEvent({type:'dragChange', index:i});
  53669. }
  53670. dropMarker(e){
  53671. if (this.isNew && !browser.isMobile() && e.pressDistance>Potree.config.clickMaxDragDis){//拖拽的话返回
  53672. return this.continueDrag(null,e)
  53673. }
  53674. if(e.hoverViewport != e.drag.dragViewport){//copy from dragMarker, for sitemodel, only mapViewport can be dropped
  53675. return this.continueDrag(null,e)
  53676. }
  53677. if(e.isTouch){
  53678. if(e.hoverViewport != viewer.mainViewport && this.unableDragAtMap){
  53679. viewer.dispatchEvent({type:'reticule_forbit', v:true});
  53680. //console.log('reticule_forbit',true)
  53681. return this.continueDrag(null,e)
  53682. }else {
  53683. viewer.dispatchEvent({type:'reticule_forbit', v:false});
  53684. //console.log('reticule_forbit',false)
  53685. }
  53686. this.isNew && this.dragMarker(e); //isNew触屏点击时必须先更新下点,因为指尖不在屏幕上时没更新。但对已经创建的marker点击时不应该更新
  53687. }
  53688. viewer.dispatchEvent({type:'dropMarker', object:this});
  53689. if (e.button != MOUSE.RIGHT && (//右键click的话继续执行,因为会停止
  53690. this.isIntersectSelf == 'all' && this.isNew //有线相交了
  53691. || this.isAtWrongPlace && this.isNew
  53692. || !e.isAtDomElement && this.isNew//如果是刚添加时在其他dom点击, 不要响应
  53693. || e.hoverViewport != viewer.mainViewport && this.unableDragAtMap //垂直的测量线不允许在地图上放点
  53694. || this.isNew && !getDifferentPoint(this.points, this.points.length ) //不允许和之前的点相同, 但这句在点云稀疏时会导致难结束
  53695. || this.isNew && (Date.now() - this.beginAddTime) < Potree.config.clickMaxPressTime && e.pressDistance < Potree.config.clickMaxDragDis/* && e.pressTime<Potree.config.clickMaxPressTime */ //有的设备过于灵敏,点击一下就结束测量了,是因为滑动了被判断为拖拽。所以判断下如果滑动距离过近不时间过短就算单击
  53696. )
  53697. ){
  53698. return this.continueDrag(null,e)
  53699. }
  53700. let i = this.markers.indexOf(e.drag.object);
  53701. if (i !== -1) {
  53702. this.dispatchEvent({
  53703. 'type': 'marker_dropped',
  53704. 'index': i
  53705. });
  53706. if(this.markers.length>2 && this.facePlane)this.cannotConfirmNormal = false;
  53707. this.guideLine &&(this.guideLine.visible = false);
  53708. }
  53709. this.setMarkerSelected(e.drag.object, 'unhover', 'single');
  53710. this.editStateChange(false);
  53711. e.drag.endDragFun && e.drag.endDragFun(e);// addmarker
  53712. //if(this.changeCallBack)this.changeCallBack()
  53713. return true
  53714. };
  53715. getFacePlane(){//最普通一种get方法,根据顶点。且假设所有点已经共面,且不重合
  53716. if(!this.atPlane || this.points.length<3) return
  53717. this.facePlane = new Plane().setFromCoplanarPoints(...this.points.slice(0,3) );
  53718. }
  53719. getPoint2dInfo(points){ //在更新areaplane之前必须更新过point2dInfo
  53720. if(this.facePlane){
  53721. var originPoint0 = points[0].clone();
  53722. var qua = math.getQuaBetween2Vector(this.facePlane.normal, new Vector3(0,0,1), new Vector3(0,0,1));
  53723. let points2d = points.map(e=>e.clone().applyQuaternion(qua));
  53724. this.point2dInfo = {
  53725. originPoint0 ,
  53726. points2d,
  53727. quaInverse : qua.clone().invert()
  53728. };
  53729. }
  53730. }
  53731. setPosition (index, position) {//拖拽后设置位置
  53732. let point = this.points[index];
  53733. point.copy(position);
  53734. /* if(this.datasetId){
  53735. this.dataset_points[index] = Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.datasetId, position:point.clone()})
  53736. } */
  53737. /* if(Potree.settings.editType == 'merge'){
  53738. this.dataset_points[index] = Potree.Utils.datasetPosTransform({toDataset:true,this.points_datasets[i], position:point.clone()})
  53739. } */
  53740. let marker = this.markers[index];
  53741. this.updateMarker(marker, point);
  53742. }
  53743. updateMarker(marker, pos){
  53744. marker.position.copy(pos);
  53745. marker.update();
  53746. }
  53747. intersectSelf(points2d){//add
  53748. var len = points2d.length;
  53749. for(var i=0;i<len;i++){
  53750. for(var j=i+2;j<len;j++){
  53751. if(Math.abs(j-len-i)<2)continue;//不和邻边比
  53752. var p1 = points2d[i];
  53753. var p2 = points2d[i+1];
  53754. var p3 = points2d[j];
  53755. var p4 = points2d[(j+1)%len];
  53756. if(p1.equals(p2) || p3.equals(p4) || p1.equals(p3) || p2.equals(p3) || p1.equals(p4) || p2.equals(p4))continue
  53757. var line1 = [p1,p2];
  53758. var line2 = [p3,p4];
  53759. var intersect = math.isLineIntersect(line1, line2, false, 0.001);
  53760. if(intersect){
  53761. if(i==len-1 || j==len-1){//最后一条线。如果还没绘制完,最后的线还没定下,可被允许继续绘制,但无法显示面积。
  53762. return 'lastLine'
  53763. }else {
  53764. return 'all'
  53765. }
  53766. break
  53767. }
  53768. }
  53769. }
  53770. }
  53771. removeMarker (index) {
  53772. this.points.splice(index, 1);
  53773. const marker = this.markers[index];
  53774. //this.remove(marker);
  53775. this.markers.splice(index, 1);
  53776. marker.dispatchEvent({type:'dispose'});
  53777. let edgeIndex = index; //(index === 0) ? 0 : (index - 1);
  53778. const edge = this.edges[edgeIndex];
  53779. if(edge){
  53780. this.remove(edge);
  53781. this.edges.splice(edgeIndex, 1);
  53782. edge.dispatchEvent({type:'dispose'});
  53783. }
  53784. this.point2dInfo && this.point2dInfo.points2d.splice(index, 1); //add
  53785. this.dispatchEvent({type:'removeMarker',index,marker});
  53786. }
  53787. createAreaPlane(mat){
  53788. var geometry = new Geometry();
  53789. var mesh = new Mesh(geometry, mat);
  53790. return mesh
  53791. }
  53792. updateAreaPlane(){
  53793. if(!this.point2dInfo)return
  53794. this.areaPlane.geometry.dispose();
  53795. if(this.points.length>2){
  53796. this.areaPlane.geometry = MeshDraw.getShapeGeo(this.point2dInfo.points2d);
  53797. var center = math.getCenterOfGravityPoint(this.point2dInfo.points2d); //重心
  53798. var firstPos = this.point2dInfo.points2d[0].clone();
  53799. firstPos.z = 0; //因为shape只读取了xy,所以位移下, 再算出最终位置,得到差距
  53800. firstPos.applyQuaternion(this.point2dInfo.quaInverse);
  53801. var vec = this.point2dInfo.originPoint0.clone().sub(firstPos);
  53802. center = new Vector3(center.x, center.y, 0);
  53803. center.applyQuaternion(this.point2dInfo.quaInverse);
  53804. this.areaPlane.quaternion.copy(this.point2dInfo.quaInverse);
  53805. this.areaPlane.position.copy(vec);
  53806. center.add(vec);
  53807. this.center = center;
  53808. }else {
  53809. this.areaPlane.geometry = new Geometry();
  53810. }
  53811. }
  53812. update(options={}){
  53813. if(this.points.length === 0){
  53814. return;
  53815. }
  53816. let lastIndex = this.points.length - 1;
  53817. for (let index = 0; index <= lastIndex; index++) {
  53818. let nextIndex = (index + 1 > lastIndex) ? 0 : index + 1;
  53819. let previousIndex = (index === 0) ? lastIndex : index - 1;
  53820. let point = this.points[index];
  53821. let nextPoint = this.points[nextIndex];
  53822. let previousPoint = this.points[previousIndex];
  53823. if(options.ifUpdateMarkers){
  53824. this.updateMarker(this.markers[index], point);
  53825. }
  53826. if(!this.closed && nextIndex == 0 )break; //add
  53827. { // edges
  53828. let edge = this.edges[index];
  53829. if(edge){
  53830. LineDraw.updateLine(edge, [point, nextPoint]);
  53831. //edge.visible = index < lastIndex || this.isRect || (this.closed && !this.isNew);
  53832. }
  53833. }
  53834. }
  53835. if(this.areaPlane){
  53836. this.updateAreaPlane();
  53837. }
  53838. //this.dispatchEvent({type:'update'})
  53839. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed'); //暂时先这么都通知
  53840. }
  53841. dispose(){//add
  53842. this.parent.remove(this);
  53843. this.markers.concat(this.edges).forEach(e=>e.dispatchEvent({type:'dispose'}));
  53844. }
  53845. reDraw(restMarkerCount=0){//重新开始画
  53846. let pointCount = this.points.length - restMarkerCount; // restMarkerCount为需要留下的marker数量
  53847. while(pointCount > 0){
  53848. this.removeMarker(--pointCount);
  53849. }
  53850. this.point2dInfo = null;
  53851. this.facePlane = null;
  53852. }
  53853. setMarkerSelected(){}
  53854. editStateChange(state){
  53855. if(!state){
  53856. viewer.dispatchEvent({
  53857. type : "CursorChange", action : "remove", name:"polygon_isIntersectSelf"
  53858. });
  53859. viewer.dispatchEvent({
  53860. type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
  53861. });
  53862. viewer.dispatchEvent({type:'reticule_forbit', v:false});
  53863. this.markers.forEach(e=>e.isDragging = false );
  53864. }
  53865. }
  53866. transformData(prop){
  53867. const pick = (defaul, alternative) => {
  53868. if(defaul != null){
  53869. return defaul;
  53870. }else {
  53871. return alternative;
  53872. }
  53873. };
  53874. prop.showDistances = (prop.showDistances === null) ? true : prop.showDistances;
  53875. prop.showArea = pick(prop.showArea, false);
  53876. prop.showAngles = pick(prop.showAngles, false);
  53877. prop.showCoordinates = pick(prop.showCoordinates, false);
  53878. prop.showHeight = pick(prop.showHeight, false);
  53879. prop.showCircle = pick(prop.showCircle, false);
  53880. prop.showAzimuth = pick(prop.showAzimuth, false);
  53881. prop.showEdges = pick(prop.showEdges, true);
  53882. prop.closed = pick(prop.closed, false);
  53883. prop.maxMarkers = pick(prop.maxMarkers, Infinity);
  53884. prop.direction = prop.direction;//add
  53885. prop.type = prop.type;
  53886. prop.showGuideLine = pick(prop.showGuideLine, false);
  53887. prop.isRect = pick(prop.isRect, false);
  53888. }
  53889. setSelected(){}
  53890. continueDrag(marker, e){
  53891. let object = marker || e.drag.object;
  53892. object.isDragging = true;
  53893. this.editStateChange(true);
  53894. var timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
  53895. if(this.parent && object.isDragging){
  53896. console.log('continueDrag', object.uuid);
  53897. viewer.inputHandler.startDragging( object ,
  53898. {endDragFun: e.drag.endDragFun, notPressMouse:e.drag.notPressMouse, dragViewport:e.drag.dragViewport}
  53899. );
  53900. }
  53901. },1);
  53902. return timer
  53903. }
  53904. }
  53905. function getDifferentPoint(points, count){//for facePlane
  53906. var result = [];
  53907. for(let i=0;i<points.length;i++){
  53908. var p = points[i];
  53909. if(result.find(e=>e.equals(p)))continue;
  53910. else result.push(p);
  53911. if(result.length == count)break
  53912. }
  53913. if(result.length == count)return result
  53914. }
  53915. let texLoader$2 = new TextureLoader();
  53916. let defaultColor$1 = new Color(config$1.measure.default.color);
  53917. let highlightColor = new Color(config$1.measure.highlight.color);
  53918. let color = new Color(config$1.measure.color);
  53919. let textColor = new Color(config$1.measure.textColor);
  53920. var markerMats = {};
  53921. var lineMats ;
  53922. var planeMats;
  53923. const lineDepthInfo = {
  53924. clipDistance : 4,//消失距离
  53925. occlusionDistance: 1,//变为backColor距离
  53926. };
  53927. const LabelDepthInfo = {
  53928. clipDistance : 6,//消失距离
  53929. occlusionDistance: 2,//变为backColor距离
  53930. };
  53931. /* const LabelDepthInfo = {
  53932. clipDistance : 0.1,//消失距离
  53933. occlusionDistance: 0.1,//变为backColor距离
  53934. } */
  53935. const markerSizeInfo = {
  53936. minSize : 30*2 , maxSize : 65*2, nearBound : 0.2, farBound : 4,
  53937. };
  53938. const labelSizeInfo = {width2d:190};
  53939. const mainLabelProp = {
  53940. backgroundColor: {r: defaultColor$1.r*255, g: defaultColor$1.g*255, b: defaultColor$1.b*255, a:config$1.measure.default.opacity},
  53941. textColor: {r: textColor.r*255, g: textColor.g*255, b: textColor.b*255, a: 1.0},
  53942. fontsize: 14,
  53943. useDepth : true , borderRadius : 12, margin:{x:20,y:4},
  53944. renderOrder : 5, pickOrder:5,
  53945. };
  53946. const subLabelProp = {
  53947. backgroundColor: {r: 255, g: 255, b: 255, a:config$1.measure.default.opacity},
  53948. textColor: {r: 0.3, g: 0.3, b:0.3, a: 1.0},
  53949. fontsize:12, borderRadius : 12, margin:{x:20,y:4},
  53950. renderOrder : 4, pickOrder:4,
  53951. };
  53952. const angle = MathUtils$1.degToRad(5);//显示水平垂直辅助线的最小角度
  53953. const guideShowMinAngle = {min: angle, max: Math.PI/2 - angle};
  53954. class Measure$1 extends ctrlPolygon{
  53955. constructor (prop) {
  53956. prop.dimension = '2d';
  53957. super('measure',prop);
  53958. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  53959. this.name = this.measureType + this.constructor.counter; //'Measure_' + this.constructor.counter;
  53960. //this.color = '#FF4399'
  53961. this.color = new Color(this.color);
  53962. this.markerLabels = [];
  53963. this.edgeLabels = [];
  53964. this.angleLabels = [];
  53965. this.coordinateLabels = [];
  53966. this.area = {value:0,string:''};
  53967. if( this.showArea ){
  53968. this.areaLabel = this.createAreaLabel();
  53969. this.add(this.areaLabel);
  53970. }
  53971. //add:
  53972. if(this.atPlane || this.faceDirection){ //是一个平面上的话
  53973. this.createGuideLine();
  53974. }
  53975. if(this.measureType == 'Distance' /* || this.measureType.includes('MulDistance') */){
  53976. this.createHorVerGuideLine();
  53977. }
  53978. this.selectStates = {};
  53979. this.setUnitSystem(prop.unit || viewer.unitConvert.UnitService.defaultSystem);
  53980. Potree.Utils.setObjectLayers(this, 'measure' );
  53981. //addMarkers:
  53982. this.initData(prop);
  53983. this.points_datasets || (this.points_datasets = []); //存每个点是哪个数据集
  53984. //这版应该没多数据集,不需要更新这个:
  53985. /* this.addEventListener('marker_dropped',(e)=>{
  53986. this.updateDatasetBelong(e.index)
  53987. }) */
  53988. this.addEventListener('isVisible', ()=>{
  53989. viewer.mapViewer && viewer.mapViewer.dispatchEvent({type:'content_changed'});
  53990. });
  53991. }
  53992. initData(prop){
  53993. let makeIt = super.initData(prop);
  53994. if(makeIt){
  53995. this.edges.forEach(edge=>{edge.dispatchEvent('addHoverEvent'); });
  53996. }else {
  53997. this.failBuilded = true;
  53998. }
  53999. }
  54000. updateDatasetBelong(changeIndex){//更新所属数据集
  54001. if(Potree.settings.editType == "merge"){//无地图
  54002. /* this.dataset_points = this.points.map((e,i)=>{
  54003. return Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.points_datasets[i], position:e.clone()})
  54004. }) */
  54005. this.dataset_points[changeIndex] = Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.points_datasets[changeIndex], position:this.points[changeIndex].clone()});
  54006. return
  54007. }
  54008. let old = this.datasetId;
  54009. let maxCount = {id:null,count:0};
  54010. let datasets = {};
  54011. this.points_datasets.forEach(e=>{
  54012. if(e == void 0)return
  54013. if(datasets[e]){
  54014. datasets[e] ++;
  54015. }else {
  54016. datasets[e] = 1;
  54017. }
  54018. });
  54019. for(let i in datasets) {
  54020. if(datasets[i]>maxCount.count){
  54021. maxCount = {id:i, count:datasets[i]};
  54022. }
  54023. }
  54024. this.datasetId = maxCount.count > 0 ? maxCount.id : null;
  54025. //if(this.datasetId != old){
  54026. //this.dispatchEvent({type:'changeDatasetId'})
  54027. if(this.datasetId == void 0){
  54028. this.dataset_points = null; //可能为空或[null,null...]
  54029. }else {
  54030. this.dataset_points = this.points.map(e=>{
  54031. return Potree.Utils.datasetPosTransform({toDataset:true,datasetId:this.datasetId, position:e.clone()})
  54032. });
  54033. }
  54034. //}
  54035. }
  54036. transformByPointcloud(){//每次移动点云 or 加载测量线时要获取一下当前position //有地图时
  54037. if(this.datasetId == void 0)return
  54038. this.points = this.dataset_points.map(e=>{
  54039. return Potree.Utils.datasetPosTransform({fromDataset:true, datasetId:this.datasetId, position:e.clone()})
  54040. });
  54041. this.getPoint2dInfo(this.points);
  54042. this.update({ifUpdateMarkers:true});
  54043. this.setSelected(false);//隐藏edgelabel
  54044. }
  54045. update(options={}) {
  54046. super.update(options);
  54047. if(this.showCoordinates && this.points.length>0){
  54048. let position = this.points[0];
  54049. this.markers[0].position.copy(position);
  54050. { // coordinate labels
  54051. let coordinateLabel = this.coordinateLabels[0];
  54052. let lonlat = viewer.transform.lonlatToLocal.inverse(position.toArray());
  54053. let EPSG4550 = viewer.transform.lonlatTo4550.forward(lonlat);
  54054. let pos = [
  54055. position.toArray(),
  54056. lonlat,
  54057. EPSG4550
  54058. ];
  54059. //let msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
  54060. let msg = pos.map(a=>
  54061. a.map(p => Utils.addCommas(p.toFixed(10))).join(", ")
  54062. ).join("<br>");
  54063. coordinateLabel.setText(msg);
  54064. coordinateLabel.setPos(position);
  54065. coordinateLabel.setVisible(true);//this.showCoordinates;
  54066. }
  54067. return
  54068. }
  54069. /* viewer.addEventListener('camera_changed',(e)=>{
  54070. if(e.changeInfo.positionChanged){
  54071. setLabelPos()
  54072. }
  54073. }) */
  54074. let setEdgeLabel = (label,p1,p2,distance)=>{//设置label位置和字
  54075. this.setEdgeLabelPos(label,p1,p2);
  54076. distance = distance == void 0 ? p1.distanceTo(p2) : distance;
  54077. var text = this.labelText || viewer.unitConvert.convert(distance, 'distance', Potree.settings.precision, this.unitSystem, 0.1 , true);//distance要传0.1 这个factor
  54078. label.setText(text);
  54079. };
  54080. let lastIndex = this.points.length - 1;
  54081. for (let index = 0; index <= lastIndex; index++) {
  54082. let nextIndex = (index + 1 > lastIndex) ? 0 : index + 1;
  54083. let previousIndex = (index === 0) ? lastIndex : index - 1;
  54084. //if(!this.closed && nextIndex == 0 )break; //add
  54085. let point = this.points[index];
  54086. let nextPoint = this.points[nextIndex];
  54087. let previousPoint = this.points[previousIndex];
  54088. if(this.showDistances || this.labelText){ // edge labels
  54089. let edgeLabel = this.edgeLabels[index];
  54090. let distance = this.labelText || point.distanceTo(nextPoint);
  54091. edgeLabel.shouldVisi = this.labelText || (index < lastIndex || this.isRect || this.closed && !this.isNew ) && distance>0;
  54092. /* this.closed || */edgeLabel.setVisible(edgeLabel.shouldVisi);
  54093. edgeLabel.sprite.lineDir = new Vector3().subVectors(point,nextPoint).normalize(); //[point,nextPoint]
  54094. if(edgeLabel.visible){
  54095. setEdgeLabel(edgeLabel,point,nextPoint,distance);
  54096. }
  54097. }
  54098. }
  54099. if(this.measureType == 'Distance' && this.points.length>1){//设置水平垂直辅助线
  54100. var pTop, pBtm;
  54101. if(this.points[0].z > this.points[1].z ){
  54102. pTop = this.points[0];
  54103. pBtm = this.points[1];
  54104. }else {
  54105. pTop = this.points[1];
  54106. pBtm = this.points[0];
  54107. }
  54108. let projectPos = new Vector3(pTop.x, pTop.y, pBtm.z);//两条guideline的交点
  54109. {//倾斜角度太小的时候不显示
  54110. let tan = pTop.distanceTo(projectPos) / pBtm.distanceTo(projectPos);
  54111. let angle = Math.atan(tan);
  54112. this.shouldShowHorVerGuide = angle > guideShowMinAngle.min && angle < guideShowMinAngle.max;
  54113. }
  54114. LineDraw.updateLine(this.verGuideEdge, [pTop, projectPos]);
  54115. LineDraw.updateLine(this.horGuideEdge, [pBtm, projectPos]);
  54116. setEdgeLabel(this.verEdgeLabel,pTop,projectPos);
  54117. setEdgeLabel(this.horEdgeLabel,pBtm,projectPos);
  54118. this.verGuideEdge.visible = this.horGuideEdge.visible = this.shouldShowHorVerGuide;
  54119. this.verEdgeLabel.visible = this.horEdgeLabel.visible = this.shouldShowHorVerGuide;
  54120. }
  54121. if(this.showArea && this.point2dInfo){ // update area
  54122. /* if(this.points.length>2){
  54123. this.area = {value:0};
  54124. this.areaLabel.setVisible(false)
  54125. }else{ */
  54126. let area = Math.abs(math.getArea(this.point2dInfo.points2d));//this.getArea();
  54127. let msg = viewer.unitConvert.convert(area, 'area', Potree.settings.precision, this.unitSystem/* , 0.1 */ );
  54128. this.area = {value:area, string:msg};
  54129. this.areaLabel.setPos(this.center);
  54130. this.areaLabel.setText(msg);
  54131. this.areaLabel.setVisible(true);
  54132. //}
  54133. }
  54134. };
  54135. setEdgeLabelPos(label,p1,p2){ //调整label的位置,使倾斜后看起来在线的中心,而不要挡住端点
  54136. let center = new Vector3().addVectors(p1,p2).multiplyScalar(0.5);
  54137. if(!label.sprite.lineDir || viewer.mainViewport.camera.type == 'OrthographicCamera'){
  54138. label.setPos(center);
  54139. }else {
  54140. let eyePos = viewer.mainViewport.camera.position;
  54141. let dir = viewer.mainViewport.view.direction; //new THREE.Vector3().subVectors(center,eyePos).normalize()
  54142. let vec = label.sprite.lineDir;
  54143. let cos = dir.dot(vec);
  54144. let efficiency = 0.35; // 0-1 数值越高,r越容易接近1或-1,label越容易在倾斜后靠近近端点。
  54145. let r = 0.5*efficiency*cos + 0.5;
  54146. //console.log(r, cos )
  54147. center = p1.clone().multiplyScalar(1-r).add(p2.clone().multiplyScalar(r)); //label在线上滑动,使尽量保持在视觉中心
  54148. label.setPos(center);
  54149. }
  54150. }
  54151. addMarker (o={}) {
  54152. let marker = new Sprite$2({mat:this.getMarkerMaterial('default'), sizeInfo: markerSizeInfo, name:"measure_point"} );
  54153. Potree.Utils.setObjectLayers(marker, 'measure' );
  54154. marker.pickOrder = marker.renderOrder = 3;
  54155. marker.markerSelectStates = {};
  54156. marker.addEventListener('startDragging',(e)=>{
  54157. if(e.drag.dragViewport.name == 'MainView')viewer.inputHandler.dispatchEvent( {type: 'isMeasuring',v:true, cause:'startDragging'});
  54158. });
  54159. marker.addEventListener('drop',(e)=>{
  54160. viewer.inputHandler.dispatchEvent({type: 'isMeasuring', v:false, cause:'stopDragging'} );
  54161. });
  54162. let edge;
  54163. { // edges
  54164. edge = LineDraw.createFatLine( [ ],{material:this.getLineMat('edgeDefault')} );
  54165. edge.pickOrder = 0;
  54166. Potree.Utils.setObjectLayers(edge, 'measure' );
  54167. let addHoverEvent = ()=>{ //当非isNew时才添加事件
  54168. let mouseover = (e) => {this.setSelected(true, 'edge');};
  54169. let mouseleave = (e) => {this.setSelected(false, 'edge');};
  54170. edge.addEventListener('mouseover', mouseover);
  54171. edge.addEventListener('mouseleave', mouseleave);
  54172. edge.removeEventListener('addHoverEvent', addHoverEvent);
  54173. };
  54174. edge.addEventListener('addHoverEvent', addHoverEvent);
  54175. }
  54176. super.addMarker({point:o.point, marker:marker, edge});
  54177. if(this.showEdges){ // edge labels
  54178. const edgeLabel = this.createEdgeLabel('edgeLabel', !this.closed);
  54179. this.edgeLabels.push(edgeLabel);
  54180. }
  54181. if(this.showCoordinates){ // coordinate labels
  54182. let coordinateLabel = new Label({
  54183. className:'measure_pointPos',
  54184. camera: viewer.scene.getActiveCamera()
  54185. });
  54186. coordinateLabel.setVisible(false);
  54187. this.coordinateLabels.push(coordinateLabel);
  54188. }
  54189. let event = {
  54190. type: 'marker_added',
  54191. measurement: this,
  54192. marker: marker
  54193. };
  54194. this.dispatchEvent(event);
  54195. //this.setMarker(this.points.length - 1, point);
  54196. this.update();//更新一下倒数第二条线
  54197. return marker;//add
  54198. };
  54199. editStateChange(state){ //主要针对edgeLabels显示切换,编辑时显示
  54200. super.editStateChange(state);
  54201. if(!state){
  54202. this.editStateTimer = setTimeout(()=>{
  54203. if(!this.isEditing){
  54204. this.dispatchEvent({type:'editStateChange',state:false});
  54205. this.setEdgesDisplay(false);
  54206. this.areaPlane && Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', true);
  54207. this.areaLabel && Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', true);
  54208. }
  54209. },100);
  54210. }else {
  54211. if(!this.isEditing){
  54212. this.dispatchEvent({type:'editStateChange',state:true});
  54213. this.setEdgesDisplay(true);
  54214. clearTimeout(this.editStateTimer);
  54215. }
  54216. }
  54217. this.isEditing = state;
  54218. viewer.dispatchEvent({type:'MeasureDragChange',state});
  54219. }
  54220. setMarkerSelected(marker, state, hoverObject){
  54221. //console.warn(marker.id , state, hoverObject)
  54222. marker.markerSelectStates[hoverObject] = state;
  54223. let absoluteState = false;
  54224. for(var i in marker.markerSelectStates){
  54225. if(marker.markerSelectStates[i] == 'hover'){
  54226. absoluteState = true; break;
  54227. }
  54228. }
  54229. if(absoluteState){
  54230. marker.material = this.getMarkerMaterial('select');
  54231. }else {
  54232. marker.material = this.getMarkerMaterial('default');
  54233. }
  54234. marker.selected = absoluteState;
  54235. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed');
  54236. viewer.dispatchEvent('content_changed');
  54237. }
  54238. setEdgesDisplay(state, ignoreGuideLine){
  54239. this.closed && this.edgeLabels.forEach(e=>e.setVisible(!!(state && e.shouldVisi)) );
  54240. if(!ignoreGuideLine && this.measureType == 'Distance'){
  54241. this.horEdgeLabel.visible = this.verEdgeLabel.visible = this.horGuideEdge.visible = this.verGuideEdge.visible = !!(state && this.shouldShowHorVerGuide);
  54242. }
  54243. }
  54244. setSelected(state, hoverObject){//add
  54245. //console.log('setSelected', state, hoverObject)
  54246. hoverObject && (this.selectStates[hoverObject] = state);
  54247. let absoluteState = false;
  54248. for(var i in this.selectStates){
  54249. if(this.selectStates[i]){
  54250. absoluteState = true; break;
  54251. }
  54252. }
  54253. if(absoluteState){
  54254. this.markers.forEach(e=>this.setMarkerSelected(e, 'hover', 'selectAll' ) );
  54255. this.edges.forEach(e=>e.material = this.getLineMat('edgeSelect') );
  54256. this.areaPlane && (this.areaPlane.material = planeMats.selected);
  54257. //this.areaLabel && this.areaLabel.elem.addClass('highLight')
  54258. //this.closed || this.edgeLabels.forEach(e=>e.elem.addClass('highLight') )
  54259. this.setEdgesDisplay(true, hoverObject=="screenshot");
  54260. this.areaLabel && this.setLabelHightState(this.areaLabel, true);
  54261. this.closed || this.edgeLabels.forEach(e=>this.setLabelHightState(e, true) );
  54262. }else {
  54263. this.markers.forEach(e=>this.setMarkerSelected(e, 'unhover', 'selectAll' ));
  54264. this.edges.forEach(e=>e.material = this.getLineMat('edgeDefault') );
  54265. this.areaPlane && (this.areaPlane.material = planeMats.default);
  54266. this.setEdgesDisplay(false, hoverObject=="screenshot");
  54267. //this.areaLabel && this.areaLabel.elem.removeClass('highLight')
  54268. //this.closed || this.edgeLabels.forEach(e=>e.elem.removeClass('highLight') )
  54269. this.areaLabel && this.setLabelHightState(this.areaLabel, false);
  54270. this.closed || this.edgeLabels.forEach(e=>this.setLabelHightState(e, false) );
  54271. }
  54272. this.selected = absoluteState;
  54273. if(hoverObject != 'byList'){
  54274. //this.bus && this.bus.emit('highlight', this.selected)
  54275. this.dispatchEvent({type:'highlight',state:this.selected});//列表高亮
  54276. }
  54277. viewer.dispatchEvent('content_changed');
  54278. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed');
  54279. }
  54280. setLabelHightState(label, state){
  54281. if(state){
  54282. let color = new Color(Potree.config.measure.highlight.color);
  54283. label.backgroundColor = {r:255*color.r, g:255*color.g, b:255*color.b, a:config$1.measure.highlight.opacity},
  54284. //label.backgroundColor.a = config.measure.highlight.opacity
  54285. label.sprite.material.useDepth = false;
  54286. //label.textColor = {r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a: 1}
  54287. }else {
  54288. label.backgroundColor = {r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a:config$1.measure.default.opacity};
  54289. //label.backgroundColor.a = config.measure.default.opacity
  54290. label.sprite.material.useDepth = true;
  54291. //label.textColor = {r: 255, g: 255, b: 255, a: 1}
  54292. }
  54293. label.updateTexture();
  54294. }
  54295. removeMarker(index ){
  54296. super.removeMarker(index);
  54297. this.points_datasets.splice(index, 1);
  54298. this.dataset_points && this.dataset_points.splice(index, 1);
  54299. this.coordinateLabels.splice(index, 1);
  54300. let edgeIndex = index;//(index === 0) ? 0 : (index - 1);
  54301. if(this.edgeLabels[edgeIndex]){
  54302. this.edgeLabels[edgeIndex].dispose();
  54303. this.edgeLabels.splice(edgeIndex, 1);
  54304. }
  54305. this.update();
  54306. this.dispatchEvent({type: 'marker_removed', measurement: this});
  54307. }
  54308. setPosition(index, position) {
  54309. super.setPosition(index, position);
  54310. let event = {
  54311. type: 'marker_moved',
  54312. measure: this,
  54313. index: index,
  54314. position: position.clone()
  54315. };
  54316. this.dispatchEvent(event);
  54317. }
  54318. dispose(){//add
  54319. var labels = this.edgeLabels.concat(this.coordinateLabels);
  54320. this.areaLabel && labels.push(this.areaLabel);
  54321. labels.forEach(e=>e.dispatchEvent({type:'dispose'}));
  54322. super.dispose();
  54323. }
  54324. getTotalDistance () {
  54325. if (this.points.length === 0) {
  54326. return 0;
  54327. }
  54328. let distance = 0;
  54329. for (let i = 1; i < this.points.length; i++) {
  54330. let prev = this.points[i - 1];
  54331. let curr = this.points[i];
  54332. let d = prev.distanceTo(curr);
  54333. distance += d;
  54334. }
  54335. if (this.closed && this.points.length > 1) {
  54336. let first = this.points[0];
  54337. let last = this.points[this.points.length - 1];
  54338. let d = last.distanceTo(first);
  54339. distance += d;
  54340. }
  54341. return distance;
  54342. }
  54343. getAngleBetweenLines (cornerPoint, point1, point2) {
  54344. let v1 = new Vector3().subVectors(point1, cornerPoint);
  54345. let v2 = new Vector3().subVectors(point2, cornerPoint);
  54346. // avoid the error printed by threejs if denominator is 0
  54347. const denominator = Math.sqrt( v1.lengthSq() * v2.lengthSq() );
  54348. if(denominator === 0){
  54349. return 0;
  54350. }else {
  54351. return v1.angleTo(v2);
  54352. }
  54353. };
  54354. getAngle (index) {
  54355. if (this.points.length < 3 || index >= this.points.length) {
  54356. return 0;
  54357. }
  54358. let previous = (index === 0) ? this.points[this.points.length - 1] : this.points[index - 1];
  54359. let point = this.points[index];
  54360. let next = this.points[(index + 1) % (this.points.length)];
  54361. return this.getAngleBetweenLines(point, previous, next);
  54362. }
  54363. getCenter(/* update */){
  54364. if(this.closed){
  54365. return this.center.clone()
  54366. }else {
  54367. let center = this.points.reduce(function(total, currentValue ){
  54368. return total.add(currentValue)
  54369. }, new Vector3 );
  54370. center.multiplyScalar(1/this.points.length);
  54371. return center //求不出重心呜呜
  54372. }
  54373. }
  54374. // updateAzimuth(){
  54375. // // if(this.points.length !== 2){
  54376. // // return;
  54377. // // }
  54378. // // const azimuth = this.azimuth;
  54379. // // const [p0, p1] = this.points;
  54380. // // const r = p0.distanceTo(p1);
  54381. // }
  54382. createGuideLine(){//add 辅助线
  54383. var guideLine = LineDraw.createFatLine([ ],{material:this.getLineMat('guide')} );
  54384. guideLine.visible = false;
  54385. this.guideLine = guideLine;
  54386. this.add(guideLine);
  54387. }
  54388. createHorVerGuideLine(){//创建水平与垂直辅助线,仅距离测量有。
  54389. var verGuideEdge = LineDraw.createFatLine([ ],{material:this.getLineMat('guide')} );
  54390. verGuideEdge.visible = false;
  54391. this.verGuideEdge = verGuideEdge;
  54392. verGuideEdge.name = 'verGuideEdge';
  54393. var horGuideEdge = LineDraw.createFatLine([ ],{material:this.getLineMat('guide')} );
  54394. horGuideEdge.visible = false;
  54395. horGuideEdge.name = 'horGuideEdge';
  54396. this.horGuideEdge = horGuideEdge;
  54397. this.add(this.verGuideEdge);
  54398. this.add(this.horGuideEdge);
  54399. //label:
  54400. this.verEdgeLabel = this.createEdgeLabel('verGuideEdge');
  54401. this.horEdgeLabel = this.createEdgeLabel('horGuideEdge');
  54402. }
  54403. focus({dontMoveCamera=false}={}){
  54404. if(!dontMoveCamera){
  54405. let dontChangeCamDir = viewer.mainViewport.camera.type == 'OrthographicCamera'; /* && math.closeTo( viewer.mainViewport.view.pitch , -1.57079632) */ // 不改角度
  54406. viewer.focusOnObject(this, 'measure', null, {dontChangeCamDir});
  54407. }
  54408. if(this.clickSelected)return
  54409. this.setSelected(true, 'focus');
  54410. this.dispatchEvent({type:'selected', state:true});
  54411. this.clickSelected = true;
  54412. //viewer.dispatchEvent({type:'selectMeasure', measure:this})
  54413. let cancelSelect = ()=>{
  54414. this.clickSelected = false;
  54415. this.removeEventListener('cancelSelect', cancelSelect);
  54416. viewer.removeEventListener('global_click', cancelSelect);
  54417. this.setSelected(false, 'focus');
  54418. this.dispatchEvent({type:'selected', state:false});
  54419. };
  54420. setTimeout(()=>{
  54421. this.addEventListener('cancelSelect', cancelSelect);
  54422. viewer.addEventListener('global_click', cancelSelect);
  54423. },10);
  54424. }
  54425. createEdgeLabel(name, hasHoverEvent){
  54426. mainLabelProp.backgroundColor = {r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a:config$1.measure.default.opacity};
  54427. const edgeLabel = new TextSprite$2(
  54428. $.extend(hasHoverEvent ? mainLabelProp : subLabelProp,{
  54429. sizeInfo: labelSizeInfo, name:name||'edgeLabel',
  54430. })
  54431. );
  54432. if(hasHoverEvent){
  54433. edgeLabel.addEventListener('mouseover',()=>{
  54434. this.setSelected(true, 'edgeLabel');
  54435. });
  54436. edgeLabel.addEventListener('mouseleave',()=>{
  54437. this.setSelected(false, 'edgeLabel');
  54438. });
  54439. edgeLabel.addEventListener('click',()=>{
  54440. if(!this.isNew) this.focus();
  54441. });
  54442. }
  54443. edgeLabel.visible = false;
  54444. edgeLabel.sprite.material.depthTestWhenPick = true;
  54445. Potree.Utils.setObjectLayers(edgeLabel, 'measure' );
  54446. this.add(edgeLabel);
  54447. return edgeLabel
  54448. }
  54449. createAreaLabel(){
  54450. /* const areaLabel = new Label({
  54451. className:'measure_area',
  54452. })
  54453. areaLabel.elem.on('mouseover',()=>{
  54454. this.setSelected(true, 'areaLabel')
  54455. })
  54456. areaLabel.elem.on('mouseout',()=>{
  54457. this.setSelected(false, 'areaLabel')
  54458. }) */
  54459. const areaLabel = new TextSprite$2(
  54460. $.extend(mainLabelProp,{sizeInfo: labelSizeInfo, name:'areaLabel_'} )
  54461. );
  54462. areaLabel.addEventListener('mouseover',()=>{
  54463. this.setSelected(true, 'areaLabel');
  54464. });
  54465. areaLabel.addEventListener('mouseleave',()=>{
  54466. this.setSelected(false, 'areaLabel');
  54467. });
  54468. areaLabel.addEventListener('click',()=>{
  54469. if(!this.isNew) this.focus();
  54470. });
  54471. Potree.Utils.setObjectLayers(areaLabel, 'measure' );
  54472. areaLabel.setVisible(false);
  54473. return areaLabel;
  54474. }
  54475. getMarkerMaterial(type){
  54476. let color = this.color.getHexString();
  54477. if(!markerMats[type + color]){
  54478. markerMats['default' + color] = new DepthBasicMaterial($.extend({},lineDepthInfo,{
  54479. transparent: !0,
  54480. opacity: 1,
  54481. map: texLoader$2.load(Potree.resourcePath+'/textures/pic_point_s32.png' ),
  54482. useDepth:true,
  54483. replaceColor:this.color,
  54484. beReplacedRed: 0.184, //0.18431372
  54485. mapColorReplace:true,
  54486. })),
  54487. markerMats['select' + color] = new DepthBasicMaterial($.extend({},lineDepthInfo,{
  54488. transparent: !0,
  54489. opacity: 1,
  54490. map: texLoader$2.load(Potree.resourcePath+'/textures/pic_point32.png' ),
  54491. //useDepth:true ,
  54492. replaceColor: new Color(Potree.config.measure.highlight.color) ,
  54493. beReplacedRed: 0.184, //0.18431372
  54494. mapColorReplace:true
  54495. }));
  54496. }
  54497. return markerMats[type + color]
  54498. }
  54499. getLineMat(type) {
  54500. if(!lineMats) Measure$1.lineMats = lineMats = {
  54501. guide: LineDraw.createFatLineMat({
  54502. color:config$1.measure.guide.color,
  54503. dashSize: 0.1,
  54504. gapSize: 0.02,
  54505. dashed: true,
  54506. lineWidth: 2
  54507. })
  54508. };
  54509. let color = this.color.getHexString();
  54510. if(!lineMats['edgeDefault'+color]){
  54511. lineMats['edgeDefault'+color] = LineDraw.createFatLineMat({
  54512. color: this.color,
  54513. lineWidth: config$1.measure.lineWidth,
  54514. useDepth :true,
  54515. dashWithDepth :true, // 只在被遮住的部分显示虚线,因为实线容易挡住label
  54516. dashed :true,
  54517. dashSize : 0.04,
  54518. gapSize: 0.04,
  54519. transparent: true,
  54520. opacity: config$1.measure.default.opacity,
  54521. depthTestWhenPick:true,
  54522. });
  54523. lineMats['edgeSelect'+color] = LineDraw.createFatLineMat({
  54524. color: Potree.config.measure.highlight.color ,
  54525. dashSize: 0.5,
  54526. gapSize: 0.2,
  54527. lineWidth: config$1.measure.lineWidth ,
  54528. transparent: true,
  54529. opacity: config$1.measure.highlight.opacity
  54530. });
  54531. }
  54532. if(type != 'guide'){
  54533. return Measure$1.lineMats[type+color]
  54534. }else return Measure$1.lineMats[type]
  54535. }
  54536. createAreaPlane(){
  54537. planeMats || (planeMats = {
  54538. default: new DepthBasicMaterial( $.extend({},LabelDepthInfo,{
  54539. color:color,
  54540. side:DoubleSide,
  54541. opacity:0.2,
  54542. transparent:true,
  54543. useDepth:true
  54544. })),
  54545. selected: new MeshBasicMaterial({
  54546. color: color ,
  54547. side:DoubleSide,
  54548. opacity:0.3,
  54549. transparent:true,
  54550. })
  54551. },Measure$1.planeMats = planeMats);
  54552. return super.createAreaPlane(planeMats.default)
  54553. }
  54554. raycast (raycaster, intersects) {
  54555. for (let i = 0; i < this.points.length; i++) {
  54556. let marker = this.markers[i];
  54557. marker.raycast(raycaster, intersects);
  54558. }
  54559. // recalculate distances because they are not necessarely correct
  54560. // for scaled objects.
  54561. // see https://github.com/mrdoob/three.js/issues/5827
  54562. // TODO: remove this once the bug has been fixed
  54563. for (let i = 0; i < intersects.length; i++) {
  54564. let I = intersects[i];
  54565. I.distance = raycaster.ray.origin.distanceTo(I.point);
  54566. }
  54567. intersects.sort(function (a, b) { return a.distance - b.distance; });
  54568. };
  54569. transformData(prop){
  54570. if(prop.measureType == 'Point'){
  54571. prop.showCoordinates = true,
  54572. prop.closed = true,
  54573. prop.maxMarkers = 1,
  54574. prop.minMarkers = 1;
  54575. }else if(prop.measureType == 'Distance'){
  54576. prop.showDistances = true,
  54577. prop.showEdges = true,
  54578. prop.maxMarkers = 2,
  54579. prop.minMarkers = 2;
  54580. }else if(prop.measureType == 'MulDistance'){//new
  54581. prop.showDistances = true,
  54582. prop.showEdges = true,
  54583. prop.minMarkers = 2;
  54584. }else if(prop.measureType == 'Ver MulDistance'){
  54585. prop.showDistances = true,
  54586. prop.atPlane = true,
  54587. prop.showEdges = true,
  54588. prop.minMarkers = 2;
  54589. prop.faceDirection = "vertical";
  54590. prop.unableDragAtMap = true;
  54591. }else if(prop.measureType == 'Hor MulDistance'){
  54592. prop.showDistances = true,
  54593. prop.atPlane = true,
  54594. prop.showEdges = true,
  54595. prop.minMarkers = 2;
  54596. prop.faceDirection = "horizontal";
  54597. }else if(prop.measureType == 'Ver Distance'){
  54598. prop.showDistances = true,
  54599. prop.showEdges = true,
  54600. prop.maxMarkers = 2,
  54601. prop.minMarkers = 2,
  54602. prop.faceDirection = "vertical";
  54603. prop.unableDragAtMap = true;
  54604. }else if(prop.measureType == 'Hor Distance'){
  54605. prop.showDistances = true,
  54606. prop.showEdges = true,
  54607. prop.maxMarkers = 2,
  54608. prop.minMarkers = 2,
  54609. prop.faceDirection = "horizontal";
  54610. }else if(prop.measureType == "Hor LINE with Text"){ //add
  54611. prop.showEdges = true,
  54612. prop.maxMarkers = 2,
  54613. prop.minMarkers = 2,
  54614. prop.faceDirection = "horizontal";
  54615. }else if(prop.measureType == 'Area'){
  54616. prop.showDistances = true,
  54617. prop.atPlane = true,
  54618. prop.showEdges = true,
  54619. prop.closed = true,
  54620. prop.minMarkers = 3;
  54621. }else if(prop.measureType == 'Hor Area'){
  54622. prop.showDistances = true,
  54623. prop.atPlane = true,
  54624. prop.showEdges = true,
  54625. prop.closed = true,
  54626. prop.minMarkers = 3;
  54627. prop.faceDirection = "horizontal";
  54628. }else if(prop.measureType == 'Ver Area'){
  54629. prop.showDistances = true,
  54630. prop.atPlane = true,
  54631. prop.showEdges = true,
  54632. prop.closed = true,
  54633. prop.minMarkers = 3;
  54634. prop.faceDirection = "vertical";
  54635. prop.unableDragAtMap = true;
  54636. }else if(prop.measureType == 'Rect Area'){
  54637. prop.showDistances = true,
  54638. prop.atPlane = true,
  54639. prop.showEdges = true,
  54640. prop.closed = true,
  54641. prop.minMarkers = 4;
  54642. prop.maxMarkers = 4;
  54643. }else if(prop.measureType == 'Hor Rect Area'){
  54644. prop.showDistances = true,
  54645. prop.atPlane = true,
  54646. prop.showEdges = true,
  54647. prop.closed = true,
  54648. prop.minMarkers = 4;
  54649. prop.maxMarkers = 4;
  54650. prop.isRect = true;
  54651. prop.faceDirection = "horizontal";
  54652. }else if(prop.measureType == 'Ver Rect Area'){
  54653. prop.showDistances = true,
  54654. prop.atPlane = true,
  54655. prop.showEdges = true,
  54656. prop.closed = true,
  54657. prop.minMarkers = 4;
  54658. prop.maxMarkers = 4;
  54659. prop.isRect = true;
  54660. prop.faceDirection = "vertical";
  54661. prop.unableDragAtMap = true;
  54662. }
  54663. if(prop.atPlane && prop.closed){ //atPlane在同一平面上
  54664. prop.showArea = true;
  54665. }
  54666. super.transformData(prop);
  54667. }
  54668. setUnitSystem(unitSystem){
  54669. //console.log(this.name +':' +this.unitSystem)
  54670. if(unitSystem != this.unitSystem){
  54671. if(unitSystem == "metric"){
  54672. }else if(unitSystem == 'imperial'){
  54673. }
  54674. this.unitSystem = unitSystem;
  54675. this.update();
  54676. }
  54677. }
  54678. reDraw(restMarkerCount=0){//重新开始画
  54679. super.reDraw(restMarkerCount);
  54680. if(this.measureType == 'Distance'){
  54681. this.shouldShowHorVerGuide = false;
  54682. this.setEdgesDisplay(false);
  54683. }
  54684. if(this.showArea){
  54685. this.area = {value:0};
  54686. this.areaLabel && this.areaLabel.setVisible(false);
  54687. }
  54688. viewer.inputHandler.dispatchEvent( {type:'isMeasuring', v:true, cause:'reDraw'} );
  54689. }
  54690. /* get showCoordinates () {
  54691. return this._showCoordinates;
  54692. }
  54693. set showCoordinates (value) {
  54694. this._showCoordinates = value;
  54695. this.update();
  54696. }
  54697. get showAngles () {
  54698. return this._showAngles;
  54699. }
  54700. set showAngles (value) {
  54701. this._showAngles = value;
  54702. this.update();
  54703. }
  54704. get showCircle () {
  54705. return this._showCircle;
  54706. }
  54707. set showCircle (value) {
  54708. this._showCircle = value;
  54709. this.update();
  54710. }
  54711. get showAzimuth(){
  54712. return this._showAzimuth;
  54713. }
  54714. set showAzimuth(value){
  54715. this._showAzimuth = value;
  54716. this.update();
  54717. }
  54718. get showEdges () {
  54719. return this._showEdges;
  54720. }
  54721. set showEdges (value) {
  54722. this._showEdges = value;
  54723. this.update();
  54724. }
  54725. get showHeight () {
  54726. return this._showHeight;
  54727. }
  54728. set showHeight (value) {
  54729. this._showHeight = value;
  54730. this.update();
  54731. }
  54732. get showArea () {
  54733. return this._showArea;
  54734. }
  54735. set showArea (value) {
  54736. this._showArea = value;
  54737. this.update();
  54738. }
  54739. get closed () {
  54740. return this._closed;
  54741. }
  54742. set closed (value) {
  54743. this._closed = value;
  54744. this.update();
  54745. }
  54746. get showDistances () {
  54747. return this._showDistances;
  54748. }
  54749. set showDistances (value) {
  54750. this._showDistances = value;
  54751. this.update();
  54752. } */
  54753. }
  54754. function createCircleRadiusLabel$1(){
  54755. const circleRadiusLabel = new TextSprite$2("");
  54756. circleRadiusLabel.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  54757. circleRadiusLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  54758. circleRadiusLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  54759. circleRadiusLabel.fontsize = 16;
  54760. circleRadiusLabel.material.depthTest = false;
  54761. circleRadiusLabel.material.opacity = 1;
  54762. circleRadiusLabel.visible = false;
  54763. return circleRadiusLabel;
  54764. }
  54765. function createCircleRadiusLine$1(){
  54766. /* const lineGeometry = new LineGeometry();
  54767. lineGeometry.setPositions([
  54768. 0, 0, 0,
  54769. 0, 0, 0,
  54770. ]);
  54771. const lineMaterial = new LineMaterial({
  54772. color: 0xff0000,
  54773. lineWidth: 2,
  54774. resolution: new THREE.Vector2(1000, 1000),
  54775. gapSize: 1,
  54776. dashed: true,
  54777. });
  54778. lineMaterial.depthTest = false;
  54779. const circleRadiusLine = new Line2(lineGeometry, lineMaterial);*/
  54780. var circleRadiusLine = LineDraw.createFatLine([ ],{
  54781. color:0xff0000,
  54782. dashSize: 0.5,
  54783. gapSize: 0.2,
  54784. lineWidth: config$1.measure.lineWidth
  54785. });
  54786. circleRadiusLine.visible = false;
  54787. return circleRadiusLine;
  54788. }
  54789. function createCircleLine$1(){
  54790. const coordinates = [];
  54791. let n = 128;
  54792. for(let i = 0; i <= n; i++){
  54793. let u0 = 2 * Math.PI * (i / n);
  54794. let u1 = 2 * Math.PI * (i + 1) / n;
  54795. let p0 = new Vector3(
  54796. Math.cos(u0),
  54797. Math.sin(u0),
  54798. 0
  54799. );
  54800. let p1 = new Vector3(
  54801. Math.cos(u1),
  54802. Math.sin(u1),
  54803. 0
  54804. );
  54805. coordinates.push(
  54806. p0,
  54807. p1
  54808. );
  54809. }
  54810. /* const geometry = new LineGeometry();
  54811. geometry.setPositions(coordinates);
  54812. const material = new LineMaterial({
  54813. color: 0xff0000,
  54814. dashSize: 5,
  54815. gapSize: 2,
  54816. lineWidth: 2,
  54817. resolution: new THREE.Vector2(1000, 1000),
  54818. });
  54819. material.depthTest = false;
  54820. const circleLine = new Line2(geometry, material);
  54821. circleLine.visible = false;
  54822. circleLine.computeLineDistances();*/
  54823. var circleLine = LineDraw.createFatLine(coordinates,{
  54824. color: 0xff0000,
  54825. dashSize: 0.5,
  54826. gapSize: 0.2,
  54827. lineWidth: config$1.measure.lineWidth
  54828. });
  54829. return circleLine;
  54830. }
  54831. /* function createCircleCenter(){
  54832. const sg = new THREE.markerGeometry(1, 32, 32);
  54833. const sm = new THREE.MeshNormalMaterial();
  54834. const circleCenter = new THREE.Mesh(sg, sm);
  54835. circleCenter.visible = false;
  54836. return circleCenter;
  54837. } */
  54838. function createLine$1(){
  54839. const line = LineDraw.createFatLine([ ],{
  54840. color: 0xff0000,
  54841. dashSize: 0.5,
  54842. gapSize: 0.2,
  54843. lineWidth: config$1.measure.lineWidth
  54844. });
  54845. return line;
  54846. }
  54847. function createCircle$1(){
  54848. const coordinates = [];
  54849. let n = 128;
  54850. for(let i = 0; i <= n; i++){
  54851. let u0 = 2 * Math.PI * (i / n);
  54852. let u1 = 2 * Math.PI * (i + 1) / n;
  54853. let p0 = new Vector3(
  54854. Math.cos(u0),
  54855. Math.sin(u0),
  54856. 0
  54857. );
  54858. let p1 = new Vector3(
  54859. Math.cos(u1),
  54860. Math.sin(u1),
  54861. 0
  54862. );
  54863. coordinates.push(
  54864. p0,
  54865. p1
  54866. );
  54867. }
  54868. var line = LineDraw.createFatLine(coordinates,{
  54869. color: 0xff0000,
  54870. dashSize: 0.5,
  54871. gapSize: 0.2,
  54872. lineWidth: config$1.measure.lineWidth
  54873. });
  54874. return line;
  54875. }
  54876. Measure$1.markerMats = markerMats;
  54877. /* function createAzimuth(){
  54878. const azimuth = {
  54879. label: null,
  54880. center: null,
  54881. target: null,
  54882. north: null,
  54883. centerToNorth: null,
  54884. centerToTarget: null,
  54885. centerToTargetground: null,
  54886. targetgroundToTarget: null,
  54887. circle: null,
  54888. node: null,
  54889. };
  54890. const sg = new THREE.markerGeometry(1, 32, 32);
  54891. const sm = new THREE.MeshNormalMaterial();
  54892. {
  54893. const label = new TextSprite("");
  54894. label.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  54895. label.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  54896. label.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  54897. label.fontsize = 16;
  54898. label.material.depthTest = false;
  54899. label.material.opacity = 1;
  54900. azimuth.label = label;
  54901. }
  54902. azimuth.center = new THREE.Mesh(sg, sm);
  54903. azimuth.target = new THREE.Mesh(sg, sm);
  54904. azimuth.north = new THREE.Mesh(sg, sm);
  54905. azimuth.centerToNorth = createLine();
  54906. azimuth.centerToTarget = createLine();
  54907. azimuth.centerToTargetground = createLine();
  54908. azimuth.targetgroundToTarget = createLine();
  54909. azimuth.circle = createCircle();
  54910. azimuth.node = new THREE.Object3D();
  54911. azimuth.node.add(
  54912. azimuth.centerToNorth,
  54913. azimuth.centerToTarget,
  54914. azimuth.centerToTargetground,
  54915. azimuth.targetgroundToTarget,
  54916. azimuth.circle,
  54917. azimuth.label,
  54918. azimuth.center,
  54919. azimuth.target,
  54920. azimuth.north,
  54921. );
  54922. return azimuth;
  54923. } */
  54924. /*
  54925. */
  54926. function updateAzimuth(viewer, measure){
  54927. if(!measure.showAzimuth)return
  54928. const azimuth = measure.azimuth;
  54929. const isOkay = measure.points.length === 2;
  54930. azimuth.node.visible = isOkay;
  54931. if(!azimuth.node.visible){
  54932. return;
  54933. }
  54934. const camera = viewer.scene.getActiveCamera();
  54935. const renderAreaSize = viewer.renderer.getSize(new Vector2());
  54936. const width = renderAreaSize.width;
  54937. const height = renderAreaSize.height;
  54938. const [p0, p1] = measure.points;
  54939. const r = p0.position.distanceTo(p1.position);
  54940. const northVec = Utils.getNorthVec(p0.position, r, viewer.getProjection());
  54941. const northPos = p0.position.clone().add(northVec);
  54942. azimuth.center.position.copy(p0.position);
  54943. azimuth.center.scale.set(2, 2, 2);
  54944. azimuth.center.visible = false;
  54945. // azimuth.target.visible = false;
  54946. { // north
  54947. azimuth.north.position.copy(northPos);
  54948. azimuth.north.scale.set(2, 2, 2);
  54949. let distance = azimuth.north.position.distanceTo(camera.position);
  54950. let pr = Utils.projectedRadius(1, camera, distance, width, height);
  54951. let scale = (5 / pr);
  54952. azimuth.north.scale.set(scale, scale, scale);
  54953. }
  54954. { // target
  54955. azimuth.target.position.copy(p1.position);
  54956. azimuth.target.position.z = azimuth.north.position.z;
  54957. let distance = azimuth.target.position.distanceTo(camera.position);
  54958. let pr = Utils.projectedRadius(1, camera, distance, width, height);
  54959. let scale = (5 / pr);
  54960. azimuth.target.scale.set(scale, scale, scale);
  54961. }
  54962. azimuth.circle.position.copy(p0.position);
  54963. azimuth.circle.scale.set(r, r, r);
  54964. azimuth.circle.material.resolution.set(width, height);
  54965. // to target
  54966. azimuth.centerToTarget.geometry.setPositions([
  54967. 0, 0, 0,
  54968. ...p1.position.clone().sub(p0.position).toArray(),
  54969. ]);
  54970. azimuth.centerToTarget.position.copy(p0.position);
  54971. azimuth.centerToTarget.geometry.verticesNeedUpdate = true;
  54972. azimuth.centerToTarget.geometry.computeBoundingSphere();
  54973. azimuth.centerToTarget.computeLineDistances();
  54974. azimuth.centerToTarget.material.resolution.set(width, height);
  54975. // to target ground
  54976. azimuth.centerToTargetground.geometry.setPositions([
  54977. 0, 0, 0,
  54978. p1.position.x - p0.position.x,
  54979. p1.position.y - p0.position.y,
  54980. 0,
  54981. ]);
  54982. azimuth.centerToTargetground.position.copy(p0.position);
  54983. azimuth.centerToTargetground.geometry.verticesNeedUpdate = true;
  54984. azimuth.centerToTargetground.geometry.computeBoundingSphere();
  54985. azimuth.centerToTargetground.computeLineDistances();
  54986. azimuth.centerToTargetground.material.resolution.set(width, height);
  54987. // to north
  54988. azimuth.centerToNorth.geometry.setPositions([
  54989. 0, 0, 0,
  54990. northPos.x - p0.position.x,
  54991. northPos.y - p0.position.y,
  54992. 0,
  54993. ]);
  54994. azimuth.centerToNorth.position.copy(p0.position);
  54995. azimuth.centerToNorth.geometry.verticesNeedUpdate = true;
  54996. azimuth.centerToNorth.geometry.computeBoundingSphere();
  54997. azimuth.centerToNorth.computeLineDistances();
  54998. azimuth.centerToNorth.material.resolution.set(width, height);
  54999. // label
  55000. const radians = Utils.computeAzimuth(p0.position, p1.position, viewer.getProjection());
  55001. let degrees = MathUtils$1.radToDeg(radians);
  55002. if(degrees < 0){
  55003. degrees = 360 + degrees;
  55004. }
  55005. const txtDegrees = `${degrees.toFixed(2)}°`;
  55006. const labelDir = northPos.clone().add(p1.position).multiplyScalar(0.5).sub(p0.position);
  55007. if(labelDir.length() > 0){
  55008. labelDir.z = 0;
  55009. labelDir.normalize();
  55010. const labelVec = labelDir.clone().multiplyScalar(r);
  55011. const labelPos = p0.position.clone().add(labelVec);
  55012. azimuth.label.position.copy(labelPos);
  55013. }
  55014. azimuth.label.setText(txtDegrees);
  55015. let distance = azimuth.label.position.distanceTo(camera.position);
  55016. let pr = Utils.projectedRadius(1, camera, distance, width, height);
  55017. let scale = (70 / pr);
  55018. azimuth.label.scale.set(scale, scale, scale);
  55019. }
  55020. class MeasuringTool extends EventDispatcher{
  55021. constructor (viewer) {
  55022. super();
  55023. this.viewer = viewer;
  55024. this.renderer = viewer.renderer;
  55025. this.viewer.addEventListener('start_inserting_measurement', e => {
  55026. this.viewer.dispatchEvent({
  55027. type: 'cancel_insertions'
  55028. });
  55029. });
  55030. this.showLabels = true;
  55031. this.scene = new Scene();
  55032. this.scene.name = 'scene_measurement';
  55033. //this.light = new THREE.PointLight(0xffffff, 1.0);
  55034. //this.scene.add(this.light);
  55035. this.viewer.inputHandler.registerInteractiveScene(this.scene);
  55036. //this.scene = viewer.overlay//
  55037. this.onRemove = (e) => { e.measurement.dispose();/* this.scene.remove(e.measurement); */};
  55038. this.onAdd = e => {this.scene.add(e.measurement);};
  55039. for(let measurement of viewer.scene.measurements){
  55040. this.onAdd({measurement: measurement});
  55041. }
  55042. viewer.addEventListener('camera_changed',(e)=>{
  55043. if(e.viewport == viewer.mainViewport ) this.update();
  55044. });
  55045. //viewer.addEventListener("update", this.update.bind(this));
  55046. viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this));
  55047. viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
  55048. viewer.scene.addEventListener('measurement_added', this.onAdd);
  55049. viewer.scene.addEventListener('measurement_removed', this.onRemove);
  55050. viewer.addEventListener('resize',this.setSize.bind(this));
  55051. }
  55052. onSceneChange(e){
  55053. if(e.oldScene){
  55054. e.oldScene.removeEventListener('measurement_added', this.onAdd);
  55055. e.oldScene.removeEventListener('measurement_removed', this.onRemove);
  55056. }
  55057. e.scene.addEventListener('measurement_added', this.onAdd);
  55058. e.scene.addEventListener('measurement_removed', this.onRemove);
  55059. }
  55060. createMeasureFromData(data){//add
  55061. const measure = new Measure$1(data);
  55062. if(measure.failBuilded){
  55063. return
  55064. }
  55065. viewer.scene.addMeasurement(measure);
  55066. if(measure.guideLine)measure.guideLine.visible = false;
  55067. return measure
  55068. }
  55069. update(){
  55070. //add
  55071. viewer.scene.measurements.forEach(measure=>{
  55072. let lastIndex = measure.points.length - 1;
  55073. for (let index = 0; index <= lastIndex; index++) {
  55074. let nextIndex = (index + 1 > lastIndex) ? 0 : index + 1;
  55075. let previousIndex = (index === 0) ? lastIndex : index - 1;
  55076. let point = measure.points[index];
  55077. let nextPoint = measure.points[nextIndex];
  55078. let previousPoint = measure.points[previousIndex];
  55079. if(measure.showDistances || measure.labelText){ // edge labels
  55080. let edgeLabel = measure.edgeLabels[index];
  55081. if(edgeLabel.visible){
  55082. measure.setEdgeLabelPos(edgeLabel, point, nextPoint );
  55083. }
  55084. }
  55085. }
  55086. });
  55087. return;
  55088. let camera = this.viewer.scene.getActiveCamera();
  55089. let domElement = this.renderer.domElement;
  55090. let measurements = this.viewer.scene.measurements;
  55091. // make size independant of distance
  55092. let mainLabels = [], subLabels = [];
  55093. for (let measure of measurements) {
  55094. measure.lengthUnit = this.viewer.lengthUnit;
  55095. measure.lengthUnitDisplay = this.viewer.lengthUnitDisplay;
  55096. //measure.update();
  55097. updateAzimuth(this.viewer, measure);
  55098. /* [...measure.markers, ...measure.edgeLabels, measure.areaLabel].forEach(e=>{
  55099. e && e.update()
  55100. }); */
  55101. // labels
  55102. /* let labels = measure.edgeLabels.concat(measure.angleLabels);
  55103. for(let label of labels){
  55104. label.update()
  55105. if(label.elem.hasClass('sub')){
  55106. subLabels.push(label)
  55107. }else{
  55108. mainLabels.push(label)
  55109. }
  55110. }
  55111. // coordinate labels
  55112. for (let j = 0; j < measure.coordinateLabels.length; j++) {
  55113. let label = measure.coordinateLabels[j];
  55114. label.update()
  55115. mainLabels.push(label)
  55116. }
  55117. if(measure.showArea){ // area label
  55118. let label = measure.areaLabel;
  55119. label.update()
  55120. mainLabels.push(label)
  55121. } */
  55122. /* if(measure.showCircle){ // radius label
  55123. let label = measure.circleRadiusLabel;
  55124. let distance = label.position.distanceTo(camera.position);
  55125. let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
  55126. let scale = (70 / pr);
  55127. label.scale.set(scale, scale, scale);
  55128. } */
  55129. if(!this.showLabels){
  55130. const labels = [
  55131. ...measure.sphereLabels,
  55132. ...measure.angleLabels,
  55133. measure.circleRadiusLabel,
  55134. ];
  55135. for(const label of labels){
  55136. label.visible = false;
  55137. }
  55138. }
  55139. }
  55140. //this.updateLabelZIndex([{labels:subLabels},{labels:mainLabels}])
  55141. }
  55142. setSize(e){ //e.resolution
  55143. /* if(Measure.lineMats){
  55144. for(var m in Measure.lineMats){
  55145. Measure.lineMats[m].resolution.set(e.canvasWidth, e.canvasHeight);
  55146. }
  55147. }
  55148. if(Measure.sphereMats){
  55149. for(var s in Measure.sphereMats){
  55150. Measure.sphereMats[s].uniforms.resolution.value.set(e.canvasWidth, e.canvasHeight);
  55151. }
  55152. }
  55153. for (let measure of this.viewer.scene.measurements) {
  55154. measure.edgeLabels.concat(measure.areaLabel).forEach(label=>{
  55155. label.sprite.material.uniforms.resolution.value.set(e.canvasWidth, e.canvasHeight);
  55156. })
  55157. } */
  55158. }
  55159. updateLabelZIndex(group){//[{labels:[]},{}] 顺序按照z-index低到高
  55160. group.forEach((e,i)=>{
  55161. e.base = group[i-1] ? group[i-1].base + group[i-1].labels.length : 0;
  55162. var labels = e.labels.sort((a,b)=>{
  55163. return b.pos2d.z - a.pos2d.z
  55164. });
  55165. labels.forEach((label,index)=>{
  55166. $(label.elem).css('z-index', e.base+index);
  55167. });
  55168. });
  55169. }
  55170. editStateChange(e){
  55171. //console.log("editStateChange" , e.state)
  55172. let state = e.state;
  55173. if(!state){
  55174. state = viewer.scene.measurements.some(e=>e.isEditing);
  55175. }
  55176. if(state){
  55177. viewer.dispatchEvent({type:"measureMovePoint"});//重新激活reticule状态
  55178. }else {
  55179. viewer.dispatchEvent({type:"endMeasureMove"});
  55180. }
  55181. //this.editing =
  55182. }
  55183. startInsertion (args = {}, callback, cancelFun) {
  55184. let domElement = this.viewer.renderer.domElement;
  55185. let measure = new Measure$1(args);
  55186. this.scene.add(measure);
  55187. measure.isNew = true;
  55188. this.viewer.dispatchEvent({
  55189. type: 'start_inserting_measurement',
  55190. measure: measure
  55191. });
  55192. measure.addEventListener('editStateChange', this.editStateChange.bind(this));
  55193. measure.editStateChange(true);
  55194. let timer;
  55195. let endDragFun = (e) => {
  55196. let length = measure.points.length;
  55197. if (e.button == MOUSE.LEFT || e.isTouch) {
  55198. if (length >= measure.maxMarkers) {
  55199. end({finish:true});
  55200. }else {
  55201. var marker = measure.addMarker({point:measure.points[length - 1].clone()});
  55202. if(args.isRect && measure.markers.length == 3){//marker全可见
  55203. measure.addMarker({point:measure.points[0].clone()});
  55204. }else {
  55205. measure.markers[length].visible = false;
  55206. measure.edges[length].visible = false;
  55207. }
  55208. measure.edges[length-1].visible = true;
  55209. measure.markers[length-1].visible = true;
  55210. marker.isDragging = true;
  55211. console.log('continueDrag' , marker.uuid);
  55212. measure.continueDrag(marker, e);
  55213. }
  55214. } else if (e.button === MOUSE.RIGHT ) { //触屏怎么取消?
  55215. if(e.pressDistance < Potree.config.clickMaxDragDis){//非拖拽的话
  55216. var isIntersectSelf = measure.atPlane && measure.closed && !measure.isRect && measure.point2dInfo && measure.intersectSelf(measure.point2dInfo.points2d.slice(0,measure.point2dInfo.points2d.length-1));//检测除了最后一个点的相交情况
  55217. if(!isIntersectSelf)end(e);
  55218. else measure.continueDrag(null, e);
  55219. }else measure.continueDrag(null, e);
  55220. }
  55221. };
  55222. let end = (e={}) => {//确定、结束
  55223. if(!measure.isNew )return
  55224. if(args.minMarkers != void 0 ){
  55225. if(!e.finish && measure.markers.length<=args.minMarkers ){//右键 当个数不够时取消
  55226. //this.viewer.scene.removeMeasurement(measure)
  55227. //重新开始画
  55228. if(measure.markers.length>0){
  55229. measure.markers[0].removeEventListener('mousedown',end);
  55230. measure.reDraw();
  55231. this.viewer.addEventListener('global_click', click, {importance:10});
  55232. measure.editStateChange(true);
  55233. }
  55234. return
  55235. /* if(!Potree.settings.isOfficial) this.viewer.scene.removeMeasurement(measure)
  55236. else if(e.drag){ //正式版本不允许右键退出, 继续
  55237. continueDrag(e.drag.object)
  55238. measure.editStateChange(true)
  55239. return
  55240. } */
  55241. }
  55242. }
  55243. if (/* !e.finish&& */ measure.markers.length > args.minMarkers) {
  55244. measure.removeMarker(measure.points.length - 1);
  55245. measure.markers[0].removeEventListener('mouseover', mouseover);
  55246. measure.markers[0].removeEventListener('mouseleave', mouseleave);
  55247. measure.markers[0].removeEventListener('click'/* 'mousedown' */,Exit);
  55248. if(e.byClickMarker && measure.markers.length > args.minMarkers){//通过点击第一个marker而结束的话,会多一个marker
  55249. measure.removeMarker(measure.points.length - 1);
  55250. }
  55251. }
  55252. measure.isNew = false;
  55253. let length = measure.points.length;
  55254. if(length){
  55255. measure.markers[length-1].visible = true;
  55256. measure.edges[length-1].visible = !!measure.closed;
  55257. measure.markers.forEach(marker=>{marker.dispatchEvent('addHoverEvent'); });
  55258. measure.edges.forEach(edge=>{edge.dispatchEvent('addHoverEvent'); });
  55259. measure.update();//update last edgeLabel
  55260. }
  55261. clearTimeout(timer);
  55262. this.viewer.removeEventListener('cancel_insertions', Exit);
  55263. //pressExit && this.viewer.inputHandler.removeEventListener('keydown', pressExit);
  55264. this.viewer.removeEventListener('global_click', click);
  55265. this.viewer.removeEventListener('global_touchstart', click );
  55266. this.viewer.removeEventListener('global_mousemove', ifAtWrongPlace);
  55267. viewer.dispatchEvent({
  55268. type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
  55269. });
  55270. viewer.inputHandler.dispatchEvent({type:'isMeasuring', v:false, cause:'stopInsertion'} );
  55271. viewer.controls.setEnable(true);
  55272. //var isIntersectSelf = measure.atPlane && measure.closed && !measure.isRect && measure.point2dInfo && measure.intersectSelf(measure.point2dInfo.points2d.slice(0,measure.point2dInfo.points2d.length-1))//检测除了最后一个点的相交情况
  55273. var isIntersectSelf = measure.atPlane && measure.closed && !measure.isRect && measure.point2dInfo && measure.intersectSelf(measure.point2dInfo.points2d);
  55274. if(isIntersectSelf) return cancelFun && cancelFun() //请求删除,不重建
  55275. e.remove || callback && callback();
  55276. /* this.viewer.dispatchEvent({
  55277. type: 'finish_inserting_measurement',
  55278. measure: measure
  55279. }); */
  55280. };
  55281. measure.addEventListener('finish', end); //完成
  55282. let Exit = (e)=>{//强制退出
  55283. if(e.measure && e.measure != measure || !viewer.scene.measurements.includes(measure) || !measure.isNew){
  55284. return;//若指定了退出的measure但和该measure不一致,就返回
  55285. }
  55286. if(e.remove){
  55287. viewer.scene.removeMeasurement(measure);
  55288. }
  55289. measure.editStateChange(false);
  55290. measure.cannotConfirmNormal = false; //一些dropMarker中的句子
  55291. measure.guideLine && (measure.guideLine.visible = false);
  55292. /*
  55293. if(this.viewer.inputHandler.drag && !e.remove ){//还未触发drop的话
  55294. this.viewer.inputHandler.drag.object.dispatchEvent({ //这句会导致又增一个marker
  55295. type: 'drop',
  55296. drag: this.viewer.inputHandler.drag,
  55297. viewer: this.viewer,
  55298. pressDistance:0,
  55299. button : THREE.MOUSE.RIGHT
  55300. });
  55301. } else {*///未结束时添加新的measure时会触发
  55302. end({finish:true, remove:e.remove, byClickMarker: e.type == 'click'});
  55303. //}
  55304. this.viewer.inputHandler.drag && (this.viewer.inputHandler.drag.object = null);
  55305. };
  55306. this.viewer.addEventListener('cancel_insertions', Exit);
  55307. /*let pressExit
  55308. if(!Potree.settings.isOfficial){
  55309. pressExit = (e)=>{
  55310. if(e.keyCode == 27){//Esc
  55311. //Exit()
  55312. //怎么模拟右键???//现由前端发出
  55313. }
  55314. }
  55315. this.viewer.inputHandler.addEventListener('keydown', pressExit)
  55316. } */
  55317. let mouseover = (e) => {
  55318. measure.setMarkerSelected(e.object, 'hover', 'single');
  55319. };
  55320. let mouseleave = (e) => {
  55321. measure.setMarkerSelected(e.object, 'unhover', 'single');
  55322. };
  55323. let isMobile = browser.isMobile();
  55324. let click = (e)=>{//一旦点击就立刻增加两marker
  55325. if(ifAtWrongPlace(e))return
  55326. if(e.clickElement || e.drag.object)return //如点击label时focusOnObject, 或拖拽marker
  55327. if(e.button === MOUSE.RIGHT )return
  55328. if(e.type == 'global_touchstart' && e.hoveredElement && e.hoveredElement.object.parent instanceof Measure$1 ){
  55329. return //点到测量线时要focus测量线而不是画新线
  55330. }
  55331. if(isMobile){
  55332. viewer.controls.setEnable(false);
  55333. }
  55334. var I = e.intersect && (/* e.intersect.orthoIntersect || */e.intersect.location);
  55335. if(!I){
  55336. return measure.dispatchEvent('intersectNoPointcloud')
  55337. }
  55338. var atMap = e.drag.dragViewport.name == 'mapViewport';
  55339. //在地图上测量的首个点按楼层高度(暂时先只按mainViewport相机高度吧,但navvis是按楼层,画在楼层的地面上,可能因为平面图显示的是楼层近地面),
  55340. if(atMap){
  55341. I = I.clone().setZ(viewer.mainViewport.camera.position.z );
  55342. }
  55343. var marker = measure.addMarker({point:I});
  55344. marker.isDragging = true;
  55345. this.viewer.inputHandler.startDragging(marker , {endDragFun, notPressMouse:!isMobile} ); //notPressMouse代表不是通过按下鼠标来拖拽
  55346. e.drag = this.viewer.inputHandler.drag;
  55347. e.drag.endDragFun = endDragFun;
  55348. e.drag.notPressMouse = !isMobile;
  55349. //if(!measure.dragMarker(e) || !measure.dropMarker(e))return
  55350. measure.dragMarker(e);
  55351. measure.dropMarker(e);
  55352. this.viewer.inputHandler.drag = null; //否则会继续拖拽
  55353. if(measure.maxMarkers > 1 ){
  55354. measure.markers[1].visible = false;
  55355. measure.edges[1].visible = false;
  55356. }
  55357. if(measure.closed && !measure.isRect){
  55358. measure.markers[0].addEventListener('mouseover', mouseover);
  55359. measure.markers[0].addEventListener('mouseleave', mouseleave);
  55360. measure.markers[0].addEventListener('click'/* 'mousedown' */,Exit); //点击到第一个marker就结束
  55361. }
  55362. this.viewer.removeEventListener('global_click', click);///* global_drop */
  55363. this.viewer.removeEventListener('global_touchstart', click );//add importance
  55364. measure.dispatchEvent('firstClick');
  55365. measure.beginAddTime = Date.now();
  55366. //console.log('measure clicked')
  55367. e.consume && e.consume();
  55368. return {stopContinue:true}//防止继续执行别的侦听,如flytopano
  55369. };
  55370. //点击第n下拥有n+1个marker, n>0
  55371. viewer.inputHandler.dispatchEvent({type: 'isMeasuring', v: true, cause:'startInsertion'});
  55372. if( isMobile ){
  55373. this.viewer.addEventListener('global_touchstart', click, {importance:10});//add importance
  55374. }else {
  55375. this.viewer.addEventListener('global_click', click, {importance:10});//add importance
  55376. }
  55377. let ifAtWrongPlace = (e)=>{
  55378. if(measure.unableDragAtMap && e.hoverViewport.name == 'mapViewport' ){
  55379. if(e.isTouch){
  55380. viewer.dispatchEvent({type:'reticule_forbit', v:true});
  55381. }else {
  55382. viewer.dispatchEvent({
  55383. type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
  55384. });
  55385. }
  55386. return true
  55387. }else {
  55388. if(e.isTouch){
  55389. viewer.dispatchEvent({type:'reticule_forbit',v:false});
  55390. }else {
  55391. viewer.dispatchEvent({
  55392. type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
  55393. });
  55394. }
  55395. }
  55396. };
  55397. if(measure.unableDragAtMap){
  55398. this.viewer.addEventListener('global_mousemove', ifAtWrongPlace);
  55399. }
  55400. this.viewer.scene.addMeasurement(measure);
  55401. return measure;
  55402. }
  55403. render(o={}){
  55404. if(this.scene.children.length == 0)return
  55405. Potree.Utils.setCameraLayers(o.camera, ['measure']);
  55406. if(o.screenshot && this.viewer.ssaaRenderPass.enabled){ //抗锯齿
  55407. this.viewer.ssaaRenderPass.sampleLevel = 4;
  55408. this.viewer.composer.render(this.scene, o.camera );
  55409. /* viewer.scene.measurements.forEach(e=>{ //隐藏除了label以外的
  55410. e.children.forEach((c)=>{
  55411. if(!(c instanceof TextSprite)){
  55412. c.visible = false
  55413. }
  55414. })
  55415. }) */
  55416. }else {
  55417. this.viewer.renderer.render(this.scene, o.camera );
  55418. }
  55419. }
  55420. };
  55421. class ProfileTool extends EventDispatcher$1 {
  55422. constructor (viewer) {
  55423. super();
  55424. this.viewer = viewer;
  55425. this.renderer = viewer.renderer;
  55426. this.addEventListener('start_inserting_profile', e => {
  55427. this.viewer.dispatchEvent({
  55428. type: 'cancel_insertions'
  55429. });
  55430. });
  55431. this.scene = new Scene();
  55432. this.scene.name = 'scene_profile';
  55433. this.light = new PointLight(0xffffff, 1.0);
  55434. this.scene.add(this.light);
  55435. this.viewer.inputHandler.registerInteractiveScene(this.scene);
  55436. this.onRemove = e => this.scene.remove(e.profile);
  55437. this.onAdd = e => this.scene.add(e.profile);
  55438. for(let profile of viewer.scene.profiles){
  55439. this.onAdd({profile: profile});
  55440. }
  55441. viewer.addEventListener("update", this.update.bind(this));
  55442. viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this));
  55443. viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
  55444. viewer.scene.addEventListener('profile_added', this.onAdd);
  55445. viewer.scene.addEventListener('profile_removed', this.onRemove);
  55446. }
  55447. onSceneChange(e){
  55448. if(e.oldScene){
  55449. e.oldScene.removeEventListeners('profile_added', this.onAdd);
  55450. e.oldScene.removeEventListeners('profile_removed', this.onRemove);
  55451. }
  55452. e.scene.addEventListener('profile_added', this.onAdd);
  55453. e.scene.addEventListener('profile_removed', this.onRemove);
  55454. }
  55455. startInsertion (args = {}) {
  55456. let domElement = this.viewer.renderer.domElement;
  55457. let profile = new Profile();
  55458. profile.name = args.name || 'Profile';
  55459. this.dispatchEvent({
  55460. type: 'start_inserting_profile',
  55461. profile: profile
  55462. });
  55463. this.scene.add(profile);
  55464. let cancel = {
  55465. callback: null
  55466. };
  55467. let insertionCallback = (e) => {
  55468. if(e.button === MOUSE.LEFT){
  55469. if(profile.points.length <= 1){
  55470. let camera = this.viewer.scene.getActiveCamera();
  55471. let distance = camera.position.distanceTo(profile.points[0]);
  55472. let clientSize = this.viewer.renderer.getSize(new Vector2());
  55473. let pr = Utils.projectedRadius(1, camera, distance, clientSize.width, clientSize.height);
  55474. let width = (10 / pr);
  55475. profile.setWidth(width);
  55476. }
  55477. profile.addMarker(profile.points[profile.points.length - 1].clone());
  55478. this.viewer.inputHandler.startDragging(
  55479. profile.spheres[profile.spheres.length - 1]);
  55480. } else if (e.button === MOUSE.RIGHT) {
  55481. cancel.callback();
  55482. }
  55483. };
  55484. cancel.callback = e => {
  55485. profile.removeMarker(profile.points.length - 1);
  55486. domElement.removeEventListener('mouseup', insertionCallback, false);
  55487. this.viewer.removeEventListener('cancel_insertions', cancel.callback);
  55488. };
  55489. this.viewer.addEventListener('cancel_insertions', cancel.callback);
  55490. domElement.addEventListener('mouseup', insertionCallback, false);
  55491. profile.addMarker(new Vector3(0, 0, 0));
  55492. this.viewer.inputHandler.startDragging(
  55493. profile.spheres[profile.spheres.length - 1]);
  55494. this.viewer.scene.addProfile(profile);
  55495. return profile;
  55496. }
  55497. update(){
  55498. let camera = this.viewer.scene.getActiveCamera();
  55499. let profiles = this.viewer.scene.profiles;
  55500. let renderAreaSize = this.viewer.renderer.getSize(new Vector2());
  55501. let clientWidth = renderAreaSize.width;
  55502. let clientHeight = renderAreaSize.height;
  55503. this.light.position.copy(camera.position);
  55504. // make size independant of distance
  55505. for(let profile of profiles){
  55506. for(let sphere of profile.spheres){
  55507. let distance = camera.position.distanceTo(sphere.getWorldPosition(new Vector3()));
  55508. let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
  55509. let scale = (15 / pr);
  55510. sphere.scale.set(scale, scale, scale);
  55511. }
  55512. }
  55513. }
  55514. render(){
  55515. this.viewer.renderer.render(this.scene, this.viewer.scene.getActiveCamera());
  55516. }
  55517. }
  55518. class ScreenBoxSelectTool extends EventDispatcher$1{
  55519. constructor(viewer){
  55520. super();
  55521. this.viewer = viewer;
  55522. this.scene = new Scene();
  55523. viewer.addEventListener("update", this.update.bind(this));
  55524. viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this));
  55525. viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
  55526. }
  55527. onSceneChange(scene){
  55528. console.log("scene changed");
  55529. }
  55530. startInsertion(){
  55531. let domElement = this.viewer.renderer.domElement;
  55532. let volume = new BoxVolume();
  55533. volume.position.set(12345, 12345, 12345);
  55534. volume.showVolumeLabel = false;
  55535. volume.visible = false;
  55536. volume.update();
  55537. this.viewer.scene.addVolume(volume);
  55538. this.importance = 10;
  55539. let selectionBox = $(`<div style="position: absolute; border: 2px solid white; pointer-events: none; border-style:dashed"></div>`);
  55540. $(domElement.parentElement).append(selectionBox);
  55541. selectionBox.css("right", "10px");
  55542. selectionBox.css("bottom", "10px");
  55543. let drag = e =>{
  55544. volume.visible = true;
  55545. let mStart = e.drag.start;
  55546. let mEnd = e.drag.end;
  55547. let box2D = new Box2();
  55548. box2D.expandByPoint(mStart);
  55549. box2D.expandByPoint(mEnd);
  55550. selectionBox.css("left", `${box2D.min.x}px`);
  55551. selectionBox.css("top", `${box2D.min.y}px`);
  55552. selectionBox.css("width", `${box2D.max.x - box2D.min.x}px`);
  55553. selectionBox.css("height", `${box2D.max.y - box2D.min.y}px`);
  55554. let camera = e.viewer.scene.getActiveCamera();
  55555. let size = e.viewer.renderer.getSize(new Vector2());
  55556. let frustumSize = new Vector2(
  55557. camera.right - camera.left,
  55558. camera.top - camera.bottom);
  55559. let screenCentroid = new Vector2().addVectors(e.drag.end, e.drag.start).multiplyScalar(0.5);
  55560. let ray = Utils.mouseToRay(screenCentroid, camera, size.width, size.height);
  55561. let diff = new Vector2().subVectors(e.drag.end, e.drag.start);
  55562. diff.divide(size).multiply(frustumSize);
  55563. volume.position.copy(ray.origin);
  55564. volume.up.copy(camera.up);
  55565. volume.rotation.copy(camera.rotation);
  55566. volume.scale.set(diff.x, diff.y, 1000 * 100);
  55567. e.consume();
  55568. };
  55569. let drop = e => {
  55570. this.importance = 0;
  55571. $(selectionBox).remove();
  55572. this.viewer.inputHandler.deselectAll();
  55573. this.viewer.inputHandler.toggleSelection(volume);
  55574. let camera = e.viewer.scene.getActiveCamera();
  55575. let size = e.viewer.renderer.getSize(new Vector2());
  55576. let screenCentroid = new Vector2().addVectors(e.drag.end, e.drag.start).multiplyScalar(0.5);
  55577. let ray = Utils.mouseToRay(screenCentroid, camera, size.width, size.height);
  55578. let line = new Line3(ray.origin, new Vector3().addVectors(ray.origin, ray.direction));
  55579. this.removeEventListener("drag", drag);
  55580. this.removeEventListener("drop", drop);
  55581. let allPointsNear = [];
  55582. let allPointsFar = [];
  55583. // TODO support more than one point cloud
  55584. for(let pointcloud of this.viewer.scene.pointclouds){
  55585. if(!pointcloud.visible){
  55586. continue;
  55587. }
  55588. let volCam = camera.clone();
  55589. volCam.left = -volume.scale.x / 2;
  55590. volCam.right = +volume.scale.x / 2;
  55591. volCam.top = +volume.scale.y / 2;
  55592. volCam.bottom = -volume.scale.y / 2;
  55593. volCam.near = -volume.scale.z / 2;
  55594. volCam.far = +volume.scale.z / 2;
  55595. volCam.rotation.copy(volume.rotation);
  55596. volCam.position.copy(volume.position);
  55597. volCam.updateMatrix();
  55598. volCam.updateMatrixWorld();
  55599. volCam.updateProjectionMatrix();
  55600. volCam.matrixWorldInverse.copy(volCam.matrixWorld).invert();
  55601. let ray = new Ray(volCam.getWorldPosition(new Vector3()), volCam.getWorldDirection(new Vector3()));
  55602. let rayInverse = new Ray(
  55603. ray.origin.clone().add(ray.direction.clone().multiplyScalar(volume.scale.z)),
  55604. ray.direction.clone().multiplyScalar(-1));
  55605. let pickerSettings = {
  55606. width: 8,
  55607. height: 8,
  55608. pickWindowSize: 8,
  55609. all: true,
  55610. pickClipped: true,
  55611. pointSizeType: PointSizeType.FIXED,
  55612. pointSize: 1};
  55613. let pointsNear = pointcloud.pick(viewer, volCam, ray, pickerSettings);
  55614. volCam.rotateX(Math.PI);
  55615. volCam.updateMatrix();
  55616. volCam.updateMatrixWorld();
  55617. volCam.updateProjectionMatrix();
  55618. volCam.matrixWorldInverse.copy(volCam.matrixWorld).invert();
  55619. let pointsFar = pointcloud.pick(viewer, volCam, rayInverse, pickerSettings);
  55620. allPointsNear.push(...pointsNear);
  55621. allPointsFar.push(...pointsFar);
  55622. }
  55623. if(allPointsNear.length > 0 && allPointsFar.length > 0){
  55624. let viewLine = new Line3(ray.origin, new Vector3().addVectors(ray.origin, ray.direction));
  55625. let closestOnLine = allPointsNear.map(p => viewLine.closestPointToPoint(p.position, false, new Vector3()));
  55626. let closest = closestOnLine.sort( (a, b) => ray.origin.distanceTo(a) - ray.origin.distanceTo(b))[0];
  55627. let farthestOnLine = allPointsFar.map(p => viewLine.closestPointToPoint(p.position, false, new Vector3()));
  55628. let farthest = farthestOnLine.sort( (a, b) => ray.origin.distanceTo(b) - ray.origin.distanceTo(a))[0];
  55629. let distance = closest.distanceTo(farthest);
  55630. let centroid = new Vector3().addVectors(closest, farthest).multiplyScalar(0.5);
  55631. volume.scale.z = distance * 1.1;
  55632. volume.position.copy(centroid);
  55633. }
  55634. volume.clip = true;
  55635. };
  55636. this.addEventListener("drag", drag);
  55637. this.addEventListener("drop", drop);
  55638. viewer.inputHandler.addInputListener(this);
  55639. return volume;
  55640. }
  55641. update(e){
  55642. //console.log(e.delta)
  55643. }
  55644. render(){
  55645. this.viewer.renderer.render(this.scene, this.viewer.scene.getActiveCamera());
  55646. }
  55647. }
  55648. class SpotLightHelper$1 extends Object3D{
  55649. constructor(light, color){
  55650. super();
  55651. this.light = light;
  55652. this.color = color;
  55653. //this.up.set(0, 0, 1);
  55654. this.updateMatrix();
  55655. this.updateMatrixWorld();
  55656. { // SPHERE
  55657. let sg = new SphereGeometry(1, 32, 32);
  55658. let sm = new MeshNormalMaterial();
  55659. this.sphere = new Mesh(sg, sm);
  55660. this.sphere.scale.set(0.5, 0.5, 0.5);
  55661. this.add(this.sphere);
  55662. }
  55663. { // LINES
  55664. let positions = new Float32Array([
  55665. +0, +0, +0, +0, +0, -1,
  55666. +0, +0, +0, -1, -1, -1,
  55667. +0, +0, +0, +1, -1, -1,
  55668. +0, +0, +0, +1, +1, -1,
  55669. +0, +0, +0, -1, +1, -1,
  55670. -1, -1, -1, +1, -1, -1,
  55671. +1, -1, -1, +1, +1, -1,
  55672. +1, +1, -1, -1, +1, -1,
  55673. -1, +1, -1, -1, -1, -1,
  55674. ]);
  55675. let geometry = new BufferGeometry();
  55676. geometry.setAttribute("position", new BufferAttribute(positions, 3));
  55677. let material = new LineBasicMaterial();
  55678. this.frustum = new LineSegments(geometry, material);
  55679. this.add(this.frustum);
  55680. }
  55681. this.update();
  55682. }
  55683. update(){
  55684. this.light.updateMatrix();
  55685. this.light.updateMatrixWorld();
  55686. let position = this.light.position;
  55687. let target = new Vector3().addVectors(
  55688. this.light.position, this.light.getWorldDirection(new Vector3()).multiplyScalar(-1));
  55689. let quat = new Quaternion().setFromRotationMatrix(
  55690. new Matrix4().lookAt( position, target, new Vector3( 0, 0, 1 ) )
  55691. );
  55692. this.setRotationFromQuaternion(quat);
  55693. this.position.copy(position);
  55694. let coneLength = (this.light.distance > 0) ? this.light.distance : 1000;
  55695. let coneWidth = coneLength * Math.tan( this.light.angle * 0.5 );
  55696. this.frustum.scale.set(coneWidth, coneWidth, coneLength);
  55697. }
  55698. }
  55699. class History extends EventDispatcher{
  55700. constructor(o){
  55701. super();
  55702. this.undoList = [];
  55703. this.redoList = [];
  55704. this.applyData = o.applyData; //应用数据的方法
  55705. this.getData = o.getData; //获取数据的方法
  55706. this.dataBefore;
  55707. }
  55708. undo(){//回退
  55709. let length = this.undoList.length;
  55710. if(length>0){
  55711. let last = this.undoList.pop();
  55712. this.applyData && this.applyData(last.before);
  55713. this.redoList.push(last);
  55714. this.dispatchEvent('undo');
  55715. //console.log('undo',last)
  55716. }
  55717. }
  55718. redo(){//撤销回退
  55719. let length = this.undoList.length;
  55720. let last = this.redoList.pop();
  55721. if(last){
  55722. //注意:每行的顺序不能乱
  55723. this.undoList.push(last);
  55724. this.applyData && this.applyData(last.after);
  55725. this.dispatchEvent('redo');
  55726. //console.log('redo',last)
  55727. }
  55728. }
  55729. beforeChange(o){//在变化之前(可能执行好几次直到变化完,但只有第一次有效)。 o的内容完全根据getData怎么定义
  55730. if(!this.dataBefore){
  55731. let data = this.getData(o);
  55732. this.dataBefore = data;
  55733. }
  55734. }
  55735. afterChange(o){//变化结束,从beforeChange到此算一次操作。
  55736. if(this.dataBefore){
  55737. this.writeIn({before:this.dataBefore, after:this.getData(o)} ); //写入某物体变化前和变化后的状态
  55738. this.dataBefore = null;
  55739. }
  55740. }
  55741. writeIn(data ){
  55742. this.redoList.length = 0; //一旦录入新的操作,就不允许undo了
  55743. this.undoList.push(data );
  55744. //console.log('新增undo', data)
  55745. }
  55746. clear(){
  55747. this.redoList.length = 0;
  55748. this.undoList.length = 0;
  55749. this.dataBefore = null;
  55750. }
  55751. }
  55752. //问题:如何转换到世界坐标?(缩放方向有bug。)
  55753. //add-------------------------------------
  55754. const OpaWhenNotSelect = 0.6;
  55755. const ScaleRatio = 3;
  55756. const OutlineColor = 0x666666;
  55757. //----------------------------------------
  55758. const hideFocusHandles = true;//add
  55759. class TransformationTool extends EventDispatcher{
  55760. constructor(viewer ) {
  55761. super();
  55762. this.viewer = viewer;
  55763. this.modesEnabled = {};//add
  55764. this.style = 'singleMode'; //建mesh时按照singleModes建的
  55765. this.scene = new Scene();
  55766. this.selection = [];
  55767. this.pivot = new Vector3();
  55768. this.dragging = false;
  55769. this.showPickVolumes = false;
  55770. this.viewer.inputHandler.registerInteractiveScene(this.scene);
  55771. this.viewer.inputHandler.addEventListener('selection_changed', (e) => {
  55772. /* for(let selected of this.selection){ //若不删除,应该会穿过选中的物体选到别的而不是取消选择
  55773. this.viewer.inputHandler.blacklist.delete(selected);
  55774. } */
  55775. this.selection = e.selection;
  55776. /* for(let selected of this.selection){
  55777. this.viewer.inputHandler.blacklist.add(selected);
  55778. } */
  55779. });
  55780. this.viewer.addEventListener('global_touchstart',(e)=>{ //add
  55781. this.update();
  55782. });
  55783. this.viewer.addEventListener('global_mousemove',(e)=>{ //add
  55784. this.onPointerMove();
  55785. });
  55786. let red = Potree.config.axis.x.color;
  55787. let green = Potree.config.axis.y.color;
  55788. let blue = Potree.config.axis.z.color;
  55789. let white = Potree.config.axis.xyz.color;
  55790. this.activeHandle = null;
  55791. this.scaleHandles = {
  55792. "scale.x+": {name: "scale.x+", node: new Object3D(), color: red, alignment: [+1, +0, +0]},
  55793. "scale.x-": {name: "scale.x-", node: new Object3D(), color: red, alignment: [-1, +0, +0]},
  55794. "scale.y+": {name: "scale.y+", node: new Object3D(), color: green, alignment: [+0, +1, +0]},
  55795. "scale.y-": {name: "scale.y-", node: new Object3D(), color: green, alignment: [+0, -1, +0]},
  55796. "scale.z+": {name: "scale.z+", node: new Object3D(), color: blue, alignment: [+0, +0, +1]},
  55797. "scale.z-": {name: "scale.z-", node: new Object3D(), color: blue, alignment: [+0, +0, -1]},
  55798. "lines": {name:'lines', node: new Object3D(), dontScale:true }//add
  55799. };
  55800. this.focusHandles = {
  55801. "focus.x+": {name: "focus.x+", node: new Object3D(), color: red, alignment: [+1, +0, +0]},
  55802. "focus.x-": {name: "focus.x-", node: new Object3D(), color: red, alignment: [-1, +0, +0]},
  55803. "focus.y+": {name: "focus.y+", node: new Object3D(), color: green, alignment: [+0, +1, +0]},
  55804. "focus.y-": {name: "focus.y-", node: new Object3D(), color: green, alignment: [+0, -1, +0]},
  55805. "focus.z+": {name: "focus.z+", node: new Object3D(), color: blue, alignment: [+0, +0, +1]},
  55806. "focus.z-": {name: "focus.z-", node: new Object3D(), color: blue, alignment: [+0, +0, -1]},
  55807. };
  55808. this.translationHandles = {
  55809. "translation.x": {name: "translation.x", node: new Object3D(), color: red, alignment: [1, 0, 0]},
  55810. "translation.y": {name: "translation.y", node: new Object3D(), color: green, alignment: [0, 1, 0]},
  55811. "translation.z": {name: "translation.z", node: new Object3D(), color: blue, alignment: [0, 0, 1]},
  55812. //add
  55813. 'translation.xyz':{name: "translation.xyz", node: new Object3D(),color: white, alignment: [0, 0, 0], alignment2: [1, 1, 1]},
  55814. 'translation.plane.xy':{name: "translation.plane.xy", node: new Object3D(),color: blue,alignment: [0, 0, 1], alignment2: [1, 1, 0]},
  55815. 'translation.plane.yz':{name: "translation.plane.yz", node: new Object3D(),color: red, alignment: [1, 0, 0], alignment2: [0, 1, 1]},
  55816. 'translation.plane.xz':{name: "translation.plane.xz", node: new Object3D(),color: green, alignment: [0, 1, 0], alignment2: [1, 0, 1]},
  55817. };
  55818. this.rotationHandles = {
  55819. "rotation.x": {name: "rotation.x", node: new Object3D(), color: red, alignment: [1, 0, 0]},
  55820. "rotation.y": {name: "rotation.y", node: new Object3D(), color: green, alignment: [0, 1, 0]},
  55821. "rotation.z": {name: "rotation.z", node: new Object3D(), color: blue, alignment: [0, 0, 1]},
  55822. };
  55823. this.handles = Object.assign({}, this.scaleHandles, hideFocusHandles?{}:this.focusHandles, this.translationHandles, this.rotationHandles);
  55824. this.pickVolumes = [];
  55825. this.initializeScaleHandles();
  55826. this.initializeFocusHandles();
  55827. this.initializeTranslationHandles();
  55828. this.initializeRotationHandles();
  55829. let boxFrameGeometry = new Geometry();
  55830. {
  55831. // bottom
  55832. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  55833. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  55834. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  55835. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  55836. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  55837. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  55838. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  55839. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  55840. // top
  55841. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  55842. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  55843. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  55844. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  55845. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  55846. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  55847. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  55848. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  55849. // sides
  55850. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  55851. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  55852. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  55853. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  55854. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  55855. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  55856. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  55857. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  55858. }
  55859. this.frame = new LineSegments(boxFrameGeometry, new LineBasicMaterial({color: 0xffff00}));
  55860. this.scene.add(this.frame);
  55861. //------------------add-----------------------
  55862. this.setModeEnable(['scale','translation','rotation']);
  55863. Potree.Utils.setObjectLayers(this.scene, 'transformationTool' );
  55864. this.scene.traverse(e=>{
  55865. e.pickDontCheckDis = true; //pick时不需要识别是否在点云之上
  55866. });
  55867. {
  55868. let exist = (object)=>{//是否没被删除(暂时不考虑换了parent)
  55869. while(object.parent){
  55870. object = object.parent;
  55871. }
  55872. if(object instanceof Scene){
  55873. return true
  55874. }
  55875. };
  55876. this.history = new History({ //也可以写到全局,但需要加个判断物品是否存在的函数
  55877. applyData: (data)=>{
  55878. if(exist(data.object)){//viewer.scene.volumes.includes(data.box) //或许还要识别是否matrixAuto
  55879. data.matrix.decompose( data.object.position, data.object.quaternion, data.object.scale );
  55880. }else {
  55881. this.history.undo();//找不到就回退下一个。(直接写这?)
  55882. }
  55883. } ,
  55884. getData:(data)=>{
  55885. return data
  55886. }
  55887. });
  55888. this.addEventListener('transformed', (e)=>{
  55889. let object = viewer.transformationTool.selection[0];
  55890. this.history.beforeChange({object, matrix:e.matrixBefore.clone()} );
  55891. this.viewer.dispatchEvent('content_changed');
  55892. });
  55893. this.addEventListener('stopDrag', (e)=>{
  55894. let object = viewer.transformationTool.selection[0];
  55895. object && this.history.afterChange({object, matrix:object.matrix.clone()} );
  55896. });
  55897. viewer.inputHandler.addEventListener('keydown', (e)=>{
  55898. if(e.keyCode == 90 && e.event.ctrlKey){//Z
  55899. this.history.undo();
  55900. }else if(e.keyCode == 89 && e.event.ctrlKey){//Y
  55901. this.history.redo();
  55902. }
  55903. });
  55904. }
  55905. }
  55906. setModeEnable(enableModes=[] ){//xzw add
  55907. let length=0;
  55908. ['translation','scale','rotation'].forEach(mode=>{
  55909. let handels = this[mode + 'Handles'];
  55910. let enable = enableModes.includes(mode);
  55911. for(let o in handels){
  55912. Potree.Utils.updateVisible(handels[o].node,'modeForce', !!enable);
  55913. }
  55914. this.modesEnabled[mode] = !!enable;
  55915. enable && length++;
  55916. });
  55917. if(this.style == 'singleMode' && length > 1){
  55918. this.changeStyle('mixedModes');
  55919. }else if(this.style == 'mixedModes' && length == 1){
  55920. this.changeStyle('singleMode');
  55921. }
  55922. }
  55923. changeStyle(style){// 切换单个mode & 多个mode混合 风格(因多个混合比较拥挤,需要做调整)
  55924. ['x','y','z'].forEach(axis=>{
  55925. this.translationHandles['translation.'+axis].node.children.forEach(mesh=>{
  55926. if(mesh.name.includes('arrow')){
  55927. Potree.Utils.updateVisible(mesh, 'modeStyle', style == 'singleMode');
  55928. }else if(mesh.name.includes('handle')){
  55929. mesh.material.lineWidth = style == 'singleMode' ? 5 : 8;
  55930. }
  55931. });
  55932. });
  55933. ['xy','yz','xz'].forEach(axis=>{
  55934. let handle = this.translationHandles['translation.plane.'+axis];
  55935. let s = style == 'singleMode' ? 15 : 12;
  55936. handle.node.children[0].scale.set(s,s,s);
  55937. handle.node.children[0].position.fromArray(handle.alignment2).multiplyScalar(s*1.5);
  55938. });
  55939. Potree.Utils.updateVisible(this.scaleHandles['lines'].node, 'modeStyle', style == 'singleMode');
  55940. this.style = style;
  55941. }
  55942. initializeTranslationHandles(){//大改
  55943. let boxGeometry = new BoxGeometry(1, 1, 1);
  55944. let length = 100 , arrowRadius = 4, arrowHeight = 10;
  55945. let arrowGeometry = new CylinderBufferGeometry( 0, arrowRadius, arrowHeight, 12, 1, false );//add 箭头朝(0,1,0)
  55946. let arrowInitialQua = new Quaternion().setFromAxisAngle(new Vector3(1,0,0), -Math.PI/2 );//先将qua旋转到朝向0,0,-1, 因为一般quaternion不设置时默认表示朝向0,0,-1,
  55947. let octahedronGeometry = new OctahedronBufferGeometry( 5, 0 );
  55948. let planeGeometry = new PlaneBufferGeometry( 1, 1 );
  55949. for(let handleName of Object.keys(this.translationHandles)){
  55950. let handle = this.handles[handleName];
  55951. let node = handle.node;
  55952. this.scene.add(node);
  55953. node.name = handleName;//add
  55954. let alignment = new Vector3(...handle.alignment);
  55955. let geometry , mesh, pickVolume, meshScale, pickScale, rotation, position, lookAtPoint, hasPick = true, meshPickable = false, renderOrder;
  55956. let matProp = {
  55957. color: handle.color,
  55958. opacity: OpaWhenNotSelect,
  55959. transparent: true,
  55960. side: handleName.includes('plane') ? DoubleSide : FrontSide
  55961. };
  55962. let material = new MeshBasicMaterial(matProp);
  55963. let pickMaterial = new MeshNormalMaterial({
  55964. opacity: 0.2,
  55965. transparent: true,
  55966. visible: this.showPickVolumes
  55967. });
  55968. if(handleName.includes('xyz') ){
  55969. geometry = octahedronGeometry;
  55970. meshPickable = true;
  55971. renderOrder = 12;
  55972. }else if(handleName.includes('plane') ){
  55973. geometry = planeGeometry;
  55974. meshPickable = true;
  55975. position = new Vector3(...handle.alignment2);
  55976. lookAtPoint = alignment;
  55977. if(handleName.includes('xy') ) {
  55978. }else if(handleName.includes('yz')){
  55979. }else if(handleName.includes('xz')){
  55980. }
  55981. }else {
  55982. geometry = boxGeometry;
  55983. let point = new Vector3(0,0,length/2);//new THREE.Vector3().copy(alignment).multiplyScalar(length/2)
  55984. mesh = LineDraw.createFatLine([point, point.clone().negate()],{lineWidth:5, material: new LineDraw.createFatLineMat(matProp)});
  55985. lookAtPoint = alignment;
  55986. renderOrder = 10;
  55987. pickScale = new Vector3(4, 4, length+arrowHeight*2); //pickScale = new THREE.Vector3(4, 4, 1.2)
  55988. {
  55989. let arrow = new Mesh(arrowGeometry, material);
  55990. arrow.name = `${handleName}.arrow`;
  55991. arrow.renderOrder = 11;
  55992. arrow.position.set( ...handle.alignment).multiplyScalar(length/2+arrowHeight/2);
  55993. arrow.lookAt(0,0,0);
  55994. node.add(arrow);
  55995. let arrow2 = arrow.clone();
  55996. arrow2.position.negate();
  55997. arrow2.lookAt(0,0,0);
  55998. node.add(arrow2);
  55999. arrow.quaternion.multiply(arrowInitialQua); //乘上初始旋转
  56000. arrow2.quaternion.multiply(arrowInitialQua);
  56001. }
  56002. }
  56003. mesh || (mesh = new Mesh(geometry,material));
  56004. mesh.name = `${handleName}.handle`;
  56005. node.add(mesh);
  56006. renderOrder && (mesh.renderOrder = renderOrder);
  56007. meshScale && mesh.scale.copy(meshScale);
  56008. rotation && mesh.rotation.copy(rotation);
  56009. lookAtPoint && mesh.lookAt(lookAtPoint);
  56010. position && mesh.position.copy(position);
  56011. if(!meshPickable && hasPick){
  56012. pickVolume = new Mesh(geometry, pickMaterial);
  56013. pickScale && pickVolume.scale.copy(pickScale);
  56014. }else if(hasPick && meshPickable){
  56015. pickVolume = mesh;
  56016. }
  56017. if(pickVolume){
  56018. if(mesh != pickVolume){
  56019. mesh.add(pickVolume);
  56020. pickVolume.name = `${handleName}.pick_volume`;
  56021. }else {
  56022. pickVolume.name += ' & pick_volume';
  56023. }
  56024. pickVolume.handle = handleName;
  56025. this.pickVolumes.push(pickVolume);
  56026. }
  56027. node.setOpacity = (target) => {
  56028. if(handleName.includes('plane')){
  56029. let more = 1.5; //减掉更多,使min更低,max还是1
  56030. target = 1 - (1-target)*more;
  56031. }
  56032. let opacity = {x: material.opacity};
  56033. let t = new TWEEN.Tween(opacity).to({x: target}, 0);
  56034. t.onUpdate(() => {
  56035. mesh.visible = opacity.x > 0;
  56036. pickVolume && (pickVolume.visible = opacity.x > 0);
  56037. material.opacity = opacity.x;
  56038. mesh.material.opacity = opacity.x;
  56039. //outlineMaterial.opacity = opacity.x;
  56040. pickMaterial.opacity = opacity.x * 0.5;
  56041. });
  56042. t.start();
  56043. };
  56044. pickVolume.addEventListener("drag", (e) => {this.dragTranslationHandle(e);});
  56045. pickVolume.addEventListener("drop", (e) => {this.dropTranslationHandle(e);});
  56046. }
  56047. }
  56048. initializeScaleHandles(){
  56049. let sgSphere = new SphereGeometry(1, 32, 32);
  56050. let sgLowPolySphere = new SphereGeometry(1, 16, 16);
  56051. for(let handleName of Object.keys(this.scaleHandles)){
  56052. let handle = this.scaleHandles[handleName];
  56053. let node = handle.node;
  56054. node.name = handleName;//add
  56055. this.scene.add(node);
  56056. if(handleName == 'lines'){ //add
  56057. ['x','y','z'].forEach(axis=>{
  56058. let handle1_ = this.scaleHandles['scale.'+axis+'+'];
  56059. let handle2_ = this.scaleHandles['scale.'+axis+'-'];
  56060. let line = LineDraw.createFatLine([
  56061. new Vector3().fromArray(handle1_.alignment).multiplyScalar(0.5),
  56062. new Vector3().fromArray(handle2_.alignment).multiplyScalar(0.5) ],
  56063. {color:handle1_.color, lineWidth:4} // , dontAlwaysSeen:true
  56064. );
  56065. node.add(line);
  56066. });
  56067. node.setOpacity = (opacity) => {
  56068. opacity *= 0.6;
  56069. node.children.forEach(e=>e.material.opacity = opacity);
  56070. };
  56071. continue;
  56072. }
  56073. node.position.set(...handle.alignment).multiplyScalar(0.5);
  56074. let material = new MeshBasicMaterial({
  56075. color: handle.color,
  56076. side:DoubleSide,//xzw add
  56077. opacity: OpaWhenNotSelect,
  56078. transparent: true
  56079. });
  56080. let outlineMaterial = new MeshBasicMaterial({
  56081. color: OutlineColor,
  56082. side: BackSide,
  56083. opacity: OpaWhenNotSelect,
  56084. transparent: true});
  56085. let pickMaterial = new MeshNormalMaterial({
  56086. opacity: 0.2,
  56087. transparent: true,
  56088. side:DoubleSide,//xzw add for orthoCam, 缩小画面时因球体放大导致到相机背面去了而看不到球体正面
  56089. visible: this.showPickVolumes});
  56090. let sphere = new Mesh(sgSphere, material);
  56091. sphere.scale.set(5, 5, 5 );
  56092. sphere.name = `${handleName}.handle`;
  56093. node.add(sphere);
  56094. sphere.renderOrder = 10;
  56095. /* let outline = new THREE.Mesh(sgSphere, outlineMaterial);
  56096. outline.scale.set(1.1, 1.1, 1.1);
  56097. outline.name = `${handleName}.outline`;
  56098. sphere.add(outline); */
  56099. let pickSphere = new Mesh(sgLowPolySphere, pickMaterial);
  56100. pickSphere.name = `${handleName}.pick_volume`;
  56101. pickSphere.scale.set(1.5, 1.5, 1.5);
  56102. sphere.add(pickSphere);
  56103. pickSphere.handle = handleName;
  56104. this.pickVolumes.push(pickSphere);
  56105. node.setOpacity = (target) => {
  56106. let opacity = {x: material.opacity};
  56107. let t = new TWEEN.Tween(opacity).to({x: target}, 0); //xzw改 原100毫秒,因为太慢容易选错
  56108. t.onUpdate(() => {
  56109. sphere.visible = opacity.x > 0;
  56110. pickSphere.visible = opacity.x > 0;
  56111. material.opacity = opacity.x;
  56112. outlineMaterial.opacity = opacity.x;
  56113. pickSphere.material.opacity = opacity.x * 0.5;
  56114. });
  56115. t.start();
  56116. };
  56117. pickSphere.addEventListener("drag", (e) => this.dragScaleHandle(e));
  56118. pickSphere.addEventListener("drop", (e) => this.dropScaleHandle(e));
  56119. pickSphere.addEventListener("mouseover", e => {
  56120. //node.setOpacity(1);
  56121. });
  56122. pickSphere.addEventListener("click", e => {
  56123. //e.consume();
  56124. });
  56125. pickSphere.addEventListener("mouseleave", e => {
  56126. //node.setOpacity(OpaWhenNotSelect);
  56127. });
  56128. }
  56129. }
  56130. initializeRotationHandles(){
  56131. let boldAdjust = 2.5;
  56132. let torusGeometry = new TorusGeometry(1.4, boldAdjust * 0.015, 8, 64, Math.PI / 2);
  56133. //let outlineGeometry = new THREE.TorusGeometry(1, boldAdjust * 0.018, 8, 64, Math.PI / 2);
  56134. let pickGeometry = new TorusGeometry(1.4, boldAdjust * 0.06, 6, 4, Math.PI / 2);
  56135. for(let handleName of Object.keys(this.rotationHandles)){
  56136. let handle = this.handles[handleName];
  56137. let node = handle.node;
  56138. this.scene.add(node);
  56139. node.name = handleName;//add
  56140. let material = new MeshBasicMaterial({
  56141. color: handle.color,
  56142. opacity: OpaWhenNotSelect,
  56143. transparent: true
  56144. });
  56145. /* let outlineMaterial = new THREE.MeshBasicMaterial({
  56146. color: OutlineColor,
  56147. side: THREE.BackSide,
  56148. opacity: OpaWhenNotSelect,
  56149. transparent: true
  56150. }); */
  56151. let pickMaterial = new MeshNormalMaterial({
  56152. opacity: 0.2,
  56153. transparent: true,
  56154. visible: this.showPickVolumes
  56155. });
  56156. let box = new Mesh(torusGeometry, material);
  56157. box.name = `${handleName}.handle`;
  56158. box.scale.set(30, 30, 30);
  56159. box.lookAt(new Vector3(...handle.alignment));
  56160. node.add(box);
  56161. handle.translateNode = box;
  56162. /* let outline = new THREE.Mesh(outlineGeometry, outlineMaterial);
  56163. outline.name = `${handleName}.outline`;
  56164. outline.scale.set(1, 1, 1);
  56165. outline.renderOrder = 0;
  56166. box.add(outline);
  56167. */
  56168. let pickVolume = new Mesh(pickGeometry, pickMaterial);
  56169. pickVolume.name = `${handleName}.pick_volume`;
  56170. pickVolume.scale.set(1, 1, 1);
  56171. pickVolume.handle = handleName;
  56172. box.add(pickVolume);
  56173. this.pickVolumes.push(pickVolume);
  56174. node.setOpacity = (target) => {
  56175. let opacity = {x: material.opacity};
  56176. let t = new TWEEN.Tween(opacity).to({x: target}, 0);
  56177. t.onUpdate(() => {
  56178. box.visible = opacity.x > 0;
  56179. pickVolume.visible = opacity.x > 0;
  56180. material.opacity = opacity.x;
  56181. //outlineMaterial.opacity = opacity.x;
  56182. pickMaterial.opacity = opacity.x * 0.5;
  56183. });
  56184. t.start();
  56185. };
  56186. //pickVolume.addEventListener("mouseover", (e) => {
  56187. // //let a = this.viewer.scene.getActiveCamera().getWorldDirection(new THREE.Vector3()).dot(pickVolume.getWorldDirection(new THREE.Vector3()));
  56188. // console.log(pickVolume.getWorldDirection(new THREE.Vector3()));
  56189. //});
  56190. pickVolume.addEventListener("drag", (e) => {this.dragRotationHandle(e);});
  56191. pickVolume.addEventListener("drop", (e) => {this.dropRotationHandle(e);});
  56192. }
  56193. }
  56194. initializeFocusHandles(){
  56195. if(hideFocusHandles)return//add
  56196. //let sgBox = new THREE.BoxGeometry(1, 1, 1);
  56197. let sgPlane = new PlaneGeometry(4, 4, 1, 1);
  56198. let sgLowPolySphere = new SphereGeometry(1, 16, 16);
  56199. let texture = new TextureLoader().load(`${exports.resourcePath}/icons/eye_2.png`);
  56200. for(let handleName of Object.keys(this.focusHandles)){
  56201. let handle = this.focusHandles[handleName];
  56202. let node = handle.node;
  56203. this.scene.add(node);
  56204. let align = handle.alignment;
  56205. node.name = handleName;//add
  56206. //node.lookAt(new THREE.Vector3().addVectors(node.position, new THREE.Vector3(...align)));
  56207. node.lookAt(new Vector3(...align));
  56208. let off = 0.8;
  56209. if(align[0] === 1){
  56210. node.position.set(1, off, -off).multiplyScalar(0.5);
  56211. node.rotation.z = Math.PI / 2;
  56212. }else if(align[0] === -1){
  56213. node.position.set(-1, -off, -off).multiplyScalar(0.5);
  56214. node.rotation.z = Math.PI / 2;
  56215. }else if(align[1] === 1){
  56216. node.position.set(-off, 1, -off).multiplyScalar(0.5);
  56217. node.rotation.set(Math.PI / 2, Math.PI, 0.0);
  56218. }else if(align[1] === -1){
  56219. node.position.set(off, -1, -off).multiplyScalar(0.5);
  56220. node.rotation.set(Math.PI / 2, 0.0, 0.0);
  56221. }else if(align[2] === 1){
  56222. node.position.set(off, off, 1).multiplyScalar(0.5);
  56223. }else if(align[2] === -1){
  56224. node.position.set(-off, off, -1).multiplyScalar(0.5);
  56225. }
  56226. let material = new MeshBasicMaterial({
  56227. color: handle.color,
  56228. opacity: 0,
  56229. transparent: true,
  56230. map: texture
  56231. });
  56232. //let outlineMaterial = new THREE.MeshBasicMaterial({
  56233. // color: 0x000000,
  56234. // side: THREE.BackSide,
  56235. // opacity: 0,
  56236. // transparent: true});
  56237. let pickMaterial = new MeshNormalMaterial({
  56238. //opacity: 0,
  56239. transparent: true,
  56240. visible: this.showPickVolumes});
  56241. let box = new Mesh(sgPlane, material);
  56242. box.name = `${handleName}.handle`;
  56243. box.scale.set(1.5, 1.5, 1.5);
  56244. box.position.set(0, 0, 0);
  56245. box.visible = false;
  56246. node.add(box);
  56247. //handle.focusNode = box;
  56248. //let outline = new THREE.Mesh(sgPlane, outlineMaterial);
  56249. //outline.scale.set(1.4, 1.4, 1.4);
  56250. //outline.name = `${handleName}.outline`;
  56251. //box.add(outline);
  56252. let pickSphere = new Mesh(sgLowPolySphere, pickMaterial);
  56253. pickSphere.name = `${handleName}.pick_volume`;
  56254. pickSphere.scale.set(2, 2, 2);
  56255. box.add(pickSphere);
  56256. pickSphere.handle = handleName;
  56257. this.pickVolumes.push(pickSphere);
  56258. node.setOpacity = (target) => {
  56259. let opacity = {x: material.opacity};
  56260. let t = new TWEEN.Tween(opacity).to({x: target}, 0);
  56261. t.onUpdate(() => {
  56262. pickSphere.visible = opacity.x > 0;
  56263. box.visible = opacity.x > 0;
  56264. material.opacity = opacity.x;
  56265. //outlineMaterial.opacity = opacity.x;
  56266. pickSphere.material.opacity = opacity.x * 0.5;
  56267. });
  56268. t.start();
  56269. };
  56270. //pickSphere.addEventListener("drag", e => {});
  56271. pickSphere.addEventListener("mouseup", e => {
  56272. //e.consume();
  56273. });
  56274. pickSphere.addEventListener("mousedown", e => {
  56275. //e.consume();
  56276. });
  56277. pickSphere.addEventListener("click", e => {
  56278. //e.consume();
  56279. let selected = this.selection[0];
  56280. let maxScale = Math.max(...selected.scale.toArray());
  56281. let minScale = Math.min(...selected.scale.toArray());
  56282. let handleLength = Math.abs(selected.scale.dot(new Vector3(...handle.alignment)));
  56283. let alignment = new Vector3(...handle.alignment).multiplyScalar(2 * maxScale / handleLength);
  56284. alignment.applyMatrix4(selected.matrixWorld);
  56285. let newCamPos = alignment;
  56286. let newCamTarget = selected.getWorldPosition(new Vector3());
  56287. Utils.moveTo(this.viewer.scene, newCamPos, newCamTarget);
  56288. });
  56289. pickSphere.addEventListener("mouseover", e => {
  56290. //box.setOpacity(1);
  56291. });
  56292. pickSphere.addEventListener("mouseleave", e => {
  56293. //box.setOpacity(OpaWhenNotSelect);
  56294. });
  56295. }
  56296. }
  56297. dragRotationHandle(e){
  56298. let drag = e.drag;
  56299. let handle = this.activeHandle;
  56300. let camera = this.viewer.mainViewport.camera;//this.viewer.scene.getActiveCamera();
  56301. if(!handle){
  56302. return
  56303. };
  56304. let localNormal = new Vector3(...handle.alignment);
  56305. let n = new Vector3();
  56306. n.copy(new Vector4(...localNormal.toArray(), 0).applyMatrix4(handle.node.matrixWorld));
  56307. n.normalize();
  56308. if (!drag.intersectionStart){
  56309. //this.viewer.scene.scene.remove(this.debug);
  56310. //this.debug = new THREE.Object3D();
  56311. //this.viewer.scene.scene.add(this.debug);
  56312. //Utils.debugSphere(this.debug, drag.location, 3, 0xaaaaaa);
  56313. //let debugEnd = drag.location.clone().add(n.clone().multiplyScalar(20));
  56314. //Utils.debugLine(this.debug, drag.location, debugEnd, 0xff0000);
  56315. drag.intersectionStart = drag.location;
  56316. drag.objectStart = drag.object.getWorldPosition(new Vector3());
  56317. drag.handle = handle;
  56318. let plane = new Plane().setFromNormalAndCoplanarPoint(n, drag.intersectionStart);
  56319. drag.dragPlane = plane;
  56320. drag.pivot = drag.intersectionStart;
  56321. }else {
  56322. handle = drag.handle;
  56323. }
  56324. if(!drag.dragPlane)return//xzw add 因有时候没有
  56325. this.dragging = true;
  56326. let pointer = this.viewer.inputHandler.pointer;
  56327. let domElement = this.viewer.renderer.domElement;
  56328. let ray = Utils.mouseToRay(pointer, camera, domElement.clientWidth, domElement.clientHeight);
  56329. let I = ray.intersectPlane(drag.dragPlane, new Vector3());
  56330. if (I) {
  56331. let center = this.scene.getWorldPosition(new Vector3());
  56332. let from = drag.pivot;
  56333. let to = I;
  56334. let v1 = from.clone().sub(center).normalize();
  56335. let v2 = to.clone().sub(center).normalize();
  56336. let angle = Math.acos(v1.dot(v2));
  56337. let sign = Math.sign(v1.cross(v2).dot(n));
  56338. angle = angle * sign;
  56339. if (Number.isNaN(angle)) {
  56340. return;
  56341. }
  56342. let matrixBefore = this.selection[0].matrix.clone();
  56343. let normal = new Vector3(...handle.alignment);
  56344. for (let selection of this.selection) {
  56345. selection.rotateOnAxis(normal, angle);
  56346. selection.dispatchEvent({
  56347. type: "orientation_changed",
  56348. object: selection
  56349. });
  56350. }
  56351. this.dispatchEvent({type:'transformed', changeType: ['orientation'], matrixBefore });//add
  56352. drag.pivot = I;
  56353. }
  56354. }
  56355. dropRotationHandle(e){
  56356. this.dragging = false;
  56357. this.setActiveHandle(null);
  56358. this.dispatchEvent({type:'stopDrag', handle:'rotation'});//add
  56359. }
  56360. dragTranslationHandle(e){//---大改,参考transformControls,为了加上xyz xy yz xz 这四个方向的变换。 (但感觉好像plane上有丢丢延迟?是因为drag延迟还是worldmatrix没更新)
  56361. let drag = e.drag;
  56362. let handle = this.activeHandle;
  56363. let camera = this.viewer.mainViewport.camera;//this.viewer.scene.getActiveCamera();
  56364. if(handle && this.selection[0]){
  56365. let posWorld = this.selection[0].getWorldPosition(new Vector3()); //是需要世界坐标吗
  56366. if(!drag.intersectionStart){
  56367. drag.intersectionStart = drag.location;
  56368. drag.worldPositionStart = posWorld;
  56369. drag.objectQua = this.selection[0].quaternion.clone();//不考虑父级
  56370. drag.objectQuaInv = drag.objectQua.clone().invert();
  56371. this.dragging = true;
  56372. }
  56373. if(drag.intersectionStart){
  56374. let pointer = this.viewer.inputHandler.pointer;
  56375. let ray = Utils.mouseToRay(pointer, camera);
  56376. let normal = viewer.mainViewport.view.direction;
  56377. drag.dragPlane = new Plane().setFromNormalAndCoplanarPoint(normal, posWorld/* drag.worldPositionStart */);//过center的与视线垂直的平面
  56378. let I = ray.intersectPlane(drag.dragPlane, new Vector3());
  56379. if (I) {
  56380. let offset = new Vector3().subVectors( I , drag.worldPositionStart );
  56381. //let offset = new THREE.Vector3().subVectors(iOnLine, drag.worldPositionStart);
  56382. if(!drag.pointStart){
  56383. drag.pointStart = offset;
  56384. }else {
  56385. drag.pointEnd = offset;
  56386. let diff = new Vector3().subVectors(drag.pointEnd, drag.pointStart);
  56387. diff.applyQuaternion(drag.objectQuaInv); // 得到在该物体local空间上的offset
  56388. if(!handle.name.includes('x')) diff.x = 0;
  56389. if(!handle.name.includes('y')) diff.y = 0;
  56390. if(!handle.name.includes('z')) diff.z = 0;
  56391. //恢复为world offset
  56392. diff.applyQuaternion(drag.objectQua);
  56393. //-------------
  56394. let matrixBefore = this.selection[0].matrix.clone();
  56395. this.selection[0].position.copy( diff ).add( drag.worldPositionStart );
  56396. for (let selection of this.selection) {
  56397. selection.dispatchEvent({
  56398. type: "position_changed",
  56399. object: selection
  56400. });
  56401. }
  56402. this.dispatchEvent({type:'transformed', changeType: ['position'], matrixBefore});//add
  56403. }
  56404. }
  56405. }
  56406. }
  56407. }
  56408. dropTranslationHandle(e){
  56409. this.dragging = false;
  56410. this.setActiveHandle(null);
  56411. this.dispatchEvent({type:'stopDrag', handle:'translation'});//add
  56412. }
  56413. dropScaleHandle(e){
  56414. this.dragging = false;
  56415. this.setActiveHandle(null);
  56416. this.dispatchEvent({type:'stopDrag', handle:'scale'});//add
  56417. }
  56418. dragScaleHandle(e){
  56419. let drag = e.drag;
  56420. let handle = this.activeHandle;
  56421. if(!handle)return
  56422. let camera = this.viewer.mainViewport.camera;//this.viewer.scene.getActiveCamera();
  56423. if(!drag.intersectionStart){
  56424. drag.intersectionStart = drag.location;
  56425. drag.objectStart = drag.object.getWorldPosition(new Vector3());
  56426. drag.handle = handle;
  56427. let start = drag.intersectionStart;
  56428. let dir = new Vector4(...handle.alignment, 0).applyMatrix4(this.scene.matrixWorld);
  56429. let end = new Vector3().addVectors(start, dir);
  56430. let line = new Line3(start.clone(), end.clone());
  56431. drag.line = line;
  56432. let normal;
  56433. if(camera.type == 'OrthographicCamera'){//xzw add
  56434. normal = new Vector3(0,0,-1).applyQuaternion(camera.quaternion);
  56435. }else {
  56436. let camOnLine = line.closestPointToPoint(camera.position, false, new Vector3());
  56437. normal = new Vector3().subVectors(camera.position, camOnLine);
  56438. }
  56439. let plane = new Plane().setFromNormalAndCoplanarPoint(normal, drag.intersectionStart); //过轴线的一个能铺满屏幕的平面
  56440. drag.dragPlane = plane;
  56441. drag.pivot = drag.intersectionStart;
  56442. //Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
  56443. }else {
  56444. handle = drag.handle;
  56445. }
  56446. this.dragging = true;
  56447. if(drag.dragPlane){//xzw add 因有时候没有
  56448. let pointer = this.viewer.inputHandler.pointer;
  56449. let domElement = this.viewer.renderer.domElement;
  56450. let ray = Utils.mouseToRay(pointer, camera, domElement.clientWidth, domElement.clientHeight);
  56451. let I = ray.intersectPlane(drag.dragPlane, new Vector3());
  56452. if (I) {
  56453. let iOnLine = drag.line.closestPointToPoint(I, false, new Vector3());
  56454. let direction = handle.alignment.reduce( (a, v) => a + v, 0);
  56455. let toObjectSpace = this.selection[0].matrixWorld.clone().invert();
  56456. let iOnLineOS = iOnLine.clone().applyMatrix4(toObjectSpace);
  56457. let pivotOS = drag.pivot.clone().applyMatrix4(toObjectSpace);
  56458. let diffOS = new Vector3().subVectors(iOnLineOS, pivotOS);
  56459. let dragDirectionOS = diffOS.clone().normalize();
  56460. if(iOnLine.distanceTo(drag.pivot) === 0){
  56461. dragDirectionOS.set(0, 0, 0);
  56462. }
  56463. let dragDirection = dragDirectionOS.dot(new Vector3(...handle.alignment));
  56464. let diff = new Vector3().subVectors(iOnLine, drag.pivot);
  56465. let diffScale = new Vector3(...handle.alignment).multiplyScalar(diff.length() * direction * dragDirection);
  56466. let diffPosition = diff.clone().multiplyScalar(0.5);
  56467. let matrixBefore = this.selection[0].matrix.clone();
  56468. for (let selection of this.selection) {
  56469. //xzw 改:否则不跟手
  56470. let diffScale_ = diffScale.clone().divide(selection.boundingBox.getSize(new Vector3));
  56471. selection.scale.add(diffScale_);
  56472. //selection.scale.add(diffScale);
  56473. selection.scale.x = Math.max(0.1, selection.scale.x);
  56474. selection.scale.y = Math.max(0.1, selection.scale.y);
  56475. selection.scale.z = Math.max(0.1, selection.scale.z);
  56476. selection.position.add(diffPosition);
  56477. selection.dispatchEvent({
  56478. type: "position_changed",
  56479. object: selection
  56480. });
  56481. selection.dispatchEvent({
  56482. type: "scale_changed",
  56483. object: selection
  56484. });
  56485. this.dispatchEvent({type:'transformed', changeType: ['position','scale'], matrixBefore});//add
  56486. }
  56487. drag.pivot.copy(iOnLine);
  56488. //Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
  56489. }
  56490. }
  56491. }
  56492. setActiveHandle(handle){
  56493. if(this.dragging){
  56494. return;
  56495. }
  56496. if(this.activeHandle === handle){
  56497. return;
  56498. }
  56499. this.activeHandle = handle;
  56500. if(handle === null){
  56501. for(let handleName of Object.keys(this.handles)){
  56502. let handle = this.handles[handleName];
  56503. handle.node.setOpacity(0);
  56504. }
  56505. }
  56506. viewer.dispatchEvent({type:'CursorChange', action: this.activeHandle ? 'add' : 'remove', name:'hoverTranHandle'});
  56507. if(!hideFocusHandles){
  56508. for(let handleName of Object.keys(this.focusHandles)){
  56509. let handle = this.focusHandles[handleName];
  56510. if(this.activeHandle === handle){
  56511. handle.node.setOpacity(1.0);
  56512. }else {
  56513. handle.node.setOpacity(OpaWhenNotSelect);
  56514. }
  56515. }
  56516. }
  56517. for(let handleName of Object.keys(this.translationHandles)){
  56518. let handle = this.translationHandles[handleName];
  56519. if(this.activeHandle === handle){
  56520. handle.node.setOpacity(1.0);
  56521. }else {
  56522. handle.node.setOpacity(OpaWhenNotSelect);
  56523. }
  56524. }
  56525. for(let handleName of Object.keys(this.rotationHandles)){
  56526. let handle = this.rotationHandles[handleName];
  56527. //if(this.activeHandle === handle){
  56528. // handle.node.setOpacity(1.0);
  56529. //}else{
  56530. // handle.node.setOpacity(OpaWhenNotSelect)
  56531. //}
  56532. handle.node.setOpacity(OpaWhenNotSelect);
  56533. }
  56534. for(let handleName of Object.keys(this.scaleHandles)){
  56535. let handle = this.scaleHandles[handleName];
  56536. if(this.activeHandle === handle){
  56537. handle.node.setOpacity(1.0);
  56538. if(!hideFocusHandles){
  56539. let relatedFocusHandle = this.focusHandles[handle.name.replace("scale", "focus")];
  56540. let relatedFocusNode = relatedFocusHandle.node;
  56541. relatedFocusNode.setOpacity(OpaWhenNotSelect);
  56542. }
  56543. for(let translationHandleName of Object.keys(this.translationHandles)){
  56544. let translationHandle = this.translationHandles[translationHandleName];
  56545. translationHandle.node.setOpacity(OpaWhenNotSelect);
  56546. }
  56547. //let relatedTranslationHandle = this.translationHandles[
  56548. // handle.name.replace("scale", "translation").replace(/[+-]/g, "")];
  56549. //let relatedTranslationNode = relatedTranslationHandle.node;
  56550. //relatedTranslationNode.setOpacity(OpaWhenNotSelect);
  56551. }else {
  56552. handle.node.setOpacity(OpaWhenNotSelect);
  56553. }
  56554. }
  56555. if(handle){
  56556. handle.node.setOpacity(1.0);
  56557. }
  56558. viewer.dispatchEvent('content_changed');
  56559. }
  56560. update () {
  56561. if(this.selection.length === 1){
  56562. this.scene.visible = true;
  56563. this.scene.updateMatrix();
  56564. this.scene.updateMatrixWorld();
  56565. let selected = this.selection[0];
  56566. let world = selected.matrixWorld;
  56567. let camera = this.viewer.mainViewport.camera;//this.viewer.scene.getActiveCamera();
  56568. let domElement = this.viewer.renderer.domElement;
  56569. let center = selected.boundingBox.getCenter(new Vector3()).clone().applyMatrix4(selected.matrixWorld);
  56570. this.scene.scale.copy(selected.boundingBox.getSize(new Vector3()).multiply(selected.scale));
  56571. this.scene.position.copy(center);
  56572. this.scene.rotation.copy(selected.rotation); //这里只考虑当前子级的scale rotation
  56573. //如果是世界坐标 (缩放方向有bug。)
  56574. /*
  56575. let boundingBox = selected.boundingBox.clone().applyMatrix4(selected.matrixWorld);
  56576. let center = boundingBox.getCenter(new THREE.Vector3())
  56577. this.scene.position.copy(center);
  56578. this.scene.scale.copy(boundingBox.getSize(new THREE.Vector3()));
  56579. */
  56580. this.scene.updateMatrixWorld();
  56581. {
  56582. // adjust rotation handles
  56583. if(!this.dragging){
  56584. if(this.modesEnabled.rotation || this.modesEnabled.translation){
  56585. let tWorld = this.scene.matrixWorld;
  56586. let tObject = tWorld.clone().invert();
  56587. let camObjectPos = camera.getWorldPosition(new Vector3()).applyMatrix4(tObject);
  56588. if(this.modesEnabled.translation){//add
  56589. ['xy','yz','xz'].forEach(axis=>{
  56590. let handle = this.translationHandles["translation.plane."+axis];
  56591. let pos = handle.node.children[0].position;
  56592. camObjectPos.x && (pos.x = Math.sign(camObjectPos.x) * Math.abs(pos.x));
  56593. camObjectPos.y && (pos.y = Math.sign(camObjectPos.y) * Math.abs(pos.y));
  56594. camObjectPos.z && (pos.z = Math.sign(camObjectPos.z) * Math.abs(pos.z));
  56595. });
  56596. }
  56597. if(this.modesEnabled.rotation){
  56598. let above = camObjectPos.z > 0;
  56599. let below = !above;
  56600. let PI_HALF = Math.PI / 2;
  56601. let x = this.rotationHandles["rotation.x"].node.rotation;
  56602. let y = this.rotationHandles["rotation.y"].node.rotation;
  56603. let z = this.rotationHandles["rotation.z"].node.rotation;
  56604. x.order = "ZYX";
  56605. y.order = "ZYX";
  56606. if(above){
  56607. if(camObjectPos.x > 0 && camObjectPos.y > 0){
  56608. x.x = 1 * PI_HALF;
  56609. y.y = 3 * PI_HALF;
  56610. z.z = 0 * PI_HALF;
  56611. }else if(camObjectPos.x < 0 && camObjectPos.y > 0){
  56612. x.x = 1 * PI_HALF;
  56613. y.y = 2 * PI_HALF;
  56614. z.z = 1 * PI_HALF;
  56615. }else if(camObjectPos.x < 0 && camObjectPos.y < 0){
  56616. x.x = 2 * PI_HALF;
  56617. y.y = 2 * PI_HALF;
  56618. z.z = 2 * PI_HALF;
  56619. }else if(camObjectPos.x > 0 && camObjectPos.y < 0){
  56620. x.x = 2 * PI_HALF;
  56621. y.y = 3 * PI_HALF;
  56622. z.z = 3 * PI_HALF;
  56623. }
  56624. }else if(below){
  56625. if(camObjectPos.x > 0 && camObjectPos.y > 0){
  56626. x.x = 0 * PI_HALF;
  56627. y.y = 0 * PI_HALF;
  56628. z.z = 0 * PI_HALF;
  56629. }else if(camObjectPos.x < 0 && camObjectPos.y > 0){
  56630. x.x = 0 * PI_HALF;
  56631. y.y = 1 * PI_HALF;
  56632. z.z = 1 * PI_HALF;
  56633. }else if(camObjectPos.x < 0 && camObjectPos.y < 0){
  56634. x.x = 3 * PI_HALF;
  56635. y.y = 1 * PI_HALF;
  56636. z.z = 2 * PI_HALF;
  56637. }else if(camObjectPos.x > 0 && camObjectPos.y < 0){
  56638. x.x = 3 * PI_HALF;
  56639. y.y = 0 * PI_HALF;
  56640. z.z = 3 * PI_HALF;
  56641. }
  56642. }
  56643. }
  56644. }
  56645. }
  56646. // adjust scale of components
  56647. for(let handleName of Object.keys(this.handles)){
  56648. let handle = this.handles[handleName];
  56649. let node = handle.node;
  56650. //xzw add:---- -当该轴正对相机时隐藏。(主要针对ortho类型camera。
  56651. if(!Potree.Utils.getObjVisiByReason(node,'modeForce') )continue;
  56652. let alignment = handle.alignment;
  56653. if(alignment && (!handleName.includes('rotation') || camera.type == 'OrthographicCamera')){//旋转的话正常都应该显示
  56654. let normal;
  56655. let dir = new Vector3(...alignment).applyQuaternion(this.scene.quaternion);
  56656. if(camera.type == 'OrthographicCamera'){
  56657. normal = new Vector3(0,0,-1).applyQuaternion(camera.quaternion);
  56658. }else {
  56659. normal = new Vector3().subVectors(center, camera.position).normalize();
  56660. }
  56661. let ifOnLine;
  56662. if(handleName.includes('rotation') || handleName.includes('plane')){ // 旋转轴和视线垂直时隐藏
  56663. ifOnLine = Math.abs(dir.dot(normal)) < 0.1;
  56664. }else {
  56665. ifOnLine = Math.abs(dir.dot(normal)) > 0.995;
  56666. }
  56667. Potree.Utils.updateVisible(node, 'faceToCamHide', !ifOnLine);
  56668. }else {
  56669. Potree.Utils.updateVisible(node, 'faceToCamHide', true);
  56670. }
  56671. if(!node.visible)continue;
  56672. //------------------------------------------------------------------------
  56673. if(handle.dontScale)continue; //add
  56674. let handlePos = node.getWorldPosition(new Vector3());
  56675. let distance = handlePos.distanceTo(camera.position);
  56676. let pr = Utils.projectedRadius(1, camera, distance, domElement.clientWidth, domElement.clientHeight);
  56677. let ws = node.parent.getWorldScale(new Vector3());
  56678. let s = (ScaleRatio / pr);
  56679. let scale = new Vector3(s, s, s).divide(ws);
  56680. let rot = new Matrix4().makeRotationFromEuler(node.rotation); //需要使用到旋转,所以我把设置scale的移到旋转后了,否则在视图上下旋转的分界线处rotateHandel会被拉长从而闪烁。
  56681. let rotInv = rot.clone().invert();
  56682. scale.applyMatrix4(rotInv);
  56683. scale.x = Math.abs(scale.x);
  56684. scale.y = Math.abs(scale.y);
  56685. scale.z = Math.abs(scale.z);
  56686. node.scale.copy(scale);
  56687. }
  56688. }
  56689. }else {
  56690. this.scene.visible = false;
  56691. }
  56692. }
  56693. onPointerMove(){
  56694. let pointer = this.viewer.inputHandler.pointer;
  56695. let camera = this.viewer.mainViewport.camera;
  56696. if( this.selection.length === 1 && !this.dragging ){ //xzw 添加dragging条件
  56697. let ray = Utils.mouseToRay(pointer, camera );
  56698. let raycaster = new Raycaster(ray.origin, ray.direction);
  56699. raycaster.layers.enableAll();//add
  56700. let pickVolumes = this.pickVolumes.filter(v=>{
  56701. let mode = v.handle.split('.')[0];
  56702. if(!this.modesEnabled[mode])return
  56703. return v.parent.parent.visible //可能被隐藏该轴
  56704. });
  56705. let intersects = raycaster.intersectObjects(pickVolumes, true);
  56706. intersects = intersects.sort(function(a,b){
  56707. let order2 = b.object.renderOrder || 0;
  56708. let order1 = a.object.renderOrder || 0;
  56709. return order2-order1
  56710. }); // 降序
  56711. if(intersects.length > 0){
  56712. let I = intersects[0];
  56713. let handleName = I.object.handle;
  56714. //console.log(handleName)
  56715. this.setActiveHandle(this.handles[handleName]);
  56716. }else {
  56717. this.setActiveHandle(null);
  56718. }
  56719. }
  56720. }
  56721. };
  56722. /*
  56723. note:
  56724. transformationTool.scene会跟随选中物体,其scale就是boundingbox的大小。因此transformationTool.frame这个框也会跟着缩放
  56725. */
  56726. const boxOpacity = {
  56727. hovered : 0.1,
  56728. selected : 0.2
  56729. };
  56730. const LineOpacity = {
  56731. default : 0.6,
  56732. selected: 1,
  56733. };
  56734. const colors = {
  56735. 2: 0x2ee4ce,//0x00ff80, //可见
  56736. 3: 0xffc23b,//0xff3158, //不可见
  56737. 4: 0xffffff, //
  56738. };
  56739. class Volume$1 extends Object3D {
  56740. constructor (args = {}) {
  56741. super();
  56742. if(this.constructor.name === "Volume"){
  56743. console.warn("Can't create object of class Volume directly. Use classes BoxVolume or SphereVolume instead.");
  56744. }
  56745. this._clip = args.clip || false;
  56746. this._visible = true;
  56747. //this.showVolumeLabel = true;
  56748. this._modifiable = args.modifiable || true;
  56749. { // event listeners
  56750. this.addEventListener('select', e => {
  56751. //console.log('select')
  56752. this.setSelected(true);
  56753. });
  56754. this.addEventListener('deselect', e => {
  56755. //console.log('deselect')
  56756. this.setSelected(false);
  56757. });
  56758. this.addEventListener('mouseover', e => {
  56759. this.hovered = true;
  56760. this.update();
  56761. });
  56762. this.addEventListener('mouseleave', e => {
  56763. this.hovered = false;
  56764. this.update();
  56765. });
  56766. }
  56767. }
  56768. setSelected(state){//add
  56769. this.selected = !!state;
  56770. this.update();
  56771. }
  56772. get visible(){
  56773. return this._visible;
  56774. }
  56775. set visible(value){
  56776. if(this._visible !== value){
  56777. this._visible = value;
  56778. this.dispatchEvent({type: "visibility_changed", object: this});
  56779. }
  56780. }
  56781. getVolume () {
  56782. console.warn("override this in subclass");
  56783. }
  56784. update () {
  56785. };
  56786. raycast (raycaster, intersects) {
  56787. }
  56788. get clip () {
  56789. return this._clip;
  56790. }
  56791. set clip (value) {
  56792. if(this._clip !== value){
  56793. this._clip = value;
  56794. this.update();
  56795. this.dispatchEvent({
  56796. type: "clip_changed",
  56797. object: this
  56798. });
  56799. }
  56800. }
  56801. get modifieable () {
  56802. return this._modifiable;
  56803. }
  56804. set modifieable (value) {
  56805. this._modifiable = value;
  56806. this.update();
  56807. }
  56808. };
  56809. class BoxVolume$1 extends Volume$1{
  56810. constructor(args = {}){
  56811. super(args);
  56812. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  56813. this.name = 'box_' + this.constructor.counter;
  56814. this.clipTask = args.clipTask || Potree.ClipTask.SHOW_INSIDE; //add
  56815. this.showBox = true;
  56816. let boxGeometry = new BoxGeometry(1, 1, 1);
  56817. boxGeometry.computeBoundingBox();
  56818. let boxFrameGeometry = new Geometry();
  56819. let Vector3$1 = Vector3;
  56820. {
  56821. boxFrameGeometry.vertices.push(
  56822. // bottom
  56823. new Vector3$1(-0.5, -0.5, 0.5),
  56824. new Vector3$1(0.5, -0.5, 0.5),
  56825. new Vector3$1(0.5, -0.5, 0.5),
  56826. new Vector3$1(0.5, -0.5, -0.5),
  56827. new Vector3$1(0.5, -0.5, -0.5),
  56828. new Vector3$1(-0.5, -0.5, -0.5),
  56829. new Vector3$1(-0.5, -0.5, -0.5),
  56830. new Vector3$1(-0.5, -0.5, 0.5),
  56831. // top
  56832. new Vector3$1(-0.5, 0.5, 0.5),
  56833. new Vector3$1(0.5, 0.5, 0.5),
  56834. new Vector3$1(0.5, 0.5, 0.5),
  56835. new Vector3$1(0.5, 0.5, -0.5),
  56836. new Vector3$1(0.5, 0.5, -0.5),
  56837. new Vector3$1(-0.5, 0.5, -0.5),
  56838. new Vector3$1(-0.5, 0.5, -0.5),
  56839. new Vector3$1(-0.5, 0.5, 0.5),
  56840. // sides
  56841. new Vector3$1(-0.5, -0.5, 0.5),
  56842. new Vector3$1(-0.5, 0.5, 0.5),
  56843. new Vector3$1(0.5, -0.5, 0.5),
  56844. new Vector3$1(0.5, 0.5, 0.5),
  56845. new Vector3$1(0.5, -0.5, -0.5),
  56846. new Vector3$1(0.5, 0.5, -0.5),
  56847. new Vector3$1(-0.5, -0.5, -0.5),
  56848. new Vector3$1(-0.5, 0.5, -0.5),
  56849. );
  56850. }
  56851. this.material = new DepthBasicMaterial({
  56852. color: colors[this.clipTask],
  56853. side:DoubleSide,
  56854. transparent: true,
  56855. opacity: boxOpacity.hovered,
  56856. depthTest: true,
  56857. depthWrite: false,
  56858. useDepth:true,
  56859. clipDistance : 2,//消失距离
  56860. occlusionDistance: 0.1,//变为backColor距离
  56861. maxClipFactor: 0.9,
  56862. });
  56863. this.box = new Mesh(boxGeometry, this.material);
  56864. this.box.geometry.computeBoundingBox();
  56865. this.boundingBox = this.box.geometry.boundingBox;
  56866. this.add(this.box);
  56867. //this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: colors[this.clipTask], opacity:LineOpacity.default/* 0xff2050 */}));
  56868. this.frame = LineDraw.createFatLine(
  56869. boxFrameGeometry.vertices,
  56870. { color: colors[this.clipTask], opacity:LineOpacity.default, lineWidth:1, dontAlwaysSeen:true} );
  56871. // this.frame.mode = THREE.Lines;
  56872. this.add(this.frame);
  56873. this.update();
  56874. }
  56875. update(){
  56876. this.boundingBox = this.box.geometry.boundingBox;
  56877. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  56878. Potree.Utils.updateVisible(this.box, 'selected', (this.selected || this.hovered) && this.showBox);
  56879. this.box.material.opacity = this.selected ? boxOpacity.selected : boxOpacity.hovered;
  56880. this.box.material.color.set(colors[this.clipTask]);
  56881. this.frame.material.color.set(colors[this.clipTask]);
  56882. this.frame.material.opacity = this.selected ? LineOpacity.selected : LineOpacity.default;
  56883. this.frame.material.lineWidth = this.selected ? 2 : 1;
  56884. }
  56885. raycast (raycaster, intersects) {
  56886. let is = [];
  56887. this.box.raycast(raycaster, is);
  56888. if (is.length > 0) {
  56889. let I = is[0];
  56890. intersects.push({
  56891. distance: I.distance,
  56892. object: this,
  56893. point: I.point.clone()
  56894. });
  56895. }
  56896. }
  56897. getVolume(){
  56898. return Math.abs(this.scale.x * this.scale.y * this.scale.z);
  56899. }
  56900. };
  56901. class SphereVolume$2 extends Volume$1{
  56902. constructor(args = {}){
  56903. super(args);
  56904. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  56905. this.name = 'sphere_' + this.constructor.counter;
  56906. let sphereGeometry = new SphereGeometry(1, 32, 32);
  56907. sphereGeometry.computeBoundingBox();
  56908. this.material = new MeshBasicMaterial({
  56909. color: 0x00ff00,
  56910. transparent: true,
  56911. opacity: 0.3,
  56912. depthTest: true,
  56913. depthWrite: false});
  56914. this.sphere = new Mesh(sphereGeometry, this.material);
  56915. this.sphere.visible = false;
  56916. this.sphere.geometry.computeBoundingBox();
  56917. this.boundingBox = this.sphere.geometry.boundingBox;
  56918. this.add(this.sphere);
  56919. this.label.visible = false;
  56920. let frameGeometry = new Geometry();
  56921. {
  56922. let steps = 64;
  56923. let uSegments = 8;
  56924. let vSegments = 5;
  56925. let r = 1;
  56926. for(let uSegment = 0; uSegment < uSegments; uSegment++){
  56927. let alpha = (uSegment / uSegments) * Math.PI * 2;
  56928. let dirx = Math.cos(alpha);
  56929. let diry = Math.sin(alpha);
  56930. for(let i = 0; i <= steps; i++){
  56931. let v = (i / steps) * Math.PI * 2;
  56932. let vNext = v + 2 * Math.PI / steps;
  56933. let height = Math.sin(v);
  56934. let xyAmount = Math.cos(v);
  56935. let heightNext = Math.sin(vNext);
  56936. let xyAmountNext = Math.cos(vNext);
  56937. let vertex = new Vector3(dirx * xyAmount, diry * xyAmount, height);
  56938. frameGeometry.vertices.push(vertex);
  56939. let vertexNext = new Vector3(dirx * xyAmountNext, diry * xyAmountNext, heightNext);
  56940. frameGeometry.vertices.push(vertexNext);
  56941. }
  56942. }
  56943. // creates rings at poles, just because it's easier to implement
  56944. for(let vSegment = 0; vSegment <= vSegments + 1; vSegment++){
  56945. //let height = (vSegment / (vSegments + 1)) * 2 - 1; // -1 to 1
  56946. let uh = (vSegment / (vSegments + 1)); // -1 to 1
  56947. uh = (1 - uh) * (-Math.PI / 2) + uh *(Math.PI / 2);
  56948. let height = Math.sin(uh);
  56949. console.log(uh, height);
  56950. for(let i = 0; i <= steps; i++){
  56951. let u = (i / steps) * Math.PI * 2;
  56952. let uNext = u + 2 * Math.PI / steps;
  56953. let dirx = Math.cos(u);
  56954. let diry = Math.sin(u);
  56955. let dirxNext = Math.cos(uNext);
  56956. let diryNext = Math.sin(uNext);
  56957. let xyAmount = Math.sqrt(1 - height * height);
  56958. let vertex = new Vector3(dirx * xyAmount, diry * xyAmount, height);
  56959. frameGeometry.vertices.push(vertex);
  56960. let vertexNext = new Vector3(dirxNext * xyAmount, diryNext * xyAmount, height);
  56961. frameGeometry.vertices.push(vertexNext);
  56962. }
  56963. }
  56964. }
  56965. this.frame = new LineSegments(frameGeometry, new LineBasicMaterial({color: 0x000000}));
  56966. this.add(this.frame);
  56967. let frameMaterial = new MeshBasicMaterial({wireframe: true, color: 0x000000});
  56968. this.frame = new Mesh(sphereGeometry, frameMaterial);
  56969. //this.add(this.frame);
  56970. //this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: 0x000000}));
  56971. // this.frame.mode = THREE.Lines;
  56972. //this.add(this.frame);
  56973. this.update();
  56974. }
  56975. update(){
  56976. this.boundingBox = this.sphere.geometry.boundingBox;
  56977. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  56978. //if (this._clip) {
  56979. // this.sphere.visible = false;
  56980. // this.label.visible = false;
  56981. //} else {
  56982. // this.sphere.visible = true;
  56983. // this.label.visible = this.showVolumeLabel;
  56984. //}
  56985. }
  56986. raycast (raycaster, intersects) {
  56987. let is = [];
  56988. this.sphere.raycast(raycaster, is);
  56989. if (is.length > 0) {
  56990. let I = is[0];
  56991. intersects.push({
  56992. distance: I.distance,
  56993. object: this,
  56994. point: I.point.clone()
  56995. });
  56996. }
  56997. }
  56998. // see https://en.wikipedia.org/wiki/Ellipsoid#Volume
  56999. getVolume(){
  57000. return (4 / 3) * Math.PI * this.scale.x * this.scale.y * this.scale.z;
  57001. }
  57002. };
  57003. const renderOrders = {
  57004. line: 0 ,
  57005. spot: 15, //高过模型
  57006. };
  57007. const planeGeo = new PlaneGeometry(1,1);
  57008. let texLoader$3 = new TextureLoader();
  57009. let lineMat = new LineBasicMaterial({
  57010. color: '#ffffff',
  57011. });
  57012. let spotMat;
  57013. const defaultLineLength = 0.6;
  57014. const defaultSpotScale = 0.4;
  57015. class Tag extends Object3D{
  57016. constructor(o){
  57017. super();
  57018. this.lineLength = o.lineLength != void 0 ? o.lineLength : defaultLineLength;
  57019. this.position.copy(o.position);
  57020. this.normal = o.normal != void 0 ? o.normal : new Vector3(0,0,-1);
  57021. this.root = o.root;
  57022. //this.matrixAutoUpdate = false
  57023. this.build();
  57024. /* this.spot.addEventListener('mouseover',()=>{
  57025. }) */
  57026. }
  57027. build(){
  57028. if(!spotMat){
  57029. spotMat = new MeshBasicMaterial({
  57030. transparent:true,
  57031. map: texLoader$3.load(Potree.resourcePath+'/textures/spot_default.png' ),
  57032. });
  57033. }
  57034. let endPos = this.normal.clone().multiplyScalar(this.lineLength);
  57035. this.line = LineDraw.createLine([
  57036. new Vector3(0,0,0),
  57037. endPos
  57038. ], {mat:lineMat});
  57039. let group = new Object3D();
  57040. this.spot = new Mesh(planeGeo, spotMat);
  57041. this.spot.scale.set(defaultSpotScale,defaultSpotScale,defaultSpotScale);
  57042. this.titleLabel = new TextSprite$2({root: group, text:'1', sizeInfo:{width2d:200},
  57043. textColor:{r:255,g:255,b:255,a:1.0},
  57044. backgroundColor:{r:0,g:0,b:0,a:0.8},
  57045. borderRadius: 6,
  57046. fontsize:13, fontWeight:'',//thick
  57047. renderOrder : renderOrders.spot, pickOrder:renderOrders.spot,
  57048. }); //更新sprite时,实际更新的是root: spot的矩阵
  57049. this.spot.renderOrder = renderOrders.spot;
  57050. /* const mainLabelProp = {
  57051. backgroundColor: {r: defaultColor.r*255, g: defaultColor.g*255, b: defaultColor.b*255, a:config.measure.default.opacity},
  57052. textColor: {r: textColor.r*255, g: textColor.g*255, b: textColor.b*255, a: 1.0},
  57053. fontsize:16,
  57054. useDepth : true ,
  57055. renderOrder : 5, pickOrder:5,
  57056. } */
  57057. this.titleLabel.position.set(0,0.4,0);
  57058. this.titleLabel.sprite.material.depthTest = this.titleLabel.sprite.material.depthWrite = true;
  57059. group.position.copy(endPos);
  57060. group.add(this.spot);
  57061. group.add(this.titleLabel);
  57062. this.add(group);
  57063. this.add(this.line);
  57064. viewer.scene.tags.add(this);
  57065. }
  57066. changeTitle(title){
  57067. this.titleLabel.changeText(title);
  57068. }
  57069. updateMatrixWorld(force){ //重写,只为了将root当做parent
  57070. this.updateMatrix();
  57071. this.matrixWorld.multiplyMatrices( this.root.matrixWorld, this.matrix );
  57072. const children = this.children;
  57073. for ( let i = 0, l = children.length; i < l; i ++ ) {
  57074. children[ i ].updateMatrixWorld( force );
  57075. }
  57076. }
  57077. updateWorldMatrix( updateParents, updateChildren ) {//重写,只为了将root当做parent
  57078. if ( updateParents === true && this.root !== null ) {
  57079. this.root.updateWorldMatrix( true, false );
  57080. }
  57081. if ( this.matrixAutoUpdate ) this.updateMatrix();
  57082. this.matrixWorld.multiplyMatrices( this.root.matrixWorld, this.matrix );
  57083. if ( updateChildren === true ) {
  57084. const children = this.children;
  57085. for ( let i = 0, l = children.length; i < l; i ++ ) {
  57086. children[ i ].updateWorldMatrix( false, true );
  57087. }
  57088. }
  57089. }
  57090. dispose(){
  57091. this.parent.remove(this);
  57092. this.titleLabel.dispatchEvent({type:'dispose'});
  57093. }
  57094. }
  57095. class TagTool extends EventDispatcher{
  57096. constructor (viewer) {
  57097. super();
  57098. this.viewer = viewer;
  57099. this.viewer.addEventListener('start_inserting_tag', e => {
  57100. this.viewer.dispatchEvent({
  57101. type: 'cancel_insertions'
  57102. });
  57103. });
  57104. }
  57105. createTagFromData(data){
  57106. let tag = new Tag({
  57107. title: data.title, position: data.position, normal: data.normal,
  57108. root: data.root //e.intersect.pointcloud || e.intersect.object
  57109. });
  57110. return tag
  57111. }
  57112. startInsertion (args = {}, callback, cancelFun) {
  57113. let deferred = $.Deferred();
  57114. this.viewer.dispatchEvent({
  57115. type: 'start_inserting_tag'
  57116. });
  57117. this.adding = true;
  57118. let cancel = ()=>{
  57119. end();
  57120. };
  57121. let end = ()=>{
  57122. this.adding = false;
  57123. viewer.dispatchEvent({type:"endTagMove"});
  57124. this.viewer.removeEventListener('global_click', click);
  57125. };
  57126. let click = (e)=>{
  57127. var worldPos = e.intersect && (/* e.intersect.orthoIntersect || */e.intersect.location);
  57128. if(!worldPos){
  57129. return
  57130. }
  57131. let localPos = Potree.Utils.datasetPosTransform({ toDataset: true, pointcloud:e.intersect.pointcloud, object:e.intersect.object, position:worldPos });
  57132. let tag = new Tag({
  57133. title: '1', position: localPos, normal:e.intersect.normal,
  57134. root: e.intersect.pointcloud || e.intersect.object
  57135. });
  57136. //pointcloud里加一个normal 的非float32
  57137. end();
  57138. e.consume && e.consume();
  57139. deferred.resolve(tag);
  57140. return {stopContinue:true}
  57141. };
  57142. this.viewer.addEventListener('global_click', click, {importance:10});
  57143. return deferred.promise()
  57144. }
  57145. }
  57146. const initDir = new Vector3(0,1,0);//指南针模型的北方向 向屏幕里
  57147. class Compass extends EventDispatcher{
  57148. constructor(dom, viewport){
  57149. super();
  57150. this.angle = 0;
  57151. this.show = false;
  57152. if(dom){
  57153. this.dom = $(dom);
  57154. }
  57155. this.viewport = viewport;
  57156. this.init();
  57157. }
  57158. init(){
  57159. var width = 100, height = 100;
  57160. if(!this.dom){
  57161. this.dom = $('<div name="compass"></div>');
  57162. $(viewer.renderArea).append(this.dom);
  57163. }
  57164. this.dom.css({ display:"none", position:"absolute",right:"1%",top: "60px",width:width+"px",height:height+"px", "z-index":100,"pointer-events":"none" });
  57165. let child = $("<div class='dirText north'><span>"+/* (config.lang=='zh'? */'北'/* :'N') */+"</span></div><div class='center'></div>");
  57166. this.dom.append(child);
  57167. this.dom.find(".dirText").css({textAlign:"center","font-size":"10px","position":"absolute",
  57168. width: "100%",
  57169. height: "25px",
  57170. "line-height": "25px"});
  57171. this.dom.find(".north").css({"color":"#02a0e9","top":"0"});
  57172. this.dom.find(".south").css({"color":"#ff1414","bottom":"0"});
  57173. this.dom.find(".center").css({
  57174. //"background":`url(${config.getStaticResource('img')}/dire.png)`,
  57175. width: width/2+"px",
  57176. height: height/2+"px",
  57177. "background-size": "contain",
  57178. "background-position": "center",
  57179. left: "50%",
  57180. top: "50%",
  57181. transform: "translate(-50%,-50%)",
  57182. position: "absolute"
  57183. });
  57184. this.dom.find(".dirText").css({
  57185. "text-align": "center",
  57186. "font-size": "10px",
  57187. "color": "rgb(255, 255, 255)",
  57188. "position": "absolute",
  57189. "top": "50%",
  57190. "left": "50%",
  57191. "width": "45%",
  57192. "height": "0px",
  57193. "transform-origin": "left center",
  57194. });
  57195. this.dom.find(".dirText span").css({
  57196. display: "block",
  57197. position: "absolute",
  57198. right: "5px",
  57199. top: "0",
  57200. width: "20px",
  57201. height: "20px",
  57202. "line-height": "20px",
  57203. // "font-size": ".75rem ",
  57204. "margin-top": "-10px",
  57205. });
  57206. try {
  57207. this.renderer = new WebGLRenderer({ antialias: true, alpha:true });//许钟文 添加个抗锯齿,否则添加的线条锯齿严重,
  57208. this.renderer.autoClear = !0;
  57209. this.renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1);
  57210. this.renderer.domElement.setAttribute('name','compass');
  57211. this.renderer.setClearAlpha(0.0);
  57212. //xst修改
  57213. //this.renderer.setSize(width/2, height/2, false, window.devicePixelRatio ? window.devicePixelRatio : 1);
  57214. //xst修改
  57215. //this.renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1);
  57216. //this.renderer.setSize(width/2, height/2);
  57217. //xst修改
  57218. this.renderer.setDrawingBufferSize( width/2, height/2, window.devicePixelRatio ? window.devicePixelRatio : 1 );
  57219. //this.emit(SceneRendererEvents.ContextCreated)
  57220. } catch (e) {
  57221. viewer.dispatchEvent('webglError', {msg:e});
  57222. }
  57223. this.dom.find(".center")[0].appendChild(this.renderer.domElement);
  57224. this.renderer.domElement.style.width = this.renderer.domElement.style.height = '100%';
  57225. this.camera = new PerspectiveCamera;
  57226. this.camera.fov = 50;
  57227. this.camera.updateProjectionMatrix();
  57228. this.scene = new Scene,
  57229. this.scene.add(this.camera);
  57230. this.createCompass();
  57231. viewer.addEventListener('camera_changed', e => {
  57232. if (e.viewport == this.viewport && (/* e.changeInfo.positionChanged || */e.changeInfo.quaternionChanged)) {
  57233. this.update();
  57234. }
  57235. });
  57236. this.setDomPos();
  57237. if(this.viewport)this.setDisplay(true);
  57238. }
  57239. createCompass(){
  57240. //ConeBufferGeometry(radius : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float)
  57241. const height = 2;
  57242. const geometry1 = new ConeBufferGeometry( 0.7, height, 4, true );
  57243. const geometry2 = new ConeBufferGeometry( 0.7, height, 4, true );
  57244. const material = new MeshBasicMaterial({
  57245. vertexColors :true
  57246. });
  57247. //指南针由两个四棱锥拼成,为了渐变颜色,采用指定vertexColor的方式。
  57248. var setColor = function(geometry, color1,color2){
  57249. const colors = [];
  57250. for ( let i = 0, n = geometry.attributes.position.count; i < n; ++ i ) {
  57251. colors.push( 1, 1, 1 );
  57252. }
  57253. var set = function(index, color){//设置第index个点的颜色
  57254. colors[index*3+0] = color[0];
  57255. colors[index*3+1] = color[1];
  57256. colors[index*3+2] = color[2];
  57257. };
  57258. var mid = [(color1[0]+color2[0])/2, (color1[1]+color2[1])/2, (color1[2]+color2[2])/2 ];
  57259. set(1,color1); set(5,color1);set(6,color1);
  57260. set(2,mid); set(3,mid);set(7,mid);
  57261. set(4,color2); set(8,color2);set(9,color2);
  57262. geometry.setAttribute("color", new BufferAttribute(new Float32Array(colors), 3));
  57263. };
  57264. var blue1 = [1/255,238/255,245/255]; //逐渐变深
  57265. var blue2 = [20/255,146/255,170/255];
  57266. var blue3 = [40/255,60/255,103/255];
  57267. setColor(geometry1, blue1,blue2);
  57268. setColor(geometry2, blue2,blue3);
  57269. /* 朝箭头方向看点构成如下 虽然geometry.attributes.position.count = 19 只有1-9设置的颜色是有效的 另外为什么7决定了上下两边的颜色呢…… 5、9可将其分成上下两个颜色
  57270. 6
  57271. /|\
  57272. / | \
  57273. 7 /_2|1_\ 5
  57274. \ 3|4 / 9
  57275. \ | /
  57276. \|/
  57277. 8
  57278. */
  57279. const cone = new Mesh( geometry1, material );
  57280. cone.position.setY(height/2);
  57281. geometry1.computeVertexNormals();//computeFaceNormals
  57282. geometry2.computeVertexNormals();
  57283. const cones = new Object3D();
  57284. cones.add(cone);
  57285. let cone2 = new Mesh( geometry2, material );
  57286. cone2.rotation.x = Math.PI;
  57287. cone2.position.setY(-height/2);
  57288. cones.add(cone2);
  57289. //cones.rotation.x = Math.PI / 2;//转向initDir的方向
  57290. //cones.rotation.z = Math.PI / 2;
  57291. cones.rotation.z = Math.PI ;//转向initDir的方向
  57292. cones.scale.set(0.7,0.7,0.7);
  57293. this.scene.add(cones);
  57294. this.cones = cones;
  57295. }
  57296. setNorth(){ //设置北方向,这决定了指南针自身的朝向。
  57297. const floors = store.getters['scene/houstFloor'].floors;
  57298. if(!floors || !floors.length){
  57299. return
  57300. }
  57301. const floor = floors[0];
  57302. const metadata = app.store.getters['scene/metadata'] || {};
  57303. this.angle = (floor && floor.dire || 0) + MathUtils$1.radToDeg(parseFloat(metadata.floorPlanAngle || 0)); //基础朝向
  57304. this.cones.rotation.y = Math.PI / 2 - MathUtils$1.degToRad(this.angle);
  57305. //console.log("dir:"+floor.dire+", floorPlanAngle:"+metadata.floorPlanAngle)
  57306. this.update();
  57307. }
  57308. update(quaternion){
  57309. if(!this.show)return;
  57310. if(!quaternion) quaternion = this.viewport.camera.quaternion.clone();
  57311. this.updateCamera(quaternion);
  57312. this.updateLabel(quaternion);
  57313. this.render();
  57314. }
  57315. /*updateLabel(quaternion){//更新北标签
  57316. var dir = viewer.mainViewport.view.direction;
  57317. var oriDir = initDir.clone() //指南针最初始时的北方向
  57318. var extraQua
  57319. if(objects.player.mode == "transitioning"){//当transitioning时,相机的quaternion不是用control的lookAt算出来,而是直接由一个quaternion过渡到另一个,这样相机将会是歪的,投影面也就不会是原先的水平面。
  57320. var tempCamera = new THREE.Camera(); //借用camera的lookAt算出如果正视同样的target, quaternion会是什么值。 将它乘以当前相机quaternion,得到的就是相机歪的旋转值。
  57321. tempCamera.position.copy(this.camera.position);
  57322. tempCamera.lookAt(tempCamera.position.clone().add(dir))
  57323. var q = tempCamera.quaternion.inverse()
  57324. extraQua = q.premultiply(quaternion) //歪掉的额外旋转值
  57325. }
  57326. //北标签的方向为指南针轮盘方向,也就是要将camera的方向投影到水平面上。 但是如果相机歪了,看到的世界都会歪一定角度,投影面也要歪一定角度。
  57327. var up = new THREE.Vector3(0,0,1) //投影水平面的法线,也是相机的摆正的up方向
  57328. extraQua && up.applyQuaternion(extraQua)
  57329. dir.projectOnPlane(up) //将方向投影到水平面上; 如果相机不是正视(extraQua不为0001),就要将水平面也转动
  57330. oriDir.projectOnPlane(up)//为什么initDir投影了和没有投影angle结果一样
  57331. var angle = dir.angleTo(oriDir)
  57332. if(dir.cross(oriDir).y > 0)angle = -angle
  57333. var deg = this.angle - 90 + THREE.Math.radToDeg(angle) //因为css写的样式初始是指向右方,和initDir差了90°,所以减去。
  57334. this.dom.find(".dirText").css( "transform","rotate("+deg+"deg)" )
  57335. this.dom.find(".dirText span").css("transform","rotate("+(-deg)+"deg)")
  57336. } */
  57337. updateLabel(quaternion){//更新北标签
  57338. let deg = MathUtils$1.radToDeg(this.viewport.view.yaw) - 90;
  57339. this.dom.find(".dirText").css( "transform","rotate("+deg+"deg)" );
  57340. this.dom.find(".dirText span").css("transform","rotate("+(-deg)+"deg)");
  57341. }
  57342. updateCamera(quaternion){ //更新canvas中的指南针表现,也就是更新相机,和场景中的相机朝向一致。
  57343. const radius = 5; //相机距离
  57344. this.camera.quaternion.copy(quaternion);
  57345. var dir = this.viewport.view.direction; //相机朝向
  57346. this.camera.position.copy(dir.multiplyScalar(radius).negate()); //相机绕着指南针中心(000)转动
  57347. }
  57348. changeViewport(viewport){
  57349. this.viewport = viewport;
  57350. this.update(); //因相机更新了
  57351. }
  57352. render(){
  57353. this.renderer.render(this.scene, this.camera);
  57354. }
  57355. setDisplay(state){
  57356. this.show = !!state;
  57357. if(this.show){
  57358. this.update();
  57359. this.dom.fadeIn(100);
  57360. }else {
  57361. this.dom.fadeOut(100);
  57362. }
  57363. }
  57364. autoJudgeDisplay(){
  57365. }
  57366. setDomPos(){
  57367. if(!this.viewport)return
  57368. let right = this.viewport.left + this.viewport.width;
  57369. this.dom.css({'right':((1-right)*100 + 1) + '%'});
  57370. }
  57371. }
  57372. // Copied from three.js: WebGLRenderer.js
  57373. function paramThreeToGL$1(_gl, p) {
  57374. let extension;
  57375. if (p === RepeatWrapping) return _gl.REPEAT;
  57376. if (p === ClampToEdgeWrapping) return _gl.CLAMP_TO_EDGE;
  57377. if (p === MirroredRepeatWrapping) return _gl.MIRRORED_REPEAT;
  57378. if (p === NearestFilter) return _gl.NEAREST;
  57379. if (p === NearestMipMapNearestFilter) return _gl.NEAREST_MIPMAP_NEAREST;
  57380. if (p === NearestMipMapLinearFilter) return _gl.NEAREST_MIPMAP_LINEAR;
  57381. if (p === LinearFilter) return _gl.LINEAR;
  57382. if (p === LinearMipMapNearestFilter) return _gl.LINEAR_MIPMAP_NEAREST;
  57383. if (p === LinearMipMapLinearFilter) return _gl.LINEAR_MIPMAP_LINEAR;
  57384. if (p === UnsignedByteType) return _gl.UNSIGNED_BYTE;
  57385. if (p === UnsignedShort4444Type) return _gl.UNSIGNED_SHORT_4_4_4_4;
  57386. if (p === UnsignedShort5551Type) return _gl.UNSIGNED_SHORT_5_5_5_1;
  57387. if (p === UnsignedShort565Type) return _gl.UNSIGNED_SHORT_5_6_5;
  57388. if (p === ByteType) return _gl.BYTE;
  57389. if (p === ShortType) return _gl.SHORT;
  57390. if (p === UnsignedShortType) return _gl.UNSIGNED_SHORT;
  57391. if (p === IntType) return _gl.INT;
  57392. if (p === UnsignedIntType) return _gl.UNSIGNED_INT;
  57393. if (p === FloatType) return _gl.FLOAT;
  57394. if (p === HalfFloatType) {
  57395. extension = extensions.get('OES_texture_half_float');
  57396. if (extension !== null) return extension.HALF_FLOAT_OES;
  57397. }
  57398. if (p === AlphaFormat) return _gl.ALPHA;
  57399. if (p === RGBFormat) return _gl.RGB;
  57400. if (p === RGBAFormat) return _gl.RGBA;
  57401. if (p === LuminanceFormat) return _gl.LUMINANCE;
  57402. if (p === LuminanceAlphaFormat) return _gl.LUMINANCE_ALPHA;
  57403. if (p === DepthFormat) return _gl.DEPTH_COMPONENT;
  57404. if (p === DepthStencilFormat) return _gl.DEPTH_STENCIL;
  57405. if (p === AddEquation) return _gl.FUNC_ADD;
  57406. if (p === SubtractEquation) return _gl.FUNC_SUBTRACT;
  57407. if (p === ReverseSubtractEquation) return _gl.FUNC_REVERSE_SUBTRACT;
  57408. if (p === ZeroFactor) return _gl.ZERO;
  57409. if (p === OneFactor) return _gl.ONE;
  57410. if (p === SrcColorFactor) return _gl.SRC_COLOR;
  57411. if (p === OneMinusSrcColorFactor) return _gl.ONE_MINUS_SRC_COLOR;
  57412. if (p === SrcAlphaFactor) return _gl.SRC_ALPHA;
  57413. if (p === OneMinusSrcAlphaFactor) return _gl.ONE_MINUS_SRC_ALPHA;
  57414. if (p === DstAlphaFactor) return _gl.DST_ALPHA;
  57415. if (p === OneMinusDstAlphaFactor) return _gl.ONE_MINUS_DST_ALPHA;
  57416. if (p === DstColorFactor) return _gl.DST_COLOR;
  57417. if (p === OneMinusDstColorFactor) return _gl.ONE_MINUS_DST_COLOR;
  57418. if (p === SrcAlphaSaturateFactor) return _gl.SRC_ALPHA_SATURATE;
  57419. if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
  57420. p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
  57421. extension = extensions.get('WEBGL_compressed_texture_s3tc');
  57422. if (extension !== null) {
  57423. if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
  57424. if (p === RGBA_S3TC_DXT1_Format$1) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
  57425. if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
  57426. if (p === RGBA_S3TC_DXT5_Format$1) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
  57427. }
  57428. }
  57429. if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
  57430. p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
  57431. extension = extensions.get('WEBGL_compressed_texture_pvrtc');
  57432. if (extension !== null) {
  57433. if (p === RGB_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  57434. if (p === RGB_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  57435. if (p === RGBA_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  57436. if (p === RGBA_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  57437. }
  57438. }
  57439. if (p === RGB_ETC1_Format) {
  57440. extension = extensions.get('WEBGL_compressed_texture_etc1');
  57441. if (extension !== null) return extension.COMPRESSED_RGB_ETC1_WEBGL;
  57442. }
  57443. if (p === MinEquation || p === MaxEquation) {
  57444. extension = extensions.get('EXT_blend_minmax');
  57445. if (extension !== null) {
  57446. if (p === MinEquation) return extension.MIN_EXT;
  57447. if (p === MaxEquation) return extension.MAX_EXT;
  57448. }
  57449. }
  57450. if (p === UnsignedInt248Type) {
  57451. extension = extensions.get('WEBGL_depth_texture');
  57452. if (extension !== null) return extension.UNSIGNED_INT_24_8_WEBGL;
  57453. }
  57454. return 0;
  57455. };
  57456. let attributeLocations$1 = {
  57457. "position": {name: "position", location: 0},
  57458. "color": {name: "color", location: 1},
  57459. "rgba": {name: "color", location: 1},
  57460. "intensity": {name: "intensity", location: 2},
  57461. "classification": {name: "classification", location: 3},
  57462. "returnNumber": {name: "returnNumber", location: 4},
  57463. "return number": {name: "returnNumber", location: 4},
  57464. "returns": {name: "returnNumber", location: 4},
  57465. "numberOfReturns": {name: "numberOfReturns", location: 5},
  57466. "number of returns": {name: "numberOfReturns", location: 5},
  57467. "pointSourceID": {name: "pointSourceID", location: 6},
  57468. "source id": {name: "pointSourceID", location: 6},
  57469. "point source id": {name: "pointSourceID", location: 6},
  57470. "indices": {name: "indices", location: 7},
  57471. "normal": {name: "normal", location: 8},
  57472. "spacing": {name: "spacing", location: 9},
  57473. "gps-time": {name: "gpsTime", location: 10},
  57474. "aExtra": {name: "aExtra", location: 11},
  57475. };
  57476. class Shader$1 {
  57477. constructor(gl, name, vsSource, fsSource) {
  57478. this.gl = gl;
  57479. this.name = name;
  57480. this.vsSource = vsSource;
  57481. this.fsSource = fsSource;
  57482. this.cache = new Map();
  57483. this.vs = null;
  57484. this.fs = null;
  57485. this.program = null;
  57486. this.uniformLocations = {};
  57487. this.attributeLocations = {};
  57488. this.uniformBlockIndices = {};
  57489. this.uniformBlocks = {};
  57490. this.uniforms = {};
  57491. this.update(vsSource, fsSource);
  57492. }
  57493. update(vsSource, fsSource) {
  57494. this.vsSource = vsSource;
  57495. this.fsSource = fsSource;
  57496. this.linkProgram();
  57497. }
  57498. compileShader(shader, source){
  57499. let gl = this.gl;
  57500. gl.shaderSource(shader, source);
  57501. gl.compileShader(shader);
  57502. let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  57503. if (!success) {
  57504. let info = gl.getShaderInfoLog(shader);
  57505. let numberedSource = source.split("\n").map((a, i) => `${i + 1}`.padEnd(5) + a).join("\n");
  57506. throw `could not compile shader ${this.name}: ${info}, \n${numberedSource}`;
  57507. }
  57508. }
  57509. linkProgram() {
  57510. const tStart = performance.now();
  57511. let gl = this.gl;
  57512. this.uniformLocations = {};
  57513. this.attributeLocations = {};
  57514. this.uniforms = {};
  57515. gl.useProgram(null);
  57516. let cached = this.cache.get(`${this.vsSource}, ${this.fsSource}`);
  57517. if (cached) {
  57518. this.program = cached.program;
  57519. this.vs = cached.vs;
  57520. this.fs = cached.fs;
  57521. this.attributeLocations = cached.attributeLocations;
  57522. this.uniformLocations = cached.uniformLocations;
  57523. this.uniformBlocks = cached.uniformBlocks;
  57524. this.uniforms = cached.uniforms;
  57525. return;
  57526. } else {
  57527. this.vs = gl.createShader(gl.VERTEX_SHADER);
  57528. this.fs = gl.createShader(gl.FRAGMENT_SHADER);
  57529. this.program = gl.createProgram();
  57530. if( !gl.isProgram(this.program )){//创建失败 开启多个页面可能会,原因是webglcontextlost
  57531. //console.error('创建program失败');
  57532. viewer.dispatchEvent('webglError', {msg: 'potreeRenderer创建program失败'});
  57533. console.log(this.vs);
  57534. console.log(this.fs);
  57535. return;
  57536. }
  57537. for(let name of Object.keys(attributeLocations$1)){
  57538. let location = attributeLocations$1[name].location;
  57539. let glslName = attributeLocations$1[name].name;
  57540. gl.bindAttribLocation(this.program, location, glslName);
  57541. }
  57542. this.compileShader(this.vs, this.vsSource);
  57543. this.compileShader(this.fs, this.fsSource);
  57544. let program = this.program;
  57545. gl.attachShader(program, this.vs);
  57546. gl.attachShader(program, this.fs);
  57547. gl.linkProgram(program);
  57548. gl.detachShader(program, this.vs);
  57549. gl.detachShader(program, this.fs);
  57550. // 检测当前程序链接状态
  57551. let success = gl.getProgramParameter(program, gl.LINK_STATUS);
  57552. if (!success) {
  57553. let info = gl.getProgramInfoLog(program);
  57554. throw `could not link program ${this.name}: ${info}`;
  57555. }
  57556. { // attribute locations
  57557. let numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
  57558. for (let i = 0; i < numAttributes; i++) {
  57559. let attribute = gl.getActiveAttrib(program, i);
  57560. let location = gl.getAttribLocation(program, attribute.name);
  57561. this.attributeLocations[attribute.name] = location;
  57562. }
  57563. }
  57564. { // uniform locations
  57565. let numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  57566. for (let i = 0; i < numUniforms; i++) {
  57567. let uniform = gl.getActiveUniform(program, i);
  57568. let location = gl.getUniformLocation(program, uniform.name);
  57569. this.uniformLocations[uniform.name] = location;
  57570. this.uniforms[uniform.name] = {
  57571. location: location,
  57572. value: null,
  57573. };
  57574. }
  57575. }
  57576. // uniform blocks
  57577. if( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext){ //WebGL2RenderingContext在mac的safari14以下是没有定义的
  57578. let numBlocks = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
  57579. for (let i = 0; i < numBlocks; i++) {
  57580. let blockName = gl.getActiveUniformBlockName(program, i);
  57581. let blockIndex = gl.getUniformBlockIndex(program, blockName);
  57582. this.uniformBlockIndices[blockName] = blockIndex;
  57583. gl.uniformBlockBinding(program, blockIndex, blockIndex);
  57584. let dataSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
  57585. let uBuffer = gl.createBuffer();
  57586. gl.bindBuffer(gl.UNIFORM_BUFFER, uBuffer);
  57587. gl.bufferData(gl.UNIFORM_BUFFER, dataSize, gl.DYNAMIC_READ);
  57588. gl.bindBufferBase(gl.UNIFORM_BUFFER, blockIndex, uBuffer);
  57589. gl.bindBuffer(gl.UNIFORM_BUFFER, null);
  57590. this.uniformBlocks[blockName] = {
  57591. name: blockName,
  57592. index: blockIndex,
  57593. dataSize: dataSize,
  57594. buffer: uBuffer
  57595. };
  57596. }
  57597. }
  57598. let cached = {
  57599. program: this.program,
  57600. vs: this.vs,
  57601. fs: this.fs,
  57602. attributeLocations: this.attributeLocations,
  57603. uniformLocations: this.uniformLocations,
  57604. uniforms: this.uniforms,
  57605. uniformBlocks: this.uniformBlocks,
  57606. };
  57607. this.cache.set(`${this.vsSource}, ${this.fsSource}`, cached);
  57608. }
  57609. const tEnd = performance.now();
  57610. const duration = tEnd - tStart;
  57611. //console.log(`shader compile duration: ${duration.toFixed(3)}`);
  57612. }
  57613. setUniformMatrix4(name, value) {
  57614. const gl = this.gl;
  57615. const location = this.uniformLocations[name];
  57616. if (location == null) {
  57617. return;
  57618. }
  57619. let tmp = new Float32Array(value.elements);
  57620. gl.uniformMatrix4fv(location, false, tmp);
  57621. }
  57622. setUniform1f(name, value) {
  57623. const gl = this.gl;
  57624. const uniform = this.uniforms[name];
  57625. if (uniform === undefined) {
  57626. return;
  57627. }
  57628. if(uniform.value === value){
  57629. return;
  57630. }
  57631. uniform.value = value;
  57632. gl.uniform1f(uniform.location, value);
  57633. }
  57634. setUniformBoolean(name, value) {
  57635. const gl = this.gl;
  57636. const uniform = this.uniforms[name];
  57637. if (uniform === undefined) {
  57638. return;
  57639. }
  57640. if(uniform.value === value){
  57641. return;
  57642. }
  57643. uniform.value = value;
  57644. gl.uniform1i(uniform.location, value);
  57645. }
  57646. setUniformTexture(name, value) {
  57647. const gl = this.gl;
  57648. const location = this.uniformLocations[name];
  57649. if (location == null) {
  57650. return;
  57651. }
  57652. gl.uniform1i(location, value);
  57653. }
  57654. setUniform2f(name, value) {
  57655. const gl = this.gl;
  57656. const location = this.uniformLocations[name];
  57657. if (location == null) {
  57658. return;
  57659. }
  57660. gl.uniform2f(location, value[0], value[1]);
  57661. }
  57662. setUniform3f(name, value) {
  57663. const gl = this.gl;
  57664. const location = this.uniformLocations[name];
  57665. if (location == null) {
  57666. return;
  57667. }
  57668. gl.uniform3f(location, value[0], value[1], value[2]);
  57669. }
  57670. setUniform(name, value) {
  57671. if (value.constructor === Matrix4) {
  57672. this.setUniformMatrix4(name, value);
  57673. } else if (typeof value === "number") {
  57674. this.setUniform1f(name, value);
  57675. } else if (typeof value === "boolean") {
  57676. this.setUniformBoolean(name, value);
  57677. } else if (value instanceof WebGLTexture$1) {
  57678. this.setUniformTexture(name, value);
  57679. } else if (value instanceof Array) {
  57680. if (value.length === 2) {
  57681. this.setUniform2f(name, value);
  57682. } else if (value.length === 3) {
  57683. this.setUniform3f(name, value);
  57684. }
  57685. } else {
  57686. console.error("unhandled uniform type: ", name, value);
  57687. }
  57688. }
  57689. setUniform1i(name, value) {
  57690. let gl = this.gl;
  57691. let location = this.uniformLocations[name];
  57692. if (location == null) {
  57693. return;
  57694. }
  57695. gl.uniform1i(location, value);
  57696. }
  57697. };
  57698. class WebGLTexture$1 {
  57699. constructor(gl, texture) {
  57700. this.gl = gl;
  57701. this.texture = texture;
  57702. this.id = gl.createTexture();
  57703. this.target = gl.TEXTURE_2D;
  57704. this.version = -1;
  57705. this.update(texture);
  57706. }
  57707. update() {
  57708. if (!this.texture.image) {
  57709. this.version = this.texture.version;
  57710. return;
  57711. }
  57712. let gl = this.gl;
  57713. let texture = this.texture;
  57714. if (this.version === texture.version) {
  57715. return;
  57716. }
  57717. this.target = gl.TEXTURE_2D;
  57718. gl.bindTexture(this.target, this.id);
  57719. let level = 0;
  57720. let internalFormat = paramThreeToGL$1(gl, texture.format);
  57721. let width = texture.image.width;
  57722. let height = texture.image.height;
  57723. let border = 0;
  57724. let srcFormat = internalFormat;
  57725. let srcType = paramThreeToGL$1(gl, texture.type);
  57726. let data;
  57727. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
  57728. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha);
  57729. gl.pixelStorei(gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
  57730. if (texture instanceof DataTexture) {
  57731. data = texture.image.data;
  57732. gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  57733. gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  57734. gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, paramThreeToGL$1(gl, texture.magFilter));
  57735. gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, paramThreeToGL$1(gl, texture.minFilter));
  57736. gl.texImage2D(this.target, level, internalFormat,
  57737. width, height, border, srcFormat, srcType,
  57738. data);
  57739. } else if ((texture instanceof CanvasTexture) || (texture instanceof Texture)) {
  57740. data = texture.image;
  57741. gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, paramThreeToGL$1(gl, texture.wrapS));
  57742. gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, paramThreeToGL$1(gl, texture.wrapT));
  57743. gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, paramThreeToGL$1(gl, texture.magFilter));
  57744. gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, paramThreeToGL$1(gl, texture.minFilter));
  57745. gl.texImage2D(this.target, level, internalFormat,
  57746. internalFormat, srcType, data);
  57747. if (texture instanceof Texture) {gl.generateMipmap(gl.TEXTURE_2D);}
  57748. }
  57749. gl.bindTexture(this.target, null);
  57750. this.version = texture.version;
  57751. }
  57752. };
  57753. class WebGLBuffer$1 {
  57754. constructor() {
  57755. this.numElements = 0;
  57756. this.vao = null;
  57757. this.vbos = new Map();
  57758. }
  57759. };
  57760. class Renderer$1 {
  57761. constructor(threeRenderer) {
  57762. this.threeRenderer = threeRenderer;
  57763. this.gl = this.threeRenderer.getContext();
  57764. this.buffers = new Map();
  57765. this.shaders = new Map();
  57766. this.textures = new Map();
  57767. this.glTypeMapping = new Map();
  57768. this.glTypeMapping.set(Float32Array, this.gl.FLOAT);
  57769. this.glTypeMapping.set(Uint8Array, this.gl.UNSIGNED_BYTE);
  57770. this.glTypeMapping.set(Uint16Array, this.gl.UNSIGNED_SHORT);
  57771. this.toggle = 0;
  57772. }
  57773. deleteBuffer(geometry) {
  57774. let gl = this.gl;
  57775. let webglBuffer = this.buffers.get(geometry);
  57776. if (webglBuffer != null) {
  57777. for (let attributeName in geometry.attributes) {
  57778. gl.deleteBuffer(webglBuffer.vbos.get(attributeName).handle);
  57779. }
  57780. this.buffers.delete(geometry);
  57781. }
  57782. }
  57783. createBuffer(geometry){
  57784. let gl = this.gl;
  57785. let webglBuffer = new WebGLBuffer$1();
  57786. webglBuffer.vao = gl.createVertexArray();
  57787. webglBuffer.numElements = geometry.attributes.position.count;
  57788. gl.bindVertexArray(webglBuffer.vao);
  57789. for(let attributeName in geometry.attributes){
  57790. let bufferAttribute = geometry.attributes[attributeName];
  57791. let vbo = gl.createBuffer();
  57792. gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  57793. gl.bufferData(gl.ARRAY_BUFFER, bufferAttribute.array, gl.STATIC_DRAW);
  57794. let normalized = bufferAttribute.normalized;
  57795. let type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  57796. if(attributeLocations$1[attributeName] === undefined){
  57797. //attributeLocation = attributeLocations["aExtra"];
  57798. }else {
  57799. let attributeLocation = attributeLocations$1[attributeName].location;
  57800. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  57801. gl.enableVertexAttribArray(attributeLocation);
  57802. }
  57803. webglBuffer.vbos.set(attributeName, {
  57804. handle: vbo,
  57805. name: attributeName,
  57806. count: bufferAttribute.count,
  57807. itemSize: bufferAttribute.itemSize,
  57808. type: geometry.attributes.position.array.constructor,
  57809. version: 0
  57810. });
  57811. }
  57812. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  57813. gl.bindVertexArray(null);
  57814. let disposeHandler = (event) => {
  57815. this.deleteBuffer(geometry);
  57816. geometry.removeEventListener("dispose", disposeHandler);
  57817. };
  57818. geometry.addEventListener("dispose", disposeHandler);
  57819. return webglBuffer;
  57820. }
  57821. updateBuffer(geometry){
  57822. let gl = this.gl;
  57823. let webglBuffer = this.buffers.get(geometry);
  57824. gl.bindVertexArray(webglBuffer.vao);
  57825. for(let attributeName in geometry.attributes){
  57826. let bufferAttribute = geometry.attributes[attributeName];
  57827. let normalized = bufferAttribute.normalized;
  57828. let type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  57829. let vbo = null;
  57830. if(!webglBuffer.vbos.has(attributeName)){
  57831. vbo = gl.createBuffer();
  57832. webglBuffer.vbos.set(attributeName, {
  57833. handle: vbo,
  57834. name: attributeName,
  57835. count: bufferAttribute.count,
  57836. itemSize: bufferAttribute.itemSize,
  57837. type: geometry.attributes.position.array.constructor,
  57838. version: bufferAttribute.version
  57839. });
  57840. }else {
  57841. vbo = webglBuffer.vbos.get(attributeName).handle;
  57842. webglBuffer.vbos.get(attributeName).version = bufferAttribute.version;
  57843. }
  57844. gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  57845. gl.bufferData(gl.ARRAY_BUFFER, bufferAttribute.array, gl.STATIC_DRAW);
  57846. if(attributeLocations$1[attributeName] === undefined){
  57847. //attributeLocation = attributeLocations["aExtra"];
  57848. }else {
  57849. let attributeLocation = attributeLocations$1[attributeName].location;
  57850. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  57851. gl.enableVertexAttribArray(attributeLocation);
  57852. }
  57853. }
  57854. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  57855. gl.bindVertexArray(null);
  57856. }
  57857. traverse(scene) {
  57858. let octrees = [];
  57859. let stack = [scene];
  57860. while (stack.length > 0) {
  57861. let node = stack.pop();
  57862. if (node instanceof PointCloudTree) {
  57863. octrees.push(node);
  57864. continue;
  57865. }
  57866. let visibleChildren = node.children.filter(c => c.visible);
  57867. stack.push(...visibleChildren);
  57868. }
  57869. let result = {
  57870. octrees: octrees
  57871. };
  57872. return result;
  57873. }
  57874. renderNodes(octree, nodes, visibilityTextureData, camera, target, shader, params) {
  57875. viewer.addTimeMark('renderNodes','start');
  57876. let gl = this.gl;
  57877. let material = params.material ? params.material : octree.material;
  57878. let shadowMaps = params.shadowMaps == null ? [] : params.shadowMaps;
  57879. let view = camera.matrixWorldInverse;
  57880. if(params.viewOverride){
  57881. view = params.viewOverride;
  57882. }
  57883. let worldView = new Matrix4();
  57884. let mat4holder = new Float32Array(16);
  57885. let i = 0;
  57886. //---------从renderOctree搬到这----
  57887. shader.setUniform1f("size", material.usePanoMap ? Potree.config.material.absolutePanoramaSize * Math.min(window.devicePixelRatio,2) : material.size);//usePanoMap时控制在不大不小的范围内感觉较好,考虑到有的点云稀疏,用大一点的点
  57888. shader.setUniform1f("uOpacity", material.usePanoMap ? 1: material.opacity);
  57889. shader.setUniform3f("uColor", material.color.toArray());
  57890. /* let currentTextureBindingPoint = params.currentTextureBindingPoint
  57891. if (material.pointSizeType >= 0 && window.needvisibilityTexture) {
  57892. if (material.pointSizeType === PointSizeType.ADAPTIVE ||
  57893. material.activeAttributeName === "level of detail") {
  57894. let vnNodes = (params.vnTextureNodes != null) ? params.vnTextureNodes : nodes;
  57895. visibilityTextureData = octree.computeVisibilityTextureData(vnNodes, camera);
  57896. const vnt = material.visibleNodesTexture;
  57897. const data = vnt.image.data;
  57898. data.set(visibilityTextureData.data);
  57899. vnt.needsUpdate = true;
  57900. let vnWebGLTexture = this.textures.get(material.visibleNodesTexture); //不知道为什么这段从renderOctree中移过来,会崩溃。暂时不移动了
  57901. if(vnWebGLTexture){
  57902. shader.setUniform1i("visibleNodes", currentTextureBindingPoint);
  57903. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  57904. gl.bindTexture(vnWebGLTexture.target, vnWebGLTexture.id);
  57905. currentTextureBindingPoint++;
  57906. }
  57907. }
  57908. } */
  57909. let transparent = false;
  57910. if(params.transparent !== undefined){
  57911. transparent = params.transparent && material.opacity < 1;
  57912. }else {
  57913. transparent = material.usePanoMap ? false : (material.useFilterByNormal || material.opacity < 1); //add useFilterByNormal
  57914. }
  57915. if (transparent){
  57916. gl.enable(gl.BLEND);
  57917. if(params.notAdditiveBlending){
  57918. gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); //NormalBlending
  57919. gl.enable(gl.DEPTH_TEST);
  57920. gl.depthMask(true); //如果不开启depthWrite,深度会错乱。
  57921. }else {
  57922. gl.blendFunc(gl.SRC_ALPHA, gl.ONE); //AdditiveBlending 原本
  57923. gl.disable(gl.DEPTH_TEST);
  57924. gl.depthMask(false);
  57925. }
  57926. } else {
  57927. gl.disable(gl.BLEND);
  57928. gl.depthMask(true);
  57929. gl.enable(gl.DEPTH_TEST);
  57930. }
  57931. if(params.blendFunc !== undefined){
  57932. gl.enable(gl.BLEND);
  57933. gl.blendFunc(...params.blendFunc);
  57934. }
  57935. if(params.depthTest !== undefined){
  57936. if(params.depthTest === true){
  57937. gl.enable(gl.DEPTH_TEST);
  57938. }else {
  57939. gl.disable(gl.DEPTH_TEST);
  57940. }
  57941. }
  57942. if(params.depthWrite !== undefined){
  57943. if(params.depthWrite === true){
  57944. gl.depthMask(true);
  57945. }else {
  57946. gl.depthMask(false);
  57947. }
  57948. }
  57949. //---------------------------------
  57950. for (let node of nodes) {
  57951. if(exports.debug.allowedNodes !== undefined){
  57952. if(!exports.debug.allowedNodes.includes(node.name)){
  57953. continue;
  57954. }
  57955. }
  57956. let world = node.sceneNode.matrixWorld;
  57957. worldView.multiplyMatrices(view, world);
  57958. if (visibilityTextureData) {
  57959. let vnStart = visibilityTextureData.offsets.get(node);
  57960. console.log('vnStart',vnStart);
  57961. shader.setUniform1f("uVNStart", vnStart);
  57962. }
  57963. let level = node.getLevel();
  57964. if(node.debug){
  57965. shader.setUniform("uDebug", true);
  57966. }else {
  57967. shader.setUniform("uDebug", false);
  57968. }
  57969. // let isLeaf = false;
  57970. // if(node instanceof PointCloudOctreeNode){
  57971. // isLeaf = Object.keys(node.children).length === 0;
  57972. // }else if(node instanceof PointCloudArena4DNode){
  57973. // isLeaf = node.geometryNode.isLeaf;
  57974. // }
  57975. // shader.setUniform("uIsLeafNode", isLeaf);
  57976. // let isLeaf = node.children.filter(n => n != null).length === 0;
  57977. // if(!isLeaf){
  57978. // continue;
  57979. // }
  57980. // TODO consider passing matrices in an array to avoid uniformMatrix4fv overhead
  57981. const lModel = shader.uniformLocations["modelMatrix"];
  57982. if (lModel) {
  57983. mat4holder.set(world.elements);
  57984. gl.uniformMatrix4fv(lModel, false, mat4holder);
  57985. }
  57986. const lModelView = shader.uniformLocations["modelViewMatrix"];
  57987. //mat4holder.set(worldView.elements);
  57988. // faster then set in chrome 63
  57989. for(let j = 0; j < 16; j++){
  57990. mat4holder[j] = worldView.elements[j];
  57991. }
  57992. gl.uniformMatrix4fv(lModelView, false, mat4holder);
  57993. { // Clip Polygons
  57994. if(material.clipPolygons && material.clipPolygons.length > 0){
  57995. let clipPolygonVCount = [];
  57996. let worldViewProjMatrices = [];
  57997. for(let clipPolygon of material.clipPolygons){
  57998. let view = clipPolygon.viewMatrix;
  57999. let proj = clipPolygon.projMatrix;
  58000. let worldViewProj = proj.clone().multiply(view).multiply(world);
  58001. clipPolygonVCount.push(clipPolygon.markers.length);
  58002. worldViewProjMatrices.push(worldViewProj);
  58003. }
  58004. let flattenedMatrices = [].concat(...worldViewProjMatrices.map(m => m.elements));
  58005. let flattenedVertices = new Array(8 * 3 * material.clipPolygons.length);
  58006. for(let i = 0; i < material.clipPolygons.length; i++){
  58007. let clipPolygon = material.clipPolygons[i];
  58008. for(let j = 0; j < clipPolygon.markers.length; j++){
  58009. flattenedVertices[i * 24 + (j * 3 + 0)] = clipPolygon.markers[j].position.x;
  58010. flattenedVertices[i * 24 + (j * 3 + 1)] = clipPolygon.markers[j].position.y;
  58011. flattenedVertices[i * 24 + (j * 3 + 2)] = clipPolygon.markers[j].position.z;
  58012. }
  58013. }
  58014. const lClipPolygonVCount = shader.uniformLocations["uClipPolygonVCount[0]"];
  58015. gl.uniform1iv(lClipPolygonVCount, clipPolygonVCount);
  58016. const lClipPolygonVP = shader.uniformLocations["uClipPolygonWVP[0]"];
  58017. gl.uniformMatrix4fv(lClipPolygonVP, false, flattenedMatrices);
  58018. const lClipPolygons = shader.uniformLocations["uClipPolygonVertices[0]"];
  58019. gl.uniform3fv(lClipPolygons, flattenedVertices);
  58020. }
  58021. }
  58022. //shader.setUniformMatrix4("modelMatrix", world);
  58023. //shader.setUniformMatrix4("modelViewMatrix", worldView);
  58024. shader.setUniform1f("uLevel", level);
  58025. shader.setUniform1f("uNodeSpacing", node.geometryNode.estimatedSpacing);
  58026. shader.setUniform1f("uPCIndex", i);
  58027. // uBBSize
  58028. if (shadowMaps.length > 0) {
  58029. const lShadowMap = shader.uniformLocations["uShadowMap[0]"];
  58030. shader.setUniform3f("uShadowColor", material.uniforms.uShadowColor.value);
  58031. let bindingStart = 5;
  58032. let bindingPoints = new Array(shadowMaps.length).fill(bindingStart).map((a, i) => (a + i));
  58033. gl.uniform1iv(lShadowMap, bindingPoints);
  58034. for (let i = 0; i < shadowMaps.length; i++) {
  58035. let shadowMap = shadowMaps[i];
  58036. let bindingPoint = bindingPoints[i];
  58037. let glTexture = this.threeRenderer.properties.get(shadowMap.target.texture).__webglTexture;
  58038. gl.activeTexture(gl[`TEXTURE${bindingPoint}`]);
  58039. gl.bindTexture(gl.TEXTURE_2D, glTexture);
  58040. }
  58041. {
  58042. let worldViewMatrices = shadowMaps
  58043. .map(sm => sm.camera.matrixWorldInverse)
  58044. .map(view => new Matrix4().multiplyMatrices(view, world));
  58045. let flattenedMatrices = [].concat(...worldViewMatrices.map(c => c.elements));
  58046. const lWorldView = shader.uniformLocations["uShadowWorldView[0]"];
  58047. gl.uniformMatrix4fv(lWorldView, false, flattenedMatrices);
  58048. }
  58049. {
  58050. let flattenedMatrices = [].concat(...shadowMaps.map(sm => sm.camera.projectionMatrix.elements));
  58051. const lProj = shader.uniformLocations["uShadowProj[0]"];
  58052. gl.uniformMatrix4fv(lProj, false, flattenedMatrices);
  58053. }
  58054. }
  58055. const geometry = node.geometryNode.geometry;
  58056. if(geometry.attributes["gps-time"]){
  58057. const bufferAttribute = geometry.attributes["gps-time"];
  58058. const attGPS = octree.getAttribute("gps-time");
  58059. let initialRange = attGPS.initialRange;
  58060. let initialRangeSize = initialRange[1] - initialRange[0];
  58061. let globalRange = attGPS.range;
  58062. let globalRangeSize = globalRange[1] - globalRange[0];
  58063. let scale = initialRangeSize / globalRangeSize;
  58064. let offset = -(globalRange[0] - initialRange[0]) / initialRangeSize;
  58065. scale = Number.isNaN(scale) ? 1 : scale;
  58066. offset = Number.isNaN(offset) ? 0 : offset;
  58067. shader.setUniform1f("uGpsScale", scale);
  58068. shader.setUniform1f("uGpsOffset", offset);
  58069. //shader.setUniform2f("uFilterGPSTimeClipRange", [-Infinity, Infinity]);
  58070. let uFilterGPSTimeClipRange = material.uniforms.uFilterGPSTimeClipRange.value;
  58071. // let gpsCliPRangeMin = uFilterGPSTimeClipRange[0]
  58072. // let gpsCliPRangeMax = uFilterGPSTimeClipRange[1]
  58073. // shader.setUniform2f("uFilterGPSTimeClipRange", [gpsCliPRangeMin, gpsCliPRangeMax]);
  58074. let normalizedClipRange = [
  58075. (uFilterGPSTimeClipRange[0] - globalRange[0]) / globalRangeSize,
  58076. (uFilterGPSTimeClipRange[1] - globalRange[0]) / globalRangeSize,
  58077. ];
  58078. shader.setUniform2f("uFilterGPSTimeClipRange", normalizedClipRange);
  58079. // // ranges in full gps coordinate system
  58080. // const globalRange = attGPS.range;
  58081. // const bufferRange = bufferAttribute.potree.range;
  58082. // // ranges in [0, 1]
  58083. // // normalizedGlobalRange = [0, 1]
  58084. // // normalizedBufferRange: norm buffer within norm global range e.g. [0.2, 0.8]
  58085. // const globalWidth = globalRange[1] - globalRange[0];
  58086. // const normalizedBufferRange = [
  58087. // (bufferRange[0] - globalRange[0]) / globalWidth,
  58088. // (bufferRange[1] - globalRange[0]) / globalWidth,
  58089. // ];
  58090. // shader.setUniform2f("uNormalizedGpsBufferRange", normalizedBufferRange);
  58091. // let uFilterGPSTimeClipRange = material.uniforms.uFilterGPSTimeClipRange.value;
  58092. // let gpsCliPRangeMin = uFilterGPSTimeClipRange[0]
  58093. // let gpsCliPRangeMax = uFilterGPSTimeClipRange[1]
  58094. // shader.setUniform2f("uFilterGPSTimeClipRange", [gpsCliPRangeMin, gpsCliPRangeMax]);
  58095. // shader.setUniform1f("uGpsScale", bufferAttribute.potree.scale);
  58096. // shader.setUniform1f("uGpsOffset", bufferAttribute.potree.offset);
  58097. }
  58098. {
  58099. let uFilterReturnNumberRange = material.uniforms.uFilterReturnNumberRange.value;
  58100. let uFilterNumberOfReturnsRange = material.uniforms.uFilterNumberOfReturnsRange.value;
  58101. let uFilterPointSourceIDClipRange = material.uniforms.uFilterPointSourceIDClipRange.value;
  58102. shader.setUniform2f("uFilterReturnNumberRange", uFilterReturnNumberRange);
  58103. shader.setUniform2f("uFilterNumberOfReturnsRange", uFilterNumberOfReturnsRange);
  58104. shader.setUniform2f("uFilterPointSourceIDClipRange", uFilterPointSourceIDClipRange);
  58105. }
  58106. let webglBuffer = null;
  58107. if(!this.buffers.has(geometry)){
  58108. webglBuffer = this.createBuffer(geometry);
  58109. this.buffers.set(geometry, webglBuffer);
  58110. }else {
  58111. webglBuffer = this.buffers.get(geometry);
  58112. for(let attributeName in geometry.attributes){
  58113. let attribute = geometry.attributes[attributeName];
  58114. if(attribute.version > webglBuffer.vbos.get(attributeName).version){
  58115. this.updateBuffer(geometry);
  58116. }
  58117. }
  58118. }
  58119. gl.bindVertexArray(webglBuffer.vao);
  58120. let isExtraAttribute =
  58121. attributeLocations$1[material.activeAttributeName] === undefined
  58122. && Object.keys(geometry.attributes).includes(material.activeAttributeName);
  58123. if(isExtraAttribute){
  58124. const attributeLocation = attributeLocations$1["aExtra"].location;
  58125. for(const attributeName in geometry.attributes){
  58126. const bufferAttribute = geometry.attributes[attributeName];
  58127. const vbo = webglBuffer.vbos.get(attributeName);
  58128. gl.bindBuffer(gl.ARRAY_BUFFER, vbo.handle);
  58129. gl.disableVertexAttribArray(attributeLocation);
  58130. }
  58131. const attName = material.activeAttributeName;
  58132. const bufferAttribute = geometry.attributes[attName];
  58133. const vbo = webglBuffer.vbos.get(attName);
  58134. if(bufferAttribute !== undefined && vbo !== undefined){
  58135. let type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  58136. let normalized = bufferAttribute.normalized;
  58137. gl.bindBuffer(gl.ARRAY_BUFFER, vbo.handle);
  58138. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  58139. gl.enableVertexAttribArray(attributeLocation);
  58140. }
  58141. {
  58142. const attExtra = octree.pcoGeometry.pointAttributes.attributes
  58143. .find(a => a.name === attName);
  58144. let range = material.getRange(attName);
  58145. if(!range){
  58146. range = attExtra.range;
  58147. }
  58148. if(!range){
  58149. range = [0, 1];
  58150. }
  58151. let initialRange = attExtra.initialRange;
  58152. let initialRangeSize = initialRange[1] - initialRange[0];
  58153. let globalRange = range;
  58154. let globalRangeSize = globalRange[1] - globalRange[0];
  58155. let scale = initialRangeSize / globalRangeSize;
  58156. let offset = -(globalRange[0] - initialRange[0]) / initialRangeSize;
  58157. scale = Number.isNaN(scale) ? 1 : scale;
  58158. offset = Number.isNaN(offset) ? 0 : offset;
  58159. shader.setUniform1f("uExtraScale", scale);
  58160. shader.setUniform1f("uExtraOffset", offset);
  58161. }
  58162. }else {
  58163. for(const attributeName in geometry.attributes){
  58164. const bufferAttribute = geometry.attributes[attributeName];
  58165. const vbo = webglBuffer.vbos.get(attributeName);
  58166. if(attributeLocations$1[attributeName] !== undefined){
  58167. const attributeLocation = attributeLocations$1[attributeName].location;
  58168. let type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  58169. let normalized = bufferAttribute.normalized;
  58170. gl.bindBuffer(gl.ARRAY_BUFFER, vbo.handle);
  58171. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  58172. gl.enableVertexAttribArray(attributeLocation);
  58173. }
  58174. }
  58175. }
  58176. let numPoints = webglBuffer.numElements;
  58177. gl.drawArrays(gl.POINTS, 0, numPoints);
  58178. //gl.drawArrays(gl.TRIANGLES, 0, numPoints);
  58179. i++;
  58180. }
  58181. gl.bindVertexArray(null);
  58182. viewer.addTimeMark('renderNodes','end');
  58183. }
  58184. renderOctree(octrees, nodes, camera, target, params = {}){
  58185. viewer.addTimeMark('renderOctree','start');
  58186. let octree;
  58187. if(octrees instanceof Array){
  58188. octree = octrees[0];
  58189. }else {
  58190. octree = octrees; octrees = [octree];
  58191. }
  58192. let gl = this.gl;
  58193. let material = params.material ? params.material : octree.material;
  58194. let shadowMaps = params.shadowMaps == null ? [] : params.shadowMaps;
  58195. let view = camera.matrixWorldInverse;
  58196. let viewInv = camera.matrixWorld;
  58197. if(params.viewOverride){
  58198. view = params.viewOverride;
  58199. viewInv = view.clone().invert();
  58200. }
  58201. let proj = camera.projectionMatrix;
  58202. let projInv = proj.clone().invert();
  58203. //let worldView = new THREE.Matrix4();
  58204. let shader = null;
  58205. let visibilityTextureData = null;
  58206. let currentTextureBindingPoint = 0;
  58207. if (material.pointSizeType >= 0) {//最好搬到renderNodes
  58208. if (material.pointSizeType === PointSizeType.ADAPTIVE ||
  58209. material.activeAttributeName === "level of detail") {
  58210. let vnNodes = (params.vnTextureNodes != null) ? params.vnTextureNodes : nodes;
  58211. visibilityTextureData = octree.computeVisibilityTextureData(vnNodes, camera);
  58212. const vnt = material.visibleNodesTexture;
  58213. const data = vnt.image.data;
  58214. data.set(visibilityTextureData.data);
  58215. vnt.needsUpdate = true;
  58216. }
  58217. }
  58218. { // UPDATE SHADER AND TEXTURES
  58219. if (!this.shaders.has(material)) {
  58220. let [vs, fs] = [material.vertexShader, material.fragmentShader];
  58221. let shader = new Shader$1(gl, "pointcloud", vs, fs);
  58222. this.shaders.set(material, shader);
  58223. }
  58224. shader = this.shaders.get(material);
  58225. if(material.shaderNeedsUpdate)
  58226. {
  58227. let [vs, fs] = [material.vertexShader, material.fragmentShader];
  58228. let numSnapshots = material.snapEnabled ? material.numSnapshots : 0;
  58229. let num_in_clipboxes = (material.clipBoxes_in && material.clipBoxes_in.length) ? material.clipBoxes_in.length : 0;
  58230. let num_out_clipboxes = (material.clipBoxes_out && material.clipBoxes_out.length) ? material.clipBoxes_out.length : 0;
  58231. let num_highlightBox = (material.highlightBoxes && material.highlightBoxes.length) ? material.highlightBoxes.length : 0;
  58232. let numClipSpheres = (params.clipSpheres && params.clipSpheres.length) ? params.clipSpheres.length : 0;
  58233. let numClipPolygons = (material.clipPolygons && material.clipPolygons.length) ? material.clipPolygons.length : 0;
  58234. let defines = [
  58235. `#define num_shadowmaps ${shadowMaps.length}`,
  58236. `#define num_snapshots ${numSnapshots}`,
  58237. `#define num_in_clipboxes ${num_in_clipboxes}`, //改
  58238. `#define num_out_clipboxes ${num_out_clipboxes}`, //改
  58239. `#define num_highlightBox ${num_highlightBox}`, //改
  58240. `#define num_clipspheres ${numClipSpheres}`,
  58241. ];
  58242. //add:-----------
  58243. if(material.bigClipInBox ){//裁剪下载
  58244. defines.push('#define bigClipInBox');
  58245. }
  58246. if(material.usePanoMap){
  58247. defines.push("#define usePanoMap");
  58248. }
  58249. if(material.useFilterByNormal){
  58250. defines.push("#define use_filter_by_normal");
  58251. //Potree.settings.editType == 'pano' ? defines.push("#define attenuated_opacity2") : defines.push("#define attenuated_opacity");
  58252. }
  58253. //---------------
  58254. if(octree.pcoGeometry.root.isLoaded()){
  58255. let attributes = octree.pcoGeometry.root.geometry.attributes;
  58256. if(attributes["gps-time"]){
  58257. defines.push("#define clip_gps_enabled");
  58258. }
  58259. if(attributes["return number"]){
  58260. defines.push("#define clip_return_number_enabled");
  58261. }
  58262. if(attributes["number of returns"]){
  58263. defines.push("#define clip_number_of_returns_enabled");
  58264. }
  58265. if(attributes["source id"] || attributes["point source id"]){
  58266. defines.push("#define clip_point_source_id_enabled");
  58267. }
  58268. }
  58269. let definesString = defines.join("\n");
  58270. let vsVersionIndex = vs.indexOf("#version ");
  58271. let fsVersionIndex = fs.indexOf("#version ");
  58272. if(vsVersionIndex >= 0){
  58273. vs = vs.replace(/(#version .*)/, `$1\n${definesString}`);
  58274. }else {
  58275. vs = `${definesString}\n${vs}`;
  58276. }
  58277. if(fsVersionIndex >= 0){
  58278. fs = fs.replace(/(#version .*)/, `$1\n${definesString}`);
  58279. }else {
  58280. fs = `${definesString}\n${fs}`;
  58281. }
  58282. shader.update(vs, fs);
  58283. material.shaderNeedsUpdate = false;
  58284. }
  58285. for (let uniformName of Object.keys(material.uniforms)) {
  58286. let uniform = material.uniforms[uniformName];
  58287. if (uniform.type == "t") {
  58288. let texture = uniform.value;
  58289. if (!texture) {
  58290. continue;
  58291. }
  58292. //add
  58293. if(uniformName == 'pano0Map' || uniformName == 'pano1Map' ){ //属于cubeTex,另外设置
  58294. continue
  58295. }
  58296. if (!this.textures.has(texture)) {
  58297. let webglTexture = new WebGLTexture$1(gl, texture);
  58298. this.textures.set(texture, webglTexture);
  58299. }
  58300. let webGLTexture = this.textures.get(texture);
  58301. webGLTexture.update();
  58302. }
  58303. }
  58304. }
  58305. gl.useProgram(shader.program);
  58306. /* let transparent = false;
  58307. if(params.transparent !== undefined){
  58308. transparent = params.transparent && material.opacity < 1;
  58309. }else{
  58310. transparent = material.usePanoMap ? false : (material.useFilterByNormal || material.opacity < 1); //add useFilterByNormal
  58311. }
  58312. if (transparent){
  58313. gl.enable(gl.BLEND);
  58314. if(params.notAdditiveBlending){
  58315. gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); //NormalBlending
  58316. gl.enable(gl.DEPTH_TEST);
  58317. gl.depthMask(true); //如果不开启depthWrite,深度会错乱。
  58318. }else{
  58319. gl.blendFunc(gl.SRC_ALPHA, gl.ONE); //AdditiveBlending 原本
  58320. gl.disable(gl.DEPTH_TEST);
  58321. gl.depthMask(false);
  58322. }
  58323. } else {
  58324. gl.disable(gl.BLEND);
  58325. gl.depthMask(true);
  58326. gl.enable(gl.DEPTH_TEST);
  58327. }
  58328. if(params.blendFunc !== undefined){
  58329. gl.enable(gl.BLEND);
  58330. gl.blendFunc(...params.blendFunc);
  58331. }
  58332. if(params.depthTest !== undefined){
  58333. if(params.depthTest === true){
  58334. gl.enable(gl.DEPTH_TEST);
  58335. }else{
  58336. gl.disable(gl.DEPTH_TEST);
  58337. }
  58338. }
  58339. if(params.depthWrite !== undefined){
  58340. if(params.depthWrite === true){
  58341. gl.depthMask(true);
  58342. }else{
  58343. gl.depthMask(false);
  58344. }
  58345. } */
  58346. { // UPDATE UNIFORMS
  58347. shader.setUniformMatrix4("projectionMatrix", proj);
  58348. shader.setUniformMatrix4("viewMatrix", view);
  58349. shader.setUniformMatrix4("uViewInv", viewInv);
  58350. shader.setUniformMatrix4("uProjInv", projInv);
  58351. /* let screenWidth = target ? target.width : material.screenWidth;
  58352. let screenHeight = target ? target.height : material.screenHeight;
  58353. shader.setUniform1f("uScreenWidth", screenWidth);
  58354. shader.setUniform1f("uScreenHeight", screenHeight); */
  58355. shader.setUniform2f('resolution', material.resolution.toArray());
  58356. shader.setUniform1f("fov", Math.PI * camera.fov / 180);
  58357. shader.setUniform1f("near", camera.near);
  58358. shader.setUniform1f("far", camera.far);
  58359. if(camera instanceof OrthographicCamera){
  58360. shader.setUniform("uUseOrthographicCamera", true);
  58361. shader.setUniform("uOrthoWidth", (camera.right - camera.left) / camera.zoom); //改
  58362. shader.setUniform("uOrthoHeight", camera.top - camera.bottom);
  58363. }else {
  58364. shader.setUniform("uUseOrthographicCamera", false);
  58365. }
  58366. /* if(material.clipBoxes.length + material.clipPolygons.length === 0){//改
  58367. shader.setUniform1i("clipTask", ClipTask.NONE);
  58368. }else{
  58369. shader.setUniform1i("clipTask", material.clipTask);
  58370. }
  58371. shader.setUniform1i("clipMethod", material.clipMethod);*/
  58372. //改
  58373. if (material.clipBoxes_in && material.clipBoxes_in.length > 0) {
  58374. //let flattenedMatrices = [].concat(...material.clipBoxes.map(c => c.inverse.elements));
  58375. const lClipBoxes = shader.uniformLocations["clipBoxes_in[0]"];
  58376. gl.uniformMatrix4fv(lClipBoxes, false, material.uniforms.clipBoxes_in.value);
  58377. }
  58378. if (material.clipBoxes_out && material.clipBoxes_out.length > 0) {//add
  58379. const lClipBoxes2 = shader.uniformLocations["clipBoxes_out[0]"];
  58380. gl.uniformMatrix4fv(lClipBoxes2, false, material.uniforms.clipBoxes_out.value);
  58381. }
  58382. if (material.highlightBoxes && material.highlightBoxes.length > 0) {//add
  58383. const boxes_highlight = shader.uniformLocations["boxes_highlight[0]"];
  58384. gl.uniformMatrix4fv(boxes_highlight, false, material.uniforms.boxes_highlight.value);
  58385. }
  58386. if (material.bigClipInBox ) {//add
  58387. shader.setUniformMatrix4("clipBoxBig_in", material.uniforms.clipBoxBig_in.value);
  58388. }
  58389. // TODO CLIPSPHERES
  58390. if(params.clipSpheres && params.clipSpheres.length > 0){
  58391. let clipSpheres = params.clipSpheres;
  58392. let matrices = [];
  58393. for(let clipSphere of clipSpheres){
  58394. //let mScale = new THREE.Matrix4().makeScale(...clipSphere.scale.toArray());
  58395. //let mTranslate = new THREE.Matrix4().makeTranslation(...clipSphere.position.toArray());
  58396. //let clipToWorld = new THREE.Matrix4().multiplyMatrices(mTranslate, mScale);
  58397. let clipToWorld = clipSphere.matrixWorld;
  58398. let viewToWorld = camera.matrixWorld;
  58399. let worldToClip = clipToWorld.clone().invert();
  58400. let viewToClip = new Matrix4().multiplyMatrices(worldToClip, viewToWorld);
  58401. matrices.push(viewToClip);
  58402. }
  58403. let flattenedMatrices = [].concat(...matrices.map(matrix => matrix.elements));
  58404. const lClipSpheres = shader.uniformLocations["uClipSpheres[0]"];
  58405. gl.uniformMatrix4fv(lClipSpheres, false, flattenedMatrices);
  58406. //const lClipSpheres = shader.uniformLocations["uClipSpheres[0]"];
  58407. //gl.uniformMatrix4fv(lClipSpheres, false, material.uniforms.clipSpheres.value);
  58408. }
  58409. shader.setUniform1f("maxSize", material.uniforms.maxSize.value);
  58410. shader.setUniform1f("minSize", material.uniforms.minSize.value);
  58411. // uniform float uPCIndex
  58412. shader.setUniform1f("uOctreeSpacing", material.spacing);
  58413. shader.setUniform("uOctreeSize", material.uniforms.octreeSize.value);
  58414. shader.setUniform2f("elevationRange", material.elevationRange);
  58415. shader.setUniform2f("intensityRange", material.intensityRange);
  58416. shader.setUniform3f("uIntensity_gbc", [
  58417. material.intensityGamma,
  58418. material.intensityBrightness,
  58419. material.intensityContrast
  58420. ]);
  58421. shader.setUniform3f("uRGB_gbc", [
  58422. material.rgbGamma,
  58423. material.rgbBrightness,
  58424. material.rgbContrast
  58425. ]);
  58426. shader.setUniform1f("uTransition", material.transition);
  58427. shader.setUniform1f("wRGB", material.weightRGB);
  58428. shader.setUniform1f("wIntensity", material.weightIntensity);
  58429. shader.setUniform1f("wElevation", material.weightElevation);
  58430. shader.setUniform1f("wClassification", material.weightClassification);
  58431. shader.setUniform1f("wReturnNumber", material.weightReturnNumber);
  58432. shader.setUniform1f("wSourceID", material.weightSourceID);
  58433. shader.setUniform("backfaceCulling", material.uniforms.backfaceCulling.value);
  58434. //==========================
  58435. //gl.TEXTURE_CUBE_MAP: 34067
  58436. //gl.TEXTURE0=33984 , vnWebGLTexture.target=gl.TEXTURE_2D = 3353
  58437. let vnWebGLTexture = this.textures.get(material.visibleNodesTexture);//最好搬到renderNodes
  58438. if(vnWebGLTexture){
  58439. shader.setUniform1i("visibleNodes", currentTextureBindingPoint); //为何之前写的是"visibleNodesTexture",但和"visibleNodes"效果相同?可shader里只有"visibleNodes"
  58440. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  58441. gl.bindTexture(vnWebGLTexture.target, vnWebGLTexture.id);
  58442. currentTextureBindingPoint++;
  58443. }
  58444. let gradientTexture = this.textures.get(material.gradientTexture);
  58445. shader.setUniform1i("gradient", currentTextureBindingPoint);
  58446. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  58447. gl.bindTexture(gradientTexture.target, gradientTexture.id);
  58448. currentTextureBindingPoint++;
  58449. const repeat = material.elevationGradientRepeat;
  58450. if(repeat === ElevationGradientRepeat.REPEAT){
  58451. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.REPEAT);
  58452. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.REPEAT);
  58453. }else if(repeat === ElevationGradientRepeat.MIRRORED_REPEAT){
  58454. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
  58455. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
  58456. }else {
  58457. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  58458. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  58459. }
  58460. currentTextureBindingPoint++;
  58461. let classificationTexture = this.textures.get(material.classificationTexture);
  58462. shader.setUniform1i("classificationLUT", currentTextureBindingPoint);
  58463. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  58464. gl.bindTexture(classificationTexture.target, classificationTexture.id);
  58465. currentTextureBindingPoint++;
  58466. let matcapTexture = this.textures.get(material.matcapTexture);
  58467. shader.setUniform1i("matcapTextureUniform", currentTextureBindingPoint);
  58468. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  58469. gl.bindTexture(matcapTexture.target, matcapTexture.id);
  58470. currentTextureBindingPoint++;
  58471. if (material.snapEnabled === true) {
  58472. {
  58473. const lSnapshot = shader.uniformLocations["uSnapshot[0]"];
  58474. const lSnapshotDepth = shader.uniformLocations["uSnapshotDepth[0]"];
  58475. let bindingStart = currentTextureBindingPoint;
  58476. let lSnapshotBindingPoints = new Array(5).fill(bindingStart).map((a, i) => (a + i));
  58477. let lSnapshotDepthBindingPoints = new Array(5)
  58478. .fill(1 + Math.max(...lSnapshotBindingPoints))
  58479. .map((a, i) => (a + i));
  58480. currentTextureBindingPoint = 1 + Math.max(...lSnapshotDepthBindingPoints);
  58481. gl.uniform1iv(lSnapshot, lSnapshotBindingPoints);
  58482. gl.uniform1iv(lSnapshotDepth, lSnapshotDepthBindingPoints);
  58483. for (let i = 0; i < 5; i++) {
  58484. let texture = material.uniforms[`uSnapshot`].value[i];
  58485. let textureDepth = material.uniforms[`uSnapshotDepth`].value[i];
  58486. if (!texture) {
  58487. break;
  58488. }
  58489. let snapTexture = this.threeRenderer.properties.get(texture).__webglTexture;
  58490. let snapTextureDepth = this.threeRenderer.properties.get(textureDepth).__webglTexture;
  58491. let bindingPoint = lSnapshotBindingPoints[i];
  58492. let depthBindingPoint = lSnapshotDepthBindingPoints[i];
  58493. gl.activeTexture(gl[`TEXTURE${bindingPoint}`]);
  58494. gl.bindTexture(gl.TEXTURE_2D, snapTexture);
  58495. gl.activeTexture(gl[`TEXTURE${depthBindingPoint}`]);
  58496. gl.bindTexture(gl.TEXTURE_2D, snapTextureDepth);
  58497. }
  58498. }
  58499. {
  58500. let flattenedMatrices = [].concat(...material.uniforms.uSnapView.value.map(c => c.elements));
  58501. const lSnapView = shader.uniformLocations["uSnapView[0]"];
  58502. gl.uniformMatrix4fv(lSnapView, false, flattenedMatrices);
  58503. }
  58504. {
  58505. let flattenedMatrices = [].concat(...material.uniforms.uSnapProj.value.map(c => c.elements));
  58506. const lSnapProj = shader.uniformLocations["uSnapProj[0]"];
  58507. gl.uniformMatrix4fv(lSnapProj, false, flattenedMatrices);
  58508. }
  58509. {
  58510. let flattenedMatrices = [].concat(...material.uniforms.uSnapProjInv.value.map(c => c.elements));
  58511. const lSnapProjInv = shader.uniformLocations["uSnapProjInv[0]"];
  58512. gl.uniformMatrix4fv(lSnapProjInv, false, flattenedMatrices);
  58513. }
  58514. {
  58515. let flattenedMatrices = [].concat(...material.uniforms.uSnapViewInv.value.map(c => c.elements));
  58516. const lSnapViewInv = shader.uniformLocations["uSnapViewInv[0]"];
  58517. gl.uniformMatrix4fv(lSnapViewInv, false, flattenedMatrices);
  58518. }
  58519. }
  58520. //=============add===========
  58521. if(material.usePanoMap){//为什么pointsize失效
  58522. shader.setUniform1f("progress", material.uniforms.progress.value);
  58523. shader.setUniform1f("easeInOutRatio", material.uniforms.easeInOutRatio.value);
  58524. shader.setUniform3f("pano0Position", material.uniforms.pano0Position.value.toArray());
  58525. shader.setUniform3f("pano1Position", material.uniforms.pano1Position.value.toArray());
  58526. shader.setUniform('pano0Matrix', material.uniforms.pano0Matrix.value);
  58527. shader.setUniform('pano1Matrix', material.uniforms.pano1Matrix.value);
  58528. let pano0Map = material.uniforms.pano0Map.value;
  58529. if(pano0Map){
  58530. this.threeRenderer._textures.safeSetTextureCube( pano0Map, ++currentTextureBindingPoint );
  58531. shader.setUniform1i('pano0Map', currentTextureBindingPoint);
  58532. }
  58533. let pano1Map = material.uniforms.pano1Map.value;
  58534. if(pano1Map){
  58535. this.threeRenderer._textures.safeSetTextureCube( pano1Map, ++currentTextureBindingPoint );
  58536. shader.setUniform1i('pano1Map', currentTextureBindingPoint);
  58537. }
  58538. //注: three.js我添加了个 _textures, safeSetTextureCube里主要就是activeTexture和bindTexture
  58539. }
  58540. }
  58541. viewer.addTimeMark('renderOctree','end');
  58542. params.currentTextureBindingPoint = currentTextureBindingPoint;
  58543. octrees.forEach(octree=>{
  58544. this.renderNodes(octree, nodes || octree.visibleNodes, visibilityTextureData, camera, target, shader, params);
  58545. });
  58546. gl.activeTexture(gl.TEXTURE2);
  58547. gl.bindTexture(gl.TEXTURE_2D, null);
  58548. gl.activeTexture(gl.TEXTURE0);
  58549. //gl.bindTexture(gl.TEXTURE_2D, null); //add
  58550. //add 恢复为不透明(否则renderToCubeMap时的贴图会被渲染成高亮的颜色)
  58551. gl.disable(gl.BLEND);
  58552. gl.depthMask(true);
  58553. gl.enable(gl.DEPTH_TEST);
  58554. //DEPTH_TEST等需要恢复吗
  58555. }
  58556. render(scene, camera, target = null, params = {}) {
  58557. const gl = this.gl;
  58558. // PREPARE
  58559. if (target != null) {
  58560. this.threeRenderer.setRenderTarget(target);
  58561. }
  58562. //camera.updateProjectionMatrix();
  58563. // camera.matrixWorldInverse.invert(camera.matrixWorld);
  58564. const traversalResult = this.traverse(scene);
  58565. //排序
  58566. if(Potree.settings.notAdditiveBlending){//add
  58567. traversalResult.octrees.forEach(tree=>{
  58568. if(tree.material.opacity==1){
  58569. tree._z = Infinity; //不透明的先渲染
  58570. }else {
  58571. let center = tree.boundCenter ? tree.boundCenter.clone() : tree.boundingBox.getCenter(tree.boundCenter).applyMatrix4(tree.matrixWorld);
  58572. center.project(camera);
  58573. tree._z = center.z;
  58574. }
  58575. });
  58576. traversalResult.octrees.sort((tree1,tree2)=>{
  58577. return tree2._z - tree1._z //降序 (-1 朝外)。 离屏幕近的后渲染
  58578. });
  58579. }
  58580. // RENDER
  58581. let mat = traversalResult.octrees[0].material;
  58582. if(Potree.settings.cloudSameMat && viewer.scene.volumes.length == 0 && mat.pointSizeType != PointSizeType.ADAPTIVE && mat.activeAttributeName != "level of detail"){
  58583. this.renderOctree(traversalResult.octrees, null, camera, target, params); //所有点云除了个别属性需要在shader中更新,其他都使用第一个点云的材质
  58584. }else for (const octree of traversalResult.octrees) {
  58585. for (const octree of traversalResult.octrees) {
  58586. this.renderOctree(octree, octree.visibleNodes, camera, target, params);
  58587. }
  58588. }
  58589. //if (octree material.pointSizeType === PointSizeType.ADAPTIVE || material.activeAttributeName === "level of detail") {
  58590. // CLEANUP
  58591. gl.activeTexture(gl.TEXTURE1);
  58592. gl.bindTexture(gl.TEXTURE_2D, null);
  58593. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  58594. gl.bindVertexArray(null);
  58595. this.threeRenderer.resetState();
  58596. }
  58597. };
  58598. /*
  58599. 中东的链接http://indoor.popsmart.cn:8094/zdoblh-yz/?vlon=5.14&vlat=-0.13&fov=100.0&pc=true&lon=121.61136592&lat=29.87855579&z=16.577
  58600. geometry: 有的attributes: 属性是:
  58601. classification:
  58602. color:
  58603. indices:
  58604. normal:
  58605. position:
  58606. 最好有个spacing
  58607. */
  58608. //
  58609. // Algorithm by Christian Boucheny
  58610. // shader code taken and adapted from CloudCompare
  58611. //
  58612. // see
  58613. // https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL
  58614. // http://www.kitware.com/source/home/post/9
  58615. // https://tel.archives-ouvertes.fr/tel-00438464/document p. 115+ (french)
  58616. class ExtendEyeDomeLightingMaterial extends EyeDomeLightingMaterial{
  58617. constructor(parameters = {}){
  58618. super(parameters);
  58619. delete this.uniforms.screenWidth;
  58620. delete this.uniforms.screenHeight;
  58621. this.uniforms.resolution = { type: 'v2', value: new Vector2()};
  58622. this.uniforms.useEDL = { type: 'i', value: 1 };
  58623. this.vertexShader = this.getDefines() + Shaders['edl_new.vs']; //改
  58624. this.fragmentShader = this.getDefines() + Shaders['edl_new.fs']; //改
  58625. }
  58626. }
  58627. const copyShader = {
  58628. uniforms: {
  58629. tDiffuse: {
  58630. type: "t",
  58631. value: null
  58632. },
  58633. opacity: {
  58634. type: "f",
  58635. value: 1
  58636. },
  58637. depthTex: {
  58638. type: "t",
  58639. value: null
  58640. }
  58641. },
  58642. vertexShader: `
  58643. varying vec2 vUv;
  58644. void main() {
  58645. vUv = uv;
  58646. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  58647. }
  58648. `,
  58649. fragmentShader: `
  58650. #extension GL_EXT_frag_depth : enable
  58651. uniform float opacity;
  58652. uniform sampler2D tDiffuse;
  58653. #if defined(GL_EXT_frag_depth) && defined(useDepth)
  58654. uniform sampler2D depthTex;
  58655. #endif
  58656. varying vec2 vUv;
  58657. void main() {
  58658. #if defined(GL_EXT_frag_depth) && defined(useDepth)
  58659. float depth = texture2D(depthTex, vUv).r;
  58660. /* if(depth >= 1.0){ //超级远(但是在modelTex里我把天空距离超出far了,所以不删)
  58661. discard;
  58662. } */
  58663. gl_FragDepthEXT = depth;
  58664. #endif
  58665. vec4 texel = texture2D( tDiffuse, vUv );
  58666. gl_FragColor = opacity * texel;
  58667. }
  58668. `
  58669. };
  58670. //import DepthTexSampler from "../custom/utils/DepthTexSampler.js";
  58671. class EDLRenderer{//Eye-Dome Lighting 眼罩照明
  58672. constructor(viewer){
  58673. this.viewer = viewer;
  58674. this.edlMaterial = null;
  58675. //this.rtRegular;
  58676. this.rtEDLs = new Map;
  58677. this.gl = viewer.renderer.getContext();
  58678. //反正也没用到,注释了:
  58679. //this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
  58680. viewer.addEventListener('resize',this.resize.bind(this));
  58681. this.initEDL(viewer);
  58682. }
  58683. initEDL(viewer){
  58684. if (this.edlMaterial != null || !Features.EXT_DEPTH.isSupported()){
  58685. return;
  58686. }
  58687. this.edlMaterial = new ExtendEyeDomeLightingMaterial();
  58688. this.edlMaterial.depthTest = true;
  58689. this.edlMaterial.depthWrite = true;
  58690. this.edlMaterial.transparent = true;
  58691. let copyUniforms = UniformsUtils.clone( copyShader.uniforms );
  58692. this.recoverToScreenMat = new ShaderMaterial({
  58693. uniforms: copyUniforms,
  58694. vertexShader:copyShader.vertexShader,
  58695. fragmentShader: copyShader.fragmentShader,
  58696. transparent: true,
  58697. defines:{
  58698. useDepth: true //开启后,其他物体才能被遮挡
  58699. }
  58700. });
  58701. /* let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
  58702. this.copyMaterial = new THREE.ShaderMaterial( {
  58703. uniforms: copyUniforms,
  58704. vertexShader: copyShader.vertexShader,
  58705. fragmentShader: copyShader.fragmentShader,
  58706. //premultipliedAlpha: true,
  58707. transparent: true,
  58708. //blending: THREE.AdditiveBlending,
  58709. depthTest: false,
  58710. depthWrite: false
  58711. }); */
  58712. if(Potree.settings.useRTskybox != Potree.settings.useRTPoint){//如果两个只开了一个
  58713. viewer.images360.addEventListener('endChangeMode',()=>{
  58714. this.resize({viewport:viewer.mainViewport});
  58715. });
  58716. }
  58717. //this.depthTexSampler = new DepthTexSampler(this);
  58718. };
  58719. resize(e){
  58720. if(Features.EXT_DEPTH.isSupported()){
  58721. let viewport = e.viewport;
  58722. let size = ( Potree.settings.displayMode == 'showPanos' ? Potree.settings.useRTskybox : Potree.settings.useRTPoint) ? viewport.resolution2 : viewport.resolution; //若要渲染skybox,需要和设备一样精度的rt
  58723. this.getRtEDL(viewport).setSize( size.x, size.y ); //理论上可以是任意尺寸,但会影响精度,且aspect最好和渲染的一致
  58724. }
  58725. }
  58726. clearTargets(params={}){
  58727. const viewer = this.viewer;
  58728. const {renderer} = viewer;
  58729. const oldTarget = renderer.getRenderTarget();
  58730. if(params.target){//add
  58731. renderer.setRenderTarget( params.target);
  58732. renderer.clear();
  58733. }
  58734. if(Features.EXT_DEPTH.isSupported()){
  58735. if(params.rtEDL){
  58736. renderer.setRenderTarget( params.rtEDL);
  58737. renderer.clear();
  58738. }else {
  58739. var rtEDL = this.getRtEDL(params.viewport);
  58740. if(rtEDL){
  58741. renderer.setRenderTarget( rtEDL );
  58742. renderer.clear( true, true, true );
  58743. }
  58744. }
  58745. }
  58746. //renderer.setRenderTarget( this.rtRegular );
  58747. //renderer.clear( true, true, false );
  58748. renderer.setRenderTarget(oldTarget);
  58749. }
  58750. getRtEDL(viewport){//根据不同viewport返回rtEDL的texture
  58751. if(!viewport){
  58752. console.warn('getRtEDL没传viewport!!!! !!!!!!!!!!');
  58753. viewport = viewer.mainViewport;
  58754. }
  58755. var rtEDL = this.rtEDLs.get(viewport);
  58756. if(!rtEDL){
  58757. if(Features.EXT_DEPTH.isSupported()){
  58758. rtEDL = new WebGLRenderTarget(viewport.resolution.x, viewport.resolution.y, {
  58759. minFilter: NearestFilter,
  58760. magFilter: NearestFilter,
  58761. format: RGBAFormat,
  58762. type: FloatType,
  58763. depthTexture: new DepthTexture(undefined, undefined, UnsignedIntType)
  58764. });
  58765. //注: 部分手机在resize时会崩溃,经检验去掉rtEDL的resize可以解决,所以更应该注释掉这个
  58766. this.rtEDLs.set(viewport, rtEDL);
  58767. }
  58768. }
  58769. return rtEDL
  58770. }
  58771. renderShadowMap(visiblePointClouds, camera, lights){
  58772. const {viewer} = this;
  58773. const doShadows = lights.length > 0 && !(lights[0].disableShadowUpdates);
  58774. if(doShadows){
  58775. let light = lights[0];
  58776. this.shadowMap.setLight(light);
  58777. let originalAttributes = new Map();
  58778. for(let pointcloud of viewer.scene.pointclouds){
  58779. // TODO IMPORTANT !!! check
  58780. originalAttributes.set(pointcloud, pointcloud.material.activeAttributeName);
  58781. pointcloud.material.disableEvents();
  58782. pointcloud.material.activeAttributeName = "depth";
  58783. //pointcloud.material.pointColorType = PointColorType.DEPTH;
  58784. }
  58785. this.shadowMap.render(viewer.scene.scenePointCloud, camera);
  58786. for(let pointcloud of visiblePointClouds){
  58787. let originalAttribute = originalAttributes.get(pointcloud);
  58788. // TODO IMPORTANT !!! check
  58789. pointcloud.material.activeAttributeName = originalAttribute;
  58790. pointcloud.material.enableEvents();
  58791. }
  58792. viewer.shadowTestCam.updateMatrixWorld();
  58793. viewer.shadowTestCam.matrixWorldInverse.copy(viewer.shadowTestCam.matrixWorld).invert();
  58794. viewer.shadowTestCam.updateProjectionMatrix();
  58795. }
  58796. }
  58797. render(params={}){
  58798. const viewer = this.viewer;
  58799. let camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  58800. let rtEDL = (Potree.settings.pointEnableRT || Potree.settings.displayMode == 'showPanos' || viewer.useEDL) &&
  58801. Features.EXT_DEPTH.isSupported() /* && camera.type != "OrthographicCamera" */&& !params.dontRenderRtEDL && (params.rtEDL || this.getRtEDL(params.viewport)); // 平面相机不用depthTex直接打开depthTest?且不使用edl
  58802. let useEDL = viewer.useEDL && rtEDL && Potree.settings.displayMode != 'showPanos';
  58803. let target = params.target || null;
  58804. const resolution = (rtEDL && Potree.settings.useRTPoint) ? new Vector2(rtEDL.width,rtEDL.height) : params.viewport ? params.viewport.resolution2 : this.viewer.renderer.getSize(new Vector2());//突然发现mobile用resolution2点云会放大
  58805. viewer.renderer.setRenderTarget(target);
  58806. //viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
  58807. let lights = [];
  58808. /* viewer.scene.scene.traverse(node => {
  58809. if(node.type === "SpotLight"){
  58810. lights.push(node);
  58811. }
  58812. }); */
  58813. //skybox 全景图
  58814. if(!params.magnifier){
  58815. if(Potree.settings.displayMode == 'showPanos' || Potree.settings.testCube){
  58816. Potree.Utils.setCameraLayers(camera, ['skybox']);
  58817. if(Potree.settings.displayMode == 'showPanos' && viewer.images360.currentPano.pointcloud.hasDepthTex && rtEDL){//渲染深度图
  58818. viewer.renderer.setRenderTarget(rtEDL); //将带有深度图的skybox画在rtEDL一下,这样就不需要绘制后边的点云了
  58819. viewer.renderer.render(viewer.scene.scene, camera);
  58820. viewer.renderer.setRenderTarget(target);
  58821. if(Potree.settings.useRTskybox){//直接使用rtEDL,但是会失去抗锯齿,不知在skybox上需要抗锯齿吗
  58822. this.recoverToScreenMat.uniforms.depthTex.value = rtEDL.depthTexture;
  58823. this.recoverToScreenMat.uniforms.tDiffuse.value = rtEDL.texture;
  58824. Utils.screenPass.render(viewer.renderer, this.recoverToScreenMat, target);
  58825. }else {
  58826. viewer.renderer.render(viewer.scene.scene, camera);
  58827. }
  58828. return
  58829. }else {
  58830. viewer.renderer.render(viewer.scene.scene, camera);
  58831. }
  58832. }
  58833. }
  58834. const visiblePointClouds2 = viewer.scene.pointclouds.filter(pc => Potree.Utils.getObjVisiByReason(pc,'datasetSelection') ); //需要绘制到rtEDL的
  58835. const showPointClouds = params.magnifier ? visiblePointClouds2.length>0 : viewer.scene.pointclouds.some(e=>e.visible); //是否有需要绘制到屏幕的
  58836. visiblePointClouds2.forEach(e=>{//为了绘制到depthTexture,先显示(展示全景图时隐藏了点云,所以需要显示下。且放大镜需要绘制点云)
  58837. e.oldVisi = e.visible;
  58838. e.visible = true;
  58839. });
  58840. Potree.Utils.setCameraLayers(camera, ['pointcloud']);
  58841. camera.layers.set(Potree.config.renderLayers.pointcloud);
  58842. //TODO adapt to multiple lights
  58843. //this.renderShadowMap(visiblePointClouds2, camera, lights); //???????
  58844. {
  58845. for (let pointcloud of visiblePointClouds2) {
  58846. let material = pointcloud.material;
  58847. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  58848. material.fov = MathUtils$1.degToRad(camera.fov);
  58849. material.resolution = resolution;
  58850. material.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  58851. material.near = camera.near;
  58852. material.far = camera.far;
  58853. material.uniforms.octreeSize.value = octreeSize;
  58854. if(useEDL ){
  58855. material.useEDL = true;
  58856. //material.fakeEDL = false; //add
  58857. }else {
  58858. material.useEDL = false;
  58859. //material.fakeEDL = true; //add 使也输出深度
  58860. }
  58861. }
  58862. if(rtEDL ){ //借用rtEDL存储深度信息
  58863. viewer.renderer.setRenderTarget( rtEDL );
  58864. if(visiblePointClouds2.length>0){ //渲染scenePointCloud到rtEDL
  58865. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, rtEDL, {
  58866. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  58867. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume$1)),
  58868. transparent: false,
  58869. });
  58870. }
  58871. if(Potree.settings.intersectOnObjs){// model也要渲染到rtEDL
  58872. Potree.Utils.setCameraLayers(camera, ['model','light']);
  58873. viewer.objs.traverse(e=>{if(e.material)e._OlddepthWrite = e.material.depthWrite, e.material.depthWrite = true;}); //否则半透明的mesh无法遮住测量线
  58874. viewer.renderer.render(viewer.scene.scene, camera);
  58875. viewer.objs.traverse(e=>{if(e.material)e.material.depthWrite = e._OlddepthWrite;});
  58876. //缺点:半透明的model 就算完全透明, 也会遮住测量线
  58877. }
  58878. }
  58879. }
  58880. //渲染到rtEDL完毕
  58881. viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer });
  58882. viewer.renderer.setRenderTarget( target );
  58883. if(!params.magnifier)visiblePointClouds2.forEach(e=>{//放大镜显示点云
  58884. e.visible = e.oldVisi;
  58885. });
  58886. if(showPointClouds){ //绘制点云到画布
  58887. if(useEDL){ //设置edlMaterial //Features.EXT_DEPTH不支持的话不会到这一块
  58888. const uniforms = this.edlMaterial.uniforms;
  58889. uniforms.resolution.value.copy(resolution);
  58890. uniforms.edlStrength.value = viewer.edlStrength;
  58891. uniforms.radius.value = viewer.edlRadius;
  58892. uniforms.useEDL.value = 1;//add
  58893. let proj = camera.projectionMatrix;
  58894. let projArray = new Float32Array(16);
  58895. projArray.set(proj.elements);
  58896. uniforms.uProj.value = projArray;
  58897. uniforms.uEDLColor.value = rtEDL.texture;
  58898. uniforms.opacity.value = viewer.edlOpacity; // HACK
  58899. Utils.screenPass.render(viewer.renderer, this.edlMaterial, target); //相当于一个描边后期特效。 缺点: 因为target上的没有抗锯齿,所以点云在晃动镜头时会不稳定地闪烁1px位置。优点:比不打开edl少绘制一次点云,更流畅了?!
  58900. }else if(Potree.settings.useRTPoint && rtEDL){
  58901. this.recoverToScreenMat.uniforms.tDiffuse.value = rtEDL.texture;
  58902. if(this.recoverToScreenMat.defines.useDepth){
  58903. this.recoverToScreenMat.uniforms.depthTex.value = rtEDL.depthTexture;
  58904. }
  58905. Utils.screenPass.render(viewer.renderer, this.recoverToScreenMat, target/* , Potree.settings.useFxaa && viewer.composer2 */);
  58906. params.drawedModelOnRT = true;
  58907. }else {
  58908. //渲染点云 (直接用rtEDL上的会失去抗锯齿, 导致频闪、密集时出现条纹, 自己写抗锯齿也要渲染好几次。另外透明度也要处理下)
  58909. let prop = {
  58910. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  58911. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume$1)) ,
  58912. notAdditiveBlending: Potree.settings.notAdditiveBlending//add 否则透明的点云会挡住后面的模型。 加上这句后竟然透明不会叠加了!
  58913. };
  58914. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, null , prop);
  58915. }
  58916. }
  58917. visiblePointClouds2.forEach(e=>{
  58918. e.visible = e.oldVisi;
  58919. });
  58920. //viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
  58921. }
  58922. /*
  58923. 渲染顺序:
  58924. 底层:背景 -> skybox(也可中间)
  58925. 中间层(含有深度信息):1 点云、marker等mesh,
  58926. 2 测量线(现在被做成借用depthTex
  58927. 顶层:maginifier
  58928. magnifier的贴图渲染不需要顶层、中间层只需要点云。
  58929. */
  58930. }
  58931. class ViewerBase extends EventDispatcher{
  58932. constructor(domElement, args = {}){
  58933. super();
  58934. this.name = args.name;
  58935. this.renderArea = domElement;
  58936. this.oldResolution = new Vector2();
  58937. this.oldResolution2 = new Vector2();
  58938. this.screenSizeInfo = {
  58939. W:0, H:0, pixelRatio:1 , windowWidth:0, windowHeight:0
  58940. };
  58941. this.initContext(args);
  58942. this.addEventListener('content_changed', ()=>{//画面改变,需要渲染
  58943. this.needRender = true;
  58944. //console.log('needRender')
  58945. });
  58946. }
  58947. initContext(args){
  58948. //console.log(`initializing three.js ${THREE.REVISION}`);
  58949. let width = this.renderArea.clientWidth;
  58950. let height = this.renderArea.clientHeight;
  58951. let contextAttributes = {
  58952. alpha: true,//支持透明
  58953. depth: true,
  58954. stencil: false,
  58955. antialias: !!args.antialias,
  58956. preserveDrawingBuffer: args.preserveDrawingBuffer || false ,
  58957. powerPreference: "high-performance",
  58958. };
  58959. let canvas = document.createElement("canvas");
  58960. let context = canvas.getContext('webgl', contextAttributes ); //不用webgl2是因为有的写法在webgl2不支持 如gl_FragDepthEXT
  58961. this.renderer = new WebGLRenderer({
  58962. premultipliedAlpha: false,
  58963. canvas: canvas,
  58964. context: context,
  58965. });
  58966. this.renderer.sortObjects = true; //原先false 打开了renderOrder才奏效
  58967. //this.renderer.setSize(width, height);
  58968. this.renderer.autoClear = args.autoClear || false;
  58969. //args.clearColor = args.clearColor || '#aa0033'
  58970. args.clearColor && this.renderer.setClearColor(args.clearColor);
  58971. this.renderArea.appendChild(this.renderer.domElement);
  58972. this.renderer.domElement.tabIndex = '2222';
  58973. this.renderer.domElement.style.position = 'absolute';
  58974. this.renderer.domElement.addEventListener('mousedown', () => {
  58975. this.renderer.domElement.focus();
  58976. });
  58977. //this.renderer.domElement.focus();
  58978. // NOTE: If extension errors occur, pass the string into this.renderer.extensions.get(x) before enabling
  58979. // enable frag_depth extension for the interpolation shader, if available
  58980. let gl = this.renderer.getContext();
  58981. gl.getExtension('EXT_frag_depth');
  58982. gl.getExtension('WEBGL_depth_texture');
  58983. gl.getExtension('WEBGL_color_buffer_float'); // Enable explicitly for more portability, EXT_color_buffer_float is the proper name in WebGL 2
  58984. if(gl.createVertexArray == null){
  58985. let extVAO = gl.getExtension('OES_vertex_array_object');
  58986. if(!extVAO){
  58987. throw new Error("OES_vertex_array_object extension not supported");
  58988. }
  58989. gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO);
  58990. gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO);
  58991. }
  58992. /* let oldClear = gl.clear;
  58993. gl.clear = (bits)=>{
  58994. console.error('clear')
  58995. }
  58996. */
  58997. }
  58998. updateScreenSize(o={}) { //有可能需要让viewport来判断,当窗口大小不变但viewport大小变时
  58999. var render = false, ratio, w, h;
  59000. //记录应当render的大小
  59001. if (o.width != void 0 && o.height != void 0) {
  59002. w = o.width;
  59003. h = o.height;
  59004. render = true;
  59005. ratio = 1;
  59006. }else {
  59007. w = this.renderArea.clientWidth;
  59008. h = this.renderArea.clientHeight;
  59009. if(w !== this.screenSizeInfo.W || h !== this.screenSizeInfo.H || o.forceUpdateSize || this.screenSizeInfo.pixelRatio != window.devicePixelRatio){
  59010. this.screenSizeInfo.W = w;
  59011. this.screenSizeInfo.H = h;
  59012. render = true;
  59013. this.screenSizeInfo.pixelRatio = window.devicePixelRatio; //如果player放在小窗口了,也要监测devicePixelRatio,因为缩放时client宽高不会改变
  59014. //config.isMobile ? (ratio = Math.min(window.devicePixelRatio, 2)) : (ratio = window.devicePixelRatio)
  59015. ratio = window.devicePixelRatio;
  59016. }
  59017. }
  59018. if (render) {
  59019. this.setSize(w, h, ratio);
  59020. }
  59021. }
  59022. setSize(width, height, devicePixelRatio, onlyForTarget){
  59023. //console.log('setSize', width)
  59024. if(!onlyForTarget){//onlyForTarget表示不更改当前renderer,只是为了rendertarget才要改变viewport
  59025. this.renderer.setPixelRatio(devicePixelRatio);
  59026. this.renderer.setSize(width, height ); // resize之后会自动clear(似乎因为setScissor ),所以一定要立刻绘制,所以setSize要在cameraChanged、update之前
  59027. }
  59028. //this.composer && this.composer.setSize(width, height);
  59029. if(this.viewports){
  59030. this.viewports.forEach((view,i)=>{
  59031. if(!view.active)return
  59032. var width_ = width * view.width;
  59033. var height_ = height * view.height;
  59034. view.setResolution(Math.ceil(width_), Math.ceil(height_), width, height ); //本来应该是floor,但是这样奇数时会少一个像素,导致向左移一个像素且宽度少1。现在则多绘制1个像素,超出的1个像素应该不会绘制出来(但不知道其他地方是否有偏差,比如pick时)
  59035. if(height_ == 0)return //avoid NAN
  59036. let aspect = width_ / height_; //camera的参数精确些,不用视口的归整的resolution像素值,否则hasChange无法为true, 导致canvasResize了但map没update从而闪烁
  59037. view.camera.aspect = aspect;
  59038. if(view.camera.type == "OrthographicCamera"){
  59039. /* //不改宽度 同4dkk
  59040. var heightHalf = view.camera.right / aspect
  59041. view.camera.top = heightHalf
  59042. view.camera.bottom = -heightHalf */
  59043. //高宽都改 使大小不随视口大小改变 navvis (直接和视口大小一致即可,通过zoom来定大小)
  59044. view.camera.left = -width_/2;
  59045. view.camera.right = width_/2;
  59046. view.camera.bottom = -height_/2;
  59047. view.camera.top = height_/2;
  59048. }else {
  59049. }
  59050. view.camera.updateProjectionMatrix();
  59051. });
  59052. }
  59053. if(!onlyForTarget){//因为onlyForTarget不传递devicePixelRatio所以不发送了
  59054. this.ifEmitResize({viewport:this.viewports[0], deviceRatio:devicePixelRatio});
  59055. }
  59056. }
  59057. ifEmitResize(e){//切换viewport渲染时, 若这些viewport大小不同就发送一次, 通知一些材质更新resolution。
  59058. if(!e.viewport.resolution.equals(this.oldResolution)||!e.viewport.resolution2.equals(this.oldResolution2)){
  59059. this.dispatchEvent($.extend(e, {type:'resize'}));
  59060. this.oldResolution.copy(e.viewport.resolution);
  59061. this.oldResolution2.copy(e.viewport.resolution2);
  59062. }
  59063. }
  59064. cameraChanged() {//判断相机是否改变
  59065. var changed = false;
  59066. /* if(this.needRender){
  59067. this.needRender = false
  59068. return true
  59069. } */
  59070. for(let i=0,j=this.viewports.length;i<j;i++){
  59071. let viewport = this.viewports[i];
  59072. let changeInfo = viewport.cameraChanged();
  59073. if(changeInfo.changed){
  59074. changed = true;
  59075. //if(!this.changeTime ||this.changeTime<100){
  59076. this.dispatchEvent({
  59077. type: "camera_changed",
  59078. camera: viewport.camera,
  59079. viewport ,
  59080. changeInfo
  59081. });
  59082. //this.changeTime = (this.changeTime || 0) +1
  59083. //}
  59084. viewport.needRender = true; //直接写这咯
  59085. if(changeInfo.resolutionChanged){
  59086. this.dispatchEvent( {type:'resize', viewport});
  59087. }
  59088. }
  59089. }
  59090. return changed
  59091. }
  59092. makeScreenshot( size, viewports, compressRatio){//暂时不要指定viewports渲染,但也可以
  59093. let {width, height} = size;
  59094. /* let oldBudget = Potree.pointBudget;
  59095. Potree.pointBudget = Math.max(10 * 1000 * 1000, 2 * oldBudget);
  59096. let result = Potree.updatePointClouds(this.scene.pointclouds, camera, size );
  59097. Potree.pointBudget = oldBudget;
  59098. this.dispatchEvent({ //resize everything such as lines targets
  59099. type: 'resize',
  59100. resolution: new THREE.Vector2(width,height),
  59101. });*/
  59102. let target = new WebGLRenderTarget(width, height, {
  59103. format: RGBAFormat,
  59104. });
  59105. this.setSize(width, height,1,true);
  59106. this.render({
  59107. target ,
  59108. //camera ,
  59109. viewports: viewports || this.viewports,
  59110. screenshot : true,
  59111. width ,
  59112. height,
  59113. resize :true //需要resize
  59114. });
  59115. let dataUrl = Potree.Utils.renderTargetToDataUrl(target, width, height, this.renderer, compressRatio);
  59116. /* let pixelCount = width * height;
  59117. let buffer = new Uint8Array(4 * pixelCount);
  59118. this.renderer.readRenderTargetPixels(target, 0, 0, width, height, buffer);
  59119. let dataUrl = Potree.Utils.pixelsArrayToDataUrl(buffer, width, height, compressRatio) */
  59120. target.dispose();
  59121. //resize back
  59122. //this.updateScreenSize({forceUpdateSize:true})
  59123. return {
  59124. width,
  59125. height,
  59126. dataUrl
  59127. };
  59128. }
  59129. }
  59130. class Viewport extends EventDispatcher{
  59131. constructor( view, camera, prop={}){//目前不支持换camera
  59132. super();
  59133. this.left = prop.left;
  59134. this.bottom = prop.bottom;
  59135. this.width = prop.width;
  59136. this.height = prop.height;
  59137. this.name = prop.name;
  59138. this.view = view;
  59139. this.camera = camera;
  59140. this.active = true;
  59141. this.unableChangePos = false;
  59142. this.noPointcloud;
  59143. //this.keys = [...] firstPersonCtl....
  59144. this.resolution = new Vector2;
  59145. this.resolution2 = new Vector2;
  59146. this.offset = new Vector2; //viewportOffset 范围从0-整个画布的像素
  59147. this.extraEnableLayers = prop.extraEnableLayers || [];//额外可展示的层
  59148. this.cameraLayers = prop.cameraLayers;
  59149. this.pixelRatio = prop.pixelRatio; //如果规定pixelRatio的话要传,这样就覆盖devicePicelRatio, 如magnifier
  59150. }
  59151. clone(){
  59152. return Common$1.CloneClassObject(this)
  59153. }
  59154. getMoveSpeed(){
  59155. return this.moveSpeed
  59156. }
  59157. setMoveSpeed(e){
  59158. this.moveSpeed = e;
  59159. }
  59160. layersAdd(name){
  59161. this.extraEnableLayers.includes(name) || this.extraEnableLayers.push(name);
  59162. }
  59163. layersRemove(name){
  59164. let index = this.extraEnableLayers.indexOf(name);
  59165. if(index > -1){
  59166. this.extraEnableLayers.splice(index, 1);
  59167. }
  59168. }
  59169. cameraChanged() {
  59170. var copy = ()=>{
  59171. this.previousState = {
  59172. projectionMatrix: this.camera.projectionMatrix.clone(),//worldMatrix在this.control时归零了所以不用了吧,用position和qua也一样
  59173. position: this.camera.position.clone(),
  59174. quaternion: this.camera.quaternion.clone(),
  59175. active:this.active,
  59176. resolution:this.resolution.clone(),
  59177. resolution2:this.resolution2.clone(), //有时clientWidth没变但是ratio缩放了
  59178. };
  59179. };
  59180. let projectionChanged = true, positionChanged = true, quaternionChanged = true, activeChanged = true, resolutionChanged = true;
  59181. let getChanged = ()=>{
  59182. return {
  59183. projectionChanged,positionChanged,quaternionChanged, activeChanged, resolutionChanged,
  59184. changed:projectionChanged || positionChanged || quaternionChanged || activeChanged || resolutionChanged
  59185. }
  59186. };
  59187. if (this.previousState){
  59188. projectionChanged = !this.camera.projectionMatrix.equals(this.previousState.projectionMatrix);
  59189. positionChanged = !this.camera.position.equals(this.previousState.position);
  59190. quaternionChanged = !this.camera.quaternion.equals(this.previousState.quaternion);
  59191. activeChanged = this.active != this.previousState.active;
  59192. resolutionChanged = !this.resolution.equals(this.previousState.resolution) || !this.resolution2.equals(this.previousState.resolution2);
  59193. }
  59194. copy();
  59195. return getChanged()
  59196. }
  59197. setResolution(w,h, wholeW=0, wholeH=0){
  59198. this.resolution.set(w,h);//是client的width height
  59199. this.resolution2.copy(this.resolution).multiplyScalar(this.pixelRatio || window.devicePixelRatio);
  59200. this.offset.set(wholeW,wholeH).multiply(new Vector2(this.left,this.bottom));//.multiplyScalar(window.devicePixelRatio)
  59201. this.dispatchEvent({type:'resize'});
  59202. }
  59203. }
  59204. /**
  59205. * @author mschuetz / http://mschuetz.at
  59206. *
  59207. *
  59208. */
  59209. let {Buttons} = Potree.defines;
  59210. class InputHandler extends EventDispatcher {
  59211. constructor (viewer,scene) {
  59212. super();
  59213. this.viewer = viewer;
  59214. this.renderer = viewer.renderer;
  59215. this.domElement = this.renderer.domElement;
  59216. this.enabled = true;
  59217. this.scene = scene;
  59218. this.interactiveScenes = [];
  59219. this.interactiveObjects = new Set();
  59220. this.inputListeners = [];
  59221. this.blacklist = new Set();
  59222. this.drag = null;
  59223. this.mouse = new Vector2(0, 0);
  59224. //add:
  59225. this.pointer = new Vector2(0, 0); //交互点的屏幕坐标,有别于DOM坐标,在此存放NDC坐标。(NDC,三维常用坐标系,二维坐标,整个屏幕映射范围(-1,1),屏幕中心为原点,+Y朝上,+X朝右)
  59226. this.mouseDownMouse = new Vector2(0, 0);
  59227. this.selection = [];
  59228. this.hoveredElements = [];
  59229. this.pressedKeys = {};
  59230. this.wheelDelta = 0;
  59231. this.speed = 1;
  59232. this.logMessages = false;
  59233. if (this.domElement.tabIndex === -1) {
  59234. this.domElement.tabIndex = 2222;
  59235. }
  59236. this.lastPointerUpTime = 0;
  59237. this.touches = [];
  59238. this.interactHistory = {move:0}; //add
  59239. this.hoverViewport = viewer.viewports[0];
  59240. this.domElement.addEventListener('contextmenu', (event) => { event.preventDefault(); }, false);
  59241. this.domElement.addEventListener('click', this.onMouseClick.bind(this), false);
  59242. this.domElement.addEventListener('mousedown', this.onMouseDown.bind(this), false);
  59243. window.addEventListener('mouseup', this.onMouseUp.bind(this), false);
  59244. this.domElement.addEventListener('mousemove', this.onMouseMove.bind(this), false);
  59245. //add
  59246. /* this.domElement.addEventListener("pointerout", this.onMouseUp.bind(this)),
  59247. this.domElement.addEventListener("pointercancel", this.onMouseUp.bind(this)),
  59248. */
  59249. this.domElement.addEventListener('mousewheel', this.onMouseWheel.bind(this), false);
  59250. this.domElement.addEventListener('DOMMouseScroll', this.onMouseWheel.bind(this), false); // Firefox
  59251. //this.domElement.addEventListener('dblclick', this.onDoubleClick.bind(this)); //因为双击时间间隔是跟随系统的所以不好判断
  59252. this.domElement.addEventListener('keydown', this.onKeyDown.bind(this));
  59253. window.addEventListener('keyup', this.onKeyUp.bind(this));
  59254. //window.addEventListener('focus',()=>{
  59255. window.addEventListener('blur',this.onKeyUp.bind(this)); //add
  59256. this.domElement.addEventListener('touchstart', this.onTouchStart.bind(this));
  59257. this.domElement.addEventListener('touchend', this.onTouchEnd.bind(this));
  59258. this.domElement.addEventListener('touchmove', this.onTouchMove.bind(this));
  59259. {
  59260. this.addEventListener('isMeasuring',(e)=>{
  59261. //console.log('isMeasuring',e.v,e.cause)
  59262. this.isMeasuring = e.v;
  59263. });
  59264. }
  59265. window.viewer.addEventListener('loopStart',()=>{
  59266. this.interactHistory = {}; //清空
  59267. });
  59268. }
  59269. /* addInputListener (listener) {
  59270. this.inputListeners.push(listener);
  59271. }
  59272. removeInputListener (listener) {
  59273. this.inputListeners = this.inputListeners.filter(e => e !== listener);
  59274. }
  59275. getSortedListeners(){
  59276. return this.inputListeners.sort( (a, b) => {
  59277. let ia = (a.importance !== undefined) ? a.importance : 0;
  59278. let ib = (b.importance !== undefined) ? b.importance : 0;
  59279. return ib - ia;
  59280. });
  59281. } */
  59282. //统一跟第一个触碰的viewport相同
  59283. updateTouchesInfo(e){
  59284. var viewport, pointer, camera;
  59285. let oldTouches = this.touches;
  59286. let changedTouches = Array.from(e.changedTouches);
  59287. let touches = Array.from(e.touches);
  59288. this.touches = touches.map(touch=>{
  59289. let touch_ = oldTouches.find(a=>a.touch.identifier == touch.identifier);
  59290. let pointer = touch_ && touch_.pointer; //复制原先的值
  59291. return {
  59292. touch, pointer,
  59293. }
  59294. });
  59295. if(e.touches.length > 0){
  59296. let newTouches = touches.filter(e=>!
  59297. oldTouches.some(a=>a.touch.identifier == e.identifier) && !changedTouches.some(a=>a.identifier == e.identifier)
  59298. ); //从按钮处划过时e.touches中会出现this.touches和changedTouches中都没有的identifier
  59299. if(newTouches.length>0){
  59300. console.warn('has new',newTouches.map(e=>e.identifier));
  59301. }
  59302. newTouches.concat(changedTouches).forEach(touch=>{ //修改changedTouches的
  59303. let touch_ = this.touches.find(a=>a.touch.identifier == touch.identifier);
  59304. if(touch_){
  59305. let a = this.getPointerInViewport(touch.pageX, touch.pageY, this.dragViewport||viewport, new Vector2);
  59306. touch_.pointer = a.pointer.clone();
  59307. viewport = a.viewport; camera = a.camera;
  59308. }
  59309. });
  59310. //使用当前touches的平均
  59311. if(e.touches.length > 1){
  59312. let pageX = Common$1.average(e.touches, "pageX");
  59313. let pageY = Common$1.average(e.touches, "pageY");
  59314. let a = this.getPointerInViewport(pageX, pageY, viewport, new Vector2);
  59315. this.pointer.copy(a.pointer);
  59316. //console.log('updateTouchesInfo', this.pointer.clone())
  59317. }else {
  59318. this.pointer = this.touches[0].pointer.clone(); //更新,使用当前touches中的第一个
  59319. }
  59320. /* if(this.touches.find(e=>!e.pointer)){
  59321. console.error(' touches has no pointer', oldTouches.map(e=>e.touch.identifier),
  59322. Array.from(e.touches).map(e=>e.identifier), Array.from(e.changedTouches).map(e=>e.identifier) )
  59323. } */
  59324. //console.log(this.touches)
  59325. //console.log('更新pointer1',this.pointer.toArray())
  59326. return {viewport, camera/* , pointer:this.pointer */}
  59327. }
  59328. }
  59329. onTouchStart (e) {
  59330. if (this.logMessages) console.log(this.constructor.name + ': onTouchStart');
  59331. e.preventDefault();
  59332. /* if (e.touches.length === 1 || !this.drag) { //!this.drag代表一次性下了两个指头
  59333. let rect = this.domElement.getBoundingClientRect();
  59334. let x = e.touches[0].pageX
  59335. let y = e.touches[0].pageY
  59336. this.dealPointerDown(x,y,e,true)
  59337. }else{
  59338. this.updateTouchesInfo(e)
  59339. this.drag.end.copy(this.pointer)
  59340. } */
  59341. this.dealPointerDown(e,true);
  59342. this.viewer.dispatchEvent($.extend(
  59343. this.getEventDesc(e,true),
  59344. {
  59345. type: 'global_' + e.type,
  59346. changedTouches: e.changedTouches
  59347. }
  59348. ));
  59349. /* console.log('targetTouches :', Array.from(e.targetTouches).map(e=>'| identifier: '+ e.identifier),
  59350. 'changedTouches :', Array.from(e.changedTouches).map(e=>'| identifier: '+ e.identifier)
  59351. ) */
  59352. //console.log('')
  59353. }
  59354. onTouchMove (e) {
  59355. if (this.logMessages) console.log(this.constructor.name + ': onTouchMove');
  59356. e.preventDefault();
  59357. /* if (e.touches.length === 1) {
  59358. let rect = this.domElement.getBoundingClientRect();
  59359. let x = e.touches[0].pageX;
  59360. let y = e.touches[0].pageY;
  59361. }else{
  59362. this.updateTouchesInfo(e)
  59363. this.drag.pointerDelta.subVectors(this.pointer, this.drag.end)
  59364. this.drag.end.copy(this.pointer)
  59365. }
  59366. */
  59367. this.dealPointerMove(e, true);
  59368. this.viewer.dispatchEvent($.extend(
  59369. this.getEventDesc(e,true),
  59370. {
  59371. type: 'global_' + e.type,
  59372. changedTouches: e.changedTouches
  59373. }
  59374. ));
  59375. /* console.log('targetTouches :', Array.from(e.targetTouches).map(e=>'| identifier: '+ e.identifier),
  59376. 'changedTouches :', Array.from(e.changedTouches).map(e=>'| identifier: '+ e.identifier)
  59377. ) */
  59378. }
  59379. onTouchEnd (e) {
  59380. if (this.logMessages) console.log(this.constructor.name + ': onTouchEnd');
  59381. e.preventDefault();
  59382. //console.log('onTouchEnd')
  59383. this.updateTouchesInfo(e);
  59384. /* if (e.touches.length === 0) {
  59385. let rect = this.domElement.getBoundingClientRect();
  59386. let x = e.changedTouches[0].pageX //万一一次松开两个指头的怎么办
  59387. let y = e.changedTouches[0].pageY
  59388. this.dealPointerUp(x,y,e,true)
  59389. }else {
  59390. this.drag.end.copy(this.pointer)
  59391. } */
  59392. this.dealPointerUp(e,true);
  59393. this.viewer.dispatchEvent($.extend(
  59394. this.getEventDesc(e,true),
  59395. {
  59396. type: 'global_' + e.type,
  59397. }
  59398. ));
  59399. //console.log('touchend length '+e.touches.length, this.touches.length)
  59400. }
  59401. onKeyDown (e) {
  59402. if (this.logMessages) console.log(this.constructor.name + ': onKeyDown');
  59403. // DELETE
  59404. /* if (e.keyCode === KeyCodes.DELETE && this.selection.length > 0) {
  59405. this.dispatchEvent({
  59406. type: 'delete',
  59407. selection: this.selection
  59408. });
  59409. this.deselectAll();
  59410. } */
  59411. this.dispatchEvent({
  59412. type: 'keydown',
  59413. keyCode: e.keyCode,
  59414. event: e
  59415. });
  59416. // for(let l of this.getSortedListeners()){
  59417. // l.dispatchEvent({
  59418. // type: "keydown",
  59419. // keyCode: e.keyCode,
  59420. // event: e
  59421. // });
  59422. // }
  59423. this.pressedKeys[e.keyCode] = true;
  59424. // e.preventDefault();
  59425. }
  59426. onKeyUp (e) {
  59427. if (this.logMessages) console.log(this.constructor.name + ': onKeyUp');
  59428. if(e.keyCode != void 0){
  59429. delete this.pressedKeys[e.keyCode];
  59430. }else {
  59431. this.pressedKeys = {};
  59432. }
  59433. e.preventDefault();
  59434. }
  59435. onDoubleClick (e) {
  59436. if (this.logMessages) console.log(this.constructor.name + ': onDoubleClick');
  59437. let consumed = false;
  59438. for (let hovered of this.hoveredElements) {
  59439. if (hovered._listeners && hovered._listeners['dblclick']) {
  59440. hovered.object.dispatchEvent({
  59441. type: 'dblclick',
  59442. mouse: this.mouse,
  59443. object: hovered.object
  59444. });
  59445. consumed = true;
  59446. break;
  59447. }
  59448. }
  59449. if (!consumed) {
  59450. /* for (let inputListener of this.getSortedListeners()) {
  59451. inputListener. */this.viewer.dispatchEvent({
  59452. type: 'global_dblclick',
  59453. mouse: this.mouse,
  59454. object: null
  59455. });
  59456. //}
  59457. }
  59458. this.needSingleClick = false;//add
  59459. e.preventDefault();
  59460. }
  59461. onMouseClick (e) {
  59462. if (this.logMessages) console.log(this.constructor.name + ': onMouseClick');
  59463. e.preventDefault();
  59464. }
  59465. dealPointerDown(e,isTouch){
  59466. e.preventDefault();
  59467. //重新获取一下pointer, 因点击了浏览器的按钮展开列表时 move回来不会触发onmousemove,所以pointer是旧的
  59468. if(isTouch){
  59469. var { camera, viewport } = this.updateTouchesInfo(e);
  59470. if(this.drag){
  59471. //因为触屏在按下前缺少pointermove所以要更新下
  59472. this.drag.end = this.pointer.clone();
  59473. }
  59474. }else {
  59475. var { camera, viewport } = this.getPointerInViewport(e.clientX, e.clientY );
  59476. }
  59477. this.dragViewport = this.hoverViewport = viewport;
  59478. //if(isTouch || !Potree.settings.intersectWhenHover ){
  59479. if(isTouch || !this.dragViewport.view.isFlying()){
  59480. this.hoveredElements = this.getHoveredElements();
  59481. this.intersect = this.getIntersect(viewport); //更新intersect,避免在没有mousemove但flyToPano后intersect未更新。
  59482. //this.intersect = this.getWholeIntersect()
  59483. } //isTouch必须更新 否则是旧的
  59484. if(!viewport)return //why add this?
  59485. if (!this.drag) {
  59486. let target = (isTouch||e.button == MOUSE.LEFT) && this.hoveredElements.find(el => (//只有左键能拖拽
  59487. el.object._listeners &&
  59488. el.object._listeners['drag'] &&
  59489. el.object._listeners['drag'].length > 0));
  59490. if (target) {
  59491. this.startDragging(target.object, {location: target.point});
  59492. } else {
  59493. this.startDragging(null);
  59494. }
  59495. }
  59496. this.drag.intersectStart = this.intersect;
  59497. if(!isTouch || e.touches.length == 1){
  59498. let consumed = false;
  59499. let consume = () => { return consumed = true; };
  59500. //if (this.hoveredElements.length === 0) {
  59501. this.viewer.dispatchEvent($.extend(
  59502. this.getEventDesc(e,isTouch),
  59503. {
  59504. type: 'global_mousedown'
  59505. }
  59506. ));
  59507. for(let hovered of this.hoveredElements){
  59508. let object = hovered.object;
  59509. object.dispatchEvent({
  59510. type: 'mousedown',
  59511. viewer: this.viewer,
  59512. consume: consume
  59513. });
  59514. if(consumed){
  59515. break;
  59516. }
  59517. }
  59518. }
  59519. this.mouseDownMouse = this.mouse.clone();
  59520. this.pointerDownTime = Date.now();
  59521. }
  59522. onMouseDown (e) {
  59523. if (this.logMessages) console.log(this.constructor.name + ': onMouseDown');
  59524. this.dealPointerDown(e);
  59525. }
  59526. /* getWholeIntersect(hoveredElements, intersectPoint){//add
  59527. hoveredElements = hoveredElements || this.hoveredElements
  59528. intersectPoint = intersectPoint || this.intersectPoint
  59529. if(Potree.settings.intersectOnObjs && hoveredElements[0] && hoveredElements[0].object.isModel){
  59530. return {//模拟点云的intersectPoint的结构写法
  59531. hoveredElement : hoveredElements[0] ,
  59532. location: hoveredElements[0].point,
  59533. point: {normal: hoveredElements[0].face.normal },
  59534. distance: hoveredElements[0].distance,
  59535. object: hoveredElements[0].object
  59536. }
  59537. }else return intersectPoint
  59538. } */
  59539. getEventDesc(e,isTouch){//搜集dispatchEvent要给的一般数据
  59540. let o = {
  59541. viewer: this.viewer,
  59542. mouse: this.mouse,
  59543. pointer:this.pointer,
  59544. drag :this.drag,
  59545. isTouch,
  59546. dragViewport : this.dragViewport,
  59547. hoverViewport: this.hoverViewport,
  59548. // button: isTouch ? 0 : e.button,
  59549. //intersectPoint:this.intersectPoint,
  59550. hoveredElement: this.hoveredElements[0],
  59551. intersect: this.intersect//this.getWholeIntersect() , //可能包含mesh上的,针对融合页面
  59552. };
  59553. if(e){
  59554. o.isAtDomElement = e.target == this.domElement;
  59555. }
  59556. if(isTouch){
  59557. o.touches = this.touches;
  59558. }else if(e){
  59559. o.button = e.button;
  59560. o.buttons = e.buttons;
  59561. }
  59562. return o;
  59563. }
  59564. dealPointerUp(e,isTouch){
  59565. if(!this.drag){// 在canvas外mousedown
  59566. return
  59567. }
  59568. this.drag.end.copy(this.pointer);
  59569. if(isTouch && e.touches.length >= 1){
  59570. return
  59571. }
  59572. let now = Date.now();
  59573. if (this.logMessages) console.log(this.constructor.name + ': onMouseUp');
  59574. e.preventDefault();
  59575. let pressDistance = this.mouseDownMouse.distanceTo(this.mouse);
  59576. let pressTime = now - this.pointerDownTime;
  59577. let noMovement = this.drag.pointerDelta.length() == 0;//this.getNormalizedDrag().length() === 0;
  59578. let consumed = false;
  59579. let consume = () => { return consumed = true; };
  59580. //if (this.hoveredElements.length === 0) {
  59581. /* for (let inputListener of this.getSortedListeners()) {
  59582. inputListener */this.viewer.dispatchEvent($.extend(
  59583. this.getEventDesc(e,isTouch),
  59584. {
  59585. type: 'global_mouseup',
  59586. pressDistance,
  59587. consume,
  59588. }
  59589. ));
  59590. /* if(consumed){//??
  59591. break;
  59592. } */
  59593. //}
  59594. //}
  59595. if (this.hoveredElements.length > 0) {
  59596. let hovered = this.hoveredElements
  59597. .map(e => e.object)
  59598. .find(e => (e._listeners && e._listeners['mouseup']));
  59599. if(hovered){
  59600. hovered.dispatchEvent({
  59601. type: 'mouseup',
  59602. viewer: this.viewer,
  59603. consume: consume
  59604. });
  59605. }
  59606. }
  59607. if (this.drag) {
  59608. //拖拽结束
  59609. if (this.drag.object/* && e.button == THREE.MOUSE.LEFT */) {//add LEFT
  59610. if (this.logMessages) console.log(`${this.constructor.name}: drop ${this.drag.object.name}`);
  59611. this.drag.object.dispatchEvent($.extend(
  59612. this.getEventDesc(e,isTouch),
  59613. {
  59614. type: 'drop',
  59615. pressDistance,
  59616. pressTime
  59617. }
  59618. ));
  59619. } else {
  59620. this.viewer.dispatchEvent($.extend(
  59621. this.getEventDesc(e,isTouch),
  59622. {
  59623. type: 'global_drop',
  59624. pressDistance
  59625. }
  59626. ));
  59627. }
  59628. // check for a click
  59629. if(pressDistance < Potree.config.clickMaxDragDis && pressTime<Potree.config.clickMaxPressTime && !e.unableClick){
  59630. let clickElement, consumed = false;
  59631. if(this.hoveredElements){
  59632. clickElement = this.hoveredElements.find(e=>e.object._listeners['click']);
  59633. if(clickElement){
  59634. //console.log('clickElement',clickElement)
  59635. if (this.logMessages) console.log(`${this.constructor.name}: click ${clickElement.name}`);
  59636. clickElement.object.dispatchEvent($.extend(
  59637. this.getEventDesc(e,isTouch),
  59638. {
  59639. type: 'click',
  59640. pressDistance
  59641. }
  59642. ));
  59643. }
  59644. }
  59645. let selectable;
  59646. if(/* !consumed && */ !this.fixSelection){
  59647. if (e.button === MOUSE.LEFT) {
  59648. if (noMovement) {
  59649. selectable = this.hoveredElements.find(el => el.object._listeners && el.object._listeners['select']);
  59650. if (selectable) {
  59651. selectable = selectable.object;
  59652. if (this.isSelected(selectable)) {
  59653. this.deselectAll();
  59654. } else {
  59655. this.deselectAll();
  59656. this.toggleSelection(selectable);
  59657. }
  59658. consumed = true; //add
  59659. } else {
  59660. if(this.selection.length>0)consumed = true; //add 取消选择后,阻断后续
  59661. this.deselectAll();
  59662. }
  59663. }
  59664. } else if ((e.button === MOUSE.RIGHT) && noMovement) {
  59665. this.deselectAll();
  59666. }
  59667. }
  59668. let consume = () => { return consumed = true; };
  59669. let desc = this.getEventDesc(e,isTouch);
  59670. if(!consumed){
  59671. this.viewer.dispatchEvent($.extend(
  59672. desc,
  59673. {
  59674. type: 'global_click',
  59675. pressDistance,
  59676. clickElement:clickElement/* || selectable */,
  59677. consume
  59678. }
  59679. ));
  59680. }
  59681. //增加 单击:
  59682. this.needSingleClick = true;
  59683. consumed || setTimeout(()=>{
  59684. if(this.needSingleClick){
  59685. this.viewer.dispatchEvent($.extend(
  59686. desc,
  59687. {
  59688. type: 'global_single_click',
  59689. pressDistance,
  59690. clickElement
  59691. }
  59692. ));
  59693. }
  59694. }, Potree.config.doubleClickTime+1);
  59695. //自行执行双击:
  59696. if(now - this.lastClickTime < Potree.config.doubleClickTime){
  59697. this.onDoubleClick(e);
  59698. }
  59699. this.lastClickTime = now;
  59700. }
  59701. this.drag = null;
  59702. }
  59703. this.dragViewport = null;
  59704. }
  59705. onMouseUp (e) {
  59706. this.dealPointerUp( e );
  59707. }
  59708. getPointerInViewport(clientX, clientY, viewForceAt, pointer ){
  59709. let rect = this.domElement.getBoundingClientRect();
  59710. let x = clientX - rect.left;
  59711. let y = clientY - rect.top;
  59712. let camera;
  59713. let viewport;
  59714. pointer = pointer ||this.pointer;
  59715. //if(this.viewer.viewports || viewForceAt){
  59716. var getDimension = (view)=>{
  59717. var left = Math.ceil(this.domElement.clientWidth * view.left)
  59718. , bottom = Math.ceil(this.domElement.clientHeight * view.bottom)
  59719. , width = Math.ceil(this.domElement.clientWidth * view.width)
  59720. , height = Math.ceil(this.domElement.clientHeight * view.height)
  59721. , top = this.domElement.clientHeight - bottom - height;
  59722. return {left, bottom, width, height, top}
  59723. };
  59724. var getView = (view, left, bottom, width, height, top)=>{
  59725. this.mouse.set(x-left, y - top );
  59726. Utils.convertScreenPositionToNDC(pointer, this.mouse, width, height);
  59727. //console.log('更新pointer2',this.pointer.toArray())
  59728. camera = view.camera;
  59729. viewport = view;
  59730. };
  59731. if(viewForceAt){
  59732. let {left, bottom, width, height, top} = getDimension(viewForceAt);
  59733. getView(viewForceAt, left, bottom, width, height, top);
  59734. }else {
  59735. var length = this.viewer.viewports.length;
  59736. //var getif = false
  59737. for(var i=0;i<length;i++){
  59738. var view = this.viewer.viewports[i];
  59739. if(!view.active)continue
  59740. var {left, bottom, width, height, top} = getDimension(view);
  59741. if(x >= left && x <= left + width && y >= top && y <= top + height){
  59742. getView(view, left, bottom, width, height, top);
  59743. //getif = true
  59744. break;
  59745. }
  59746. }
  59747. }
  59748. return {
  59749. camera, viewport, pointer
  59750. }
  59751. }
  59752. ifBlockedByIntersect({pos3d, margin=0, cameraPos, pickWindowSize, pano, useDepthTex}={}){//某点是否被遮挡(不允许camera修改位置, 因为depthTex不好置换)
  59753. let intersect = this.getIntersect(this.hoverViewport, true, pickWindowSize, null, null, useDepthTex, {pos3d, cameraPos, pano});
  59754. let cameraPos_ = (!cameraPos && pano) ? pano.position : (cameraPos||this.hoverViewport.view.position);
  59755. if(intersect && intersect.distance+margin <= pos3d.distanceTo(cameraPos_)){
  59756. return intersect //被遮挡
  59757. }
  59758. //点云模式,对没加载出的点云不准确。 尤其是需要修改相机位置时,因临时修改并不能使点云加载。
  59759. }
  59760. getIntersect(viewport, onlyGetIntersect, pickWindowSize, dontIntersect, usePointcloud, useDepthTex, prop={}){// usePointcloud:必须使用点云
  59761. let intersectPoint;
  59762. let camera = viewport.camera;
  59763. let raycaster;
  59764. viewer.addTimeMark('getIntersect','start');
  59765. let getByDepthTex = ()=>{
  59766. let intersect;
  59767. if(prop.pos3d){
  59768. let cameraPos = prop.pano ? prop.pano.position : camera.position;
  59769. let dir = new Vector3().subVectors(prop.pos3d, cameraPos).normalize();
  59770. intersect = {dir};
  59771. }else {
  59772. intersect = Utils.getIntersect(camera, [viewer.images360.cube], this.pointer, raycaster);
  59773. }
  59774. intersectPoint = viewer.images360.depthSampler.sample(intersect, prop.pano, !!prop.pos3d); //可能不准确, 因pano可能未加载depthTex
  59775. if(intersectPoint && Potree.settings.depTexLocBindDataset){
  59776. intersectPoint.pointcloud = (prop.pano || viewer.images360.currentPano).pointcloud;
  59777. //在全景模式下,虽然深度图上的点可能对应别的pointcloud,但因为是在当前全景图处得到的,所以即使将原本对应的点云移走,该点也不移动是有道理的。它可以永远跟着该全景图。
  59778. }
  59779. };
  59780. let getByCloud = ()=>{
  59781. if(prop.pos3d){//指定了目标点,而非只是用pointer所在位置
  59782. prop.cameraPos && camera.position.copy(prop.cameraPos);
  59783. camera.lookAt(prop.pos3d);
  59784. camera.updateMatrixWorld();
  59785. prop.pointer = this.pointer.clone();
  59786. prop.mouse = this.mouse.clone();
  59787. this.pointer.set(0,0); //画布中心
  59788. this.mouse.set(Math.round(viewport.resolution.x/2), Math.round(viewport.resolution.y/2));
  59789. }
  59790. intersectPoint = (viewport.noPointcloud || dontIntersect)? null : Utils.getMousePointCloudIntersection(
  59791. viewport,
  59792. this.mouse,
  59793. this.pointer,
  59794. camera,
  59795. this.viewer,
  59796. this.viewer.scene.pointclouds,
  59797. {pickClipped: true, isMeasuring: this.isMeasuring, pickWindowSize, cameraChanged: !!prop.pos3d }
  59798. );
  59799. //恢复
  59800. if(prop.pos3d){
  59801. viewport.view.applyToCamera(camera);
  59802. this.pointer.copy(prop.pointer);
  59803. this.mouse.copy(prop.mouse);
  59804. }
  59805. };
  59806. let canUseDepthTex = !Potree.settings.unableUseDepTexPick && (Potree.settings.displayMode == 'showPanos' || useDepthTex)
  59807. && viewer.images360.currentPano.pointcloud.hasDepthTex && viewport == viewer.mainViewport && !usePointcloud;
  59808. /* if(canUseDepthTex)getByDepthTex()
  59809. else getByCloud() */
  59810. if(canUseDepthTex && !this.isMeasuring){
  59811. getByDepthTex();
  59812. }else {
  59813. getByCloud();
  59814. if(!intersectPoint && canUseDepthTex ){ //若在测量,先尝试点云,再用全景 //后来发现有深度图的点云全景visibleNode为空,pick不到的
  59815. getByDepthTex();
  59816. }
  59817. }
  59818. //console.log(viewport.name , intersectPoint && intersectPoint.location )
  59819. let intersect;
  59820. let intersectOnModel, allElements;
  59821. if(Potree.settings.intersectOnObjs && !dontIntersect){
  59822. if(prop.point){
  59823. raycaster = new Raycaster();
  59824. var dir = new Vector3().subVectors(prop.point, camera.position).normalize();
  59825. raycaster.set(camera.position, dir); //var origin = new THREE.Vector3(pointer.x, pointer.y, -1).unproject(camera),
  59826. }
  59827. allElements = this.getHoveredElements(viewer.objs.children, true, raycaster);
  59828. if(allElements[0]){
  59829. intersectOnModel = {//模拟点云的intersectPoint的结构写法
  59830. hoveredElement : allElements[0] ,
  59831. location: allElements[0].point,
  59832. //point: {normal: allElements[0].face.normal },
  59833. normal: allElements[0].face && allElements[0].face.normal,
  59834. distance: allElements[0].distance,
  59835. object: allElements[0].object
  59836. };
  59837. }
  59838. }
  59839. if(intersectPoint && intersectOnModel){
  59840. if(intersectPoint.distance < intersectOnModel.distance){
  59841. intersect = intersectPoint;
  59842. }else {
  59843. intersect = intersectOnModel;
  59844. }
  59845. }else {
  59846. intersect = intersectOnModel || intersectPoint;
  59847. }
  59848. if(viewport.camera.type == 'OrthographicCamera'/* == 'mapViewport' */){
  59849. let pos3d = new Vector3(this.pointer.x,this.pointer.y,-1).unproject(viewport.camera); //z:-1朝外
  59850. if(!intersect){
  59851. intersect = {};
  59852. }
  59853. intersect.orthoIntersect = pos3d.clone();
  59854. }
  59855. //记录全部hover到的:
  59856. if(intersect){
  59857. intersect.allElements = allElements;
  59858. intersect.pointclouds = intersectPoint ? intersectPoint.pointclouds : [];
  59859. }
  59860. viewer.addTimeMark('getIntersect','end');
  59861. //点云费时:2-15ms
  59862. //深度图费时: 0.1-0.2ms
  59863. this.viewer.dispatchEvent({type:'getIntersect', intersect});
  59864. if(onlyGetIntersect){
  59865. return intersect
  59866. }
  59867. if (intersect) {
  59868. if(viewer.showCoordType){ //显示坐标位置时
  59869. let pos = intersect.point.position.toArray();
  59870. if(viewer.showCoordType == "local"){
  59871. }else if(viewer.showCoordType == "lonlat"){
  59872. pos = viewer.transform.lonlatToLocal.inverse(pos);
  59873. }else {
  59874. pos = viewer.transform.lonlatToLocal.inverse(pos);
  59875. pos = viewer.transform.lonlatTo4550.forward(pos);
  59876. }
  59877. viewer.dispatchEvent({
  59878. type : "coordinateChange", pos
  59879. });
  59880. }
  59881. }
  59882. //console.log('getIntersect', !!intersectPoint)
  59883. this.intersect = intersect;
  59884. intersect && (this.hoverViewport.lastIntersect = intersect);
  59885. return intersect
  59886. }
  59887. onMouseMove (e) {
  59888. return this.dealPointerMove( e )
  59889. }
  59890. dealPointerMove(e, isTouch){
  59891. if(this.interactHistory.move) return //一帧只触发一次
  59892. this.interactHistory.move = 1;
  59893. if(isTouch){
  59894. var { camera, viewport } = this.updateTouchesInfo(e);
  59895. }else {
  59896. var { camera, viewport } = this.getPointerInViewport(e.clientX, e.clientY, this.dragViewport);
  59897. }
  59898. this.hoverViewport = viewport;
  59899. if(!viewport)return//刚变化viewport时会找不到
  59900. let isFlying = this.viewer.viewports.some(e=>e.view.isFlying()) || viewer.scene.cameraAnimations.some(c=>c.onUpdate);
  59901. let intersect;
  59902. if(e.onlyGetIntersect || Potree.settings.intersectWhenHover && (!this.drag || this.drag.object || viewport.alignment ) ){ //没有拖拽物体,但按下鼠标了的话,不intersect。触屏的就能直接避免intersect
  59903. let dontIntersect = this.drag && viewport.alignment || isFlying; /* viewer.images360.flying */ // flying 时可能卡顿
  59904. //console.log('dontIntersectPointcloud',dontIntersectPointcloud)
  59905. intersect = this.getIntersect(viewport, e.onlyGetIntersect, e.pickWindowSize, !!dontIntersect, e.whichPointcloud || e.usePointcloud || this.drag); //深度图不准,尽量用点云
  59906. //console.log('intersectPoint', intersectPoint)
  59907. }
  59908. if(e.onlyGetIntersect){
  59909. /* if(Potree.settings.intersectOnObjs){
  59910. let hoveredElements = this.getHoveredElements() //应该不用发送mouseover事件吧
  59911. let intersect = this.getWholeIntersect(hoveredElements, intersectPoint)
  59912. return intersect
  59913. }
  59914. return intersectPoint */
  59915. return intersect
  59916. }
  59917. e.preventDefault();
  59918. /* if(intersectPoint && intersectPoint.pointcloud){
  59919. console.log(intersectPoint.pointcloud.name)
  59920. } */
  59921. if (this.drag) {//有拖拽(不一定拖拽了物体, 也不一定按下了鼠标)
  59922. this.drag.mouse = isTouch ? 1 : e.buttons;
  59923. //add:
  59924. //this.drag.pointer = this.pointer.clone();
  59925. //this.drag.hoverViewport = this.hoverViewport
  59926. this.drag.pointerDelta.subVectors(this.pointer, this.drag.end);
  59927. this.drag.end.copy(this.pointer);
  59928. if (this.drag.object && (e.buttons == Buttons.NONE || !this.drag.notPressMouse )){//如果是本不需要按鼠标的拖拽,但按下了鼠标,就不执行这段(改为拖拽场景,如添加测量时突然拖拽画面)
  59929. if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);
  59930. this.drag.object.dispatchEvent($.extend(
  59931. this.getEventDesc(e,isTouch),
  59932. {
  59933. type: 'drag', //拖拽物体
  59934. }
  59935. ));
  59936. viewer.dispatchEvent('content_changed');
  59937. } else {
  59938. if (this.logMessages) console.log(this.constructor.name + ': drag: ');
  59939. let dragConsumed = false;
  59940. this.viewer.dispatchEvent($.extend(
  59941. this.getEventDesc(e,isTouch),
  59942. {
  59943. type: 'global_drag', //拖拽画面
  59944. consume: () => {dragConsumed = true;}
  59945. }
  59946. ));
  59947. }
  59948. }
  59949. if(!isTouch || e.touches.length == 1){
  59950. if((!this.drag || this.drag.notPressMouse || Potree.settings.intersectOnObjs && this.drag.object) && !isFlying){
  59951. /* let blacklist = this.drag && this.drag */
  59952. let hoveredElements = this.getHoveredElements( );
  59953. if(hoveredElements.length > 0){
  59954. let names = hoveredElements.map(h => h.object.name).join(", ");
  59955. if (this.logMessages) console.log(`${this.constructor.name}: onMouseMove; hovered: '${names}'`);
  59956. }
  59957. let curr = hoveredElements.map(a => a.object).find(a => true);//只取第一个
  59958. let prev = this.lastMouseoverElement; //this.hoveredElements.map(a => a.object).find(a => true);
  59959. if(curr !== prev){
  59960. if(curr){
  59961. if (this.logMessages) console.log(`${this.constructor.name}: mouseover: ${curr.name}`);
  59962. curr.dispatchEvent({
  59963. type: 'mouseover',
  59964. object: curr,
  59965. });
  59966. }
  59967. if(prev){
  59968. if (this.logMessages) console.log(`${this.constructor.name}: mouseleave: ${prev.name}`);
  59969. prev.dispatchEvent({
  59970. type: 'mouseleave',
  59971. object: prev,
  59972. });
  59973. }
  59974. this.lastMouseoverElement = curr;
  59975. viewer.dispatchEvent('content_changed');
  59976. }
  59977. if(hoveredElements.length > 0){
  59978. let object = hoveredElements
  59979. .map(e => e.object)
  59980. .find(e => (e._listeners && e._listeners['mousemove']));
  59981. if(object){
  59982. object.dispatchEvent({
  59983. type: 'mousemove',
  59984. object: object
  59985. });
  59986. }
  59987. }
  59988. this.hoveredElements = hoveredElements;
  59989. }
  59990. //this.intersect = this.getWholeIntersect()
  59991. this.viewer.dispatchEvent($.extend(
  59992. this.getEventDesc(e,isTouch),
  59993. {
  59994. type: 'global_mousemove',
  59995. }
  59996. ));
  59997. }
  59998. }
  59999. onMouseWheel(e){
  60000. if(!this.enabled) return;
  60001. if(this.logMessages) console.log(this.constructor.name + ": onMouseWheel");
  60002. e.preventDefault();
  60003. let delta = 0;
  60004. if (e.wheelDelta !== undefined) { // WebKit / Opera / Explorer 9
  60005. delta = e.wheelDelta;
  60006. } else if (e.detail !== undefined) { // Firefox
  60007. delta = -e.detail;
  60008. }
  60009. let ndelta = Math.sign(delta);
  60010. // this.wheelDelta += Math.sign(delta);
  60011. if(!this.hoverViewport){//调试手机版时会无
  60012. var { viewport } = this.getPointerInViewport(e.clientX, e.clientY );
  60013. this.hoverViewport = viewport;
  60014. }
  60015. if (this.hoveredElement) {
  60016. this.hoveredElement.object.dispatchEvent($.extend(
  60017. this.getEventDesc(e,isTouch),
  60018. {
  60019. type: 'mousewheel',
  60020. delta: ndelta,
  60021. object: this.hoveredElement.object
  60022. }
  60023. ));
  60024. } else {
  60025. this.viewer.dispatchEvent($.extend(
  60026. this.getEventDesc(e),
  60027. {
  60028. type: 'global_mousewheel',
  60029. delta: ndelta,
  60030. }
  60031. ));
  60032. }
  60033. setTimeout(()=>{
  60034. this.dealPointerMove(e );//add 在更新完view后重新获取intersect 和 drag
  60035. },1);//只延迟1会崩溃吗
  60036. }
  60037. startDragging (object, args = null) {
  60038. let name = object ? object.name : "no name";
  60039. if (this.logMessages) console.log(`${this.constructor.name}: startDragging: '${name}'`);
  60040. this.drag = {
  60041. start: this.pointer.clone(),
  60042. end: this.pointer.clone(),
  60043. pointerDelta: new Vector2(0, 0),
  60044. object: object,
  60045. hoverViewport: this.hoverViewport, //会变化
  60046. dragViewport: this.hoverViewport, //不变
  60047. };
  60048. if (args) {
  60049. for (let key of Object.keys(args)) {
  60050. this.drag[key] = args[key];
  60051. }
  60052. }
  60053. if(object){
  60054. object.dispatchEvent($.extend(
  60055. this.getEventDesc(),
  60056. {
  60057. type: 'startDragging'
  60058. }
  60059. ));
  60060. }
  60061. }
  60062. /* getMousePointCloudIntersection (mouse) {
  60063. return Utils.getMousePointCloudIntersection(
  60064. this.mouse,
  60065. this.scene.getActiveCamera(),
  60066. this.viewer,
  60067. this.scene.pointclouds);
  60068. } */
  60069. toggleSelection (object) {
  60070. let oldSelection = this.selection;
  60071. let index = this.selection.indexOf(object);
  60072. if (index === -1) {
  60073. this.selection.push(object);
  60074. object.dispatchEvent({
  60075. type: 'select'
  60076. });
  60077. } else {
  60078. this.selection.splice(index, 1);
  60079. object.dispatchEvent({
  60080. type: 'deselect'
  60081. });
  60082. }
  60083. this.dispatchEvent({
  60084. type: 'selection_changed',
  60085. oldSelection: oldSelection,
  60086. selection: this.selection
  60087. });
  60088. viewer.dispatchEvent('content_changed');
  60089. }
  60090. deselect(object){
  60091. let oldSelection = this.selection;
  60092. let index = this.selection.indexOf(object);
  60093. if(index >= 0){
  60094. this.selection.splice(index, 1);
  60095. object.dispatchEvent({
  60096. type: 'deselect'
  60097. });
  60098. this.dispatchEvent({
  60099. type: 'selection_changed',
  60100. oldSelection: oldSelection,
  60101. selection: this.selection
  60102. });
  60103. }
  60104. viewer.dispatchEvent('content_changed');
  60105. }
  60106. deselectAll () {
  60107. for (let object of this.selection) {
  60108. object.dispatchEvent({
  60109. type: 'deselect'
  60110. });
  60111. }
  60112. let oldSelection = this.selection;
  60113. if (this.selection.length > 0) {
  60114. this.selection = [];
  60115. this.dispatchEvent({
  60116. type: 'selection_changed',
  60117. oldSelection: oldSelection,
  60118. selection: this.selection
  60119. });
  60120. }
  60121. viewer.dispatchEvent('content_changed');
  60122. }
  60123. isSelected (object) {
  60124. let index = this.selection.indexOf(object);
  60125. return index !== -1;
  60126. }
  60127. registerInteractiveObject(object){
  60128. this.interactiveObjects.add(object);
  60129. }
  60130. removeInteractiveObject(object){
  60131. this.interactiveObjects.delete(object);
  60132. }
  60133. registerInteractiveScene (scene) {
  60134. let index = this.interactiveScenes.indexOf(scene);
  60135. if (index === -1) {
  60136. this.interactiveScenes.push(scene);
  60137. }
  60138. }
  60139. unregisterInteractiveScene (scene) {
  60140. let index = this.interactiveScenes.indexOf(scene);
  60141. if (index > -1) {
  60142. this.interactiveScenes.splice(index, 1);
  60143. }
  60144. }
  60145. getHoveredElement () {
  60146. let hoveredElements = this.getHoveredElements();
  60147. if (hoveredElements.length > 0) {
  60148. return hoveredElements[0];
  60149. } else {
  60150. return null;
  60151. }
  60152. }
  60153. getHoveredElements (interactables, dontCheckDis, raycaster) {
  60154. if(!interactables){
  60155. let scenes = this.hoverViewport.interactiveScenes || this.interactiveScenes.concat(this.scene);
  60156. let interactableListeners = ['mouseup', 'mousemove', 'mouseover', 'mouseleave', 'drag', 'drop', 'click', 'select', 'deselect'];
  60157. interactables = [];
  60158. for (let scene of scenes) {
  60159. scene.traverseVisible(node => {//检测加了侦听的object
  60160. if (node._listeners && node.visible && !this.blacklist.has(node) ) {
  60161. let hasInteractableListener = interactableListeners.filter((e) => {
  60162. return node._listeners[e] !== undefined;
  60163. }).length > 0;
  60164. if (hasInteractableListener) {
  60165. interactables.push(node);
  60166. }
  60167. }
  60168. });
  60169. }
  60170. }
  60171. let camera = this.hoverViewport.camera;
  60172. if(!raycaster){
  60173. let ray = Utils.mouseToRay(this.pointer, camera );
  60174. raycaster = new Raycaster();
  60175. raycaster.ray.set(ray.origin, ray.direction);
  60176. raycaster.camera = camera; //add
  60177. }
  60178. if(camera.type == "OrthographicCamera"){//使无论多远,threshold区域都是一样宽的
  60179. raycaster.params.Line.threshold = 20/camera.zoom;
  60180. }else {
  60181. raycaster.params.Line.threshold = 0.04; //相对长度
  60182. }
  60183. raycaster.params.Line2 = {threshold :20 }; //拓宽的lineWidth
  60184. //raycaster.layers.enableAll()//add
  60185. Potree.Utils.setCameraLayers(raycaster, //设置能识别到的layers(如空间模型里只有mapViewer能识别到marker)
  60186. ['sceneObjects','mapObjects','measure', 'transformationTool', 'model'],
  60187. this.hoverViewport && this.hoverViewport.extraEnableLayers
  60188. );
  60189. //this.hoverViewport.beforeRender && this.hoverViewport.beforeRender()
  60190. viewer.dispatchEvent( {type:'raycaster', viewport: this.hoverViewport});//add
  60191. let intersections = raycaster.intersectObjects(interactables.filter(o => o.visible), true, null, true); //原本是false 检测不到children
  60192. let intersectionsCopy = intersections.slice();
  60193. if(this.intersect && this.intersect.distance != void 0 && !dontCheckDis){//add
  60194. intersections = intersections.filter(e=>{
  60195. let material = e.object.material;
  60196. return e.object.pickDontCheckDis || ( material.depthTest == false || material.depthWrite == false) && !material.realUseDepth //!material.depthTestWhenPick
  60197. || ( material.useDepth ? e.distance < this.intersect.distance + material.uniforms.occlusionDistance.value : e.distance < this.intersect.distance )
  60198. });
  60199. }
  60200. intersections = intersections.map(e=>{//add 转化为interactables
  60201. var object = e.object;
  60202. do{
  60203. if(interactables.includes(object)) {
  60204. e.oriObject = e.object;
  60205. e.object = object;
  60206. break
  60207. }
  60208. object = object.parent;
  60209. }while(object)
  60210. return e
  60211. });
  60212. //add for测量线,在检测到sphere时优先选中sphere而非线
  60213. //intersections = intersections.sort(function(a,b){return b.object.renderOrder-a.object.renderOrder}) // 降序
  60214. intersections = intersections.sort(function(a,b){
  60215. let order2 = b.object.pickOrder || 0;
  60216. let order1 = a.object.pickOrder || 0;
  60217. return order2-order1
  60218. }); // 降序
  60219. return intersections;
  60220. }
  60221. /* setScene (scene) {
  60222. this.deselectAll();
  60223. this.scene = scene;
  60224. } */
  60225. update (delta) {
  60226. }
  60227. /*getNormalizedDrag () {
  60228. if (!this.drag) {
  60229. return new THREE.Vector2(0, 0);
  60230. }
  60231. let diff = new THREE.Vector2().subVectors(this.drag.end, this.drag.start);
  60232. diff.x = diff.x / this.domElement.clientWidth;
  60233. diff.y = diff.y / this.domElement.clientHeight;
  60234. return diff;
  60235. }
  60236. getNormalizedLastDrag () {
  60237. if (!this.drag) {
  60238. return new THREE.Vector2(0, 0);
  60239. }
  60240. let mouseDelta = this.drag.mouseDelta.clone();
  60241. mouseDelta.x = mouseDelta.x / this.domElement.clientWidth;
  60242. mouseDelta.y = mouseDelta.y / this.domElement.clientHeight;
  60243. return mouseDelta;
  60244. } */
  60245. getMouseDirection(pointer) {//add
  60246. pointer = pointer || this.pointer;
  60247. let camera = this.hoverViewport.camera;
  60248. var t = new Vector3(pointer.x, pointer.y, -1).unproject(camera),
  60249. i = new Vector3(pointer.x, pointer.y, 1).unproject(camera);
  60250. return {origin: t, direction:i.clone().sub(t).normalize() }
  60251. }
  60252. }
  60253. /**
  60254. * @author mschuetz / http://mschuetz.at
  60255. *
  60256. * adapted from THREE.OrbitControls by
  60257. *
  60258. * @author qiao / https://github.com/qiao
  60259. * @author mrdoob / http://mrdoob.com
  60260. * @author alteredq / http://alteredqualia.com/
  60261. * @author WestLangley / http://github.com/WestLangley
  60262. * @author erich666 / http://erichaines.com
  60263. *
  60264. *
  60265. *
  60266. */
  60267. let minRadius = 2;
  60268. class OrbitControls extends EventDispatcher{
  60269. constructor(viewer, viewport){
  60270. super();
  60271. this.viewer = viewer;
  60272. this.renderer = viewer.renderer;
  60273. this.scene = null;
  60274. this.sceneControls = new Scene();
  60275. this.rotationSpeed = 3; //旋转速度
  60276. this.setCurrentViewport({hoverViewport:viewport, force:true}); //this.currentViewport = viewport
  60277. this.fadeFactor = 8;
  60278. this.yawDelta = 0;
  60279. this.pitchDelta = 0;
  60280. this.panDelta = new Vector2(0, 0);
  60281. this.radiusDelta = 0;
  60282. this.doubleClockZoomEnabled = true;
  60283. this.tweens = [];
  60284. this.dollyStart = new Vector2;
  60285. this.dollyEnd = new Vector2;
  60286. this.keys = {
  60287. FORWARD: ['W'.charCodeAt(0), 38],
  60288. BACKWARD: ['S'.charCodeAt(0), 40],
  60289. LEFT: ['A'.charCodeAt(0), 37],
  60290. RIGHT: ['D'.charCodeAt(0), 39],
  60291. UP: ['Q'.charCodeAt(0)],
  60292. DOWN: ['E'.charCodeAt(0)],
  60293. };
  60294. let drag = (e) => {
  60295. if(!this.enabled)return
  60296. let viewport = e.dragViewport;
  60297. if(!viewport /* || viewport.camera.type == "OrthographicCamera" */)return
  60298. //let camera = viewport.camera
  60299. if (e.drag.object !== null) {
  60300. return;
  60301. }
  60302. let mode;
  60303. if(e.isTouch){
  60304. if(e.touches.length == 1){
  60305. mode = 'rotate';
  60306. }else {
  60307. mode = 'scale-pan';
  60308. }
  60309. }else {
  60310. mode = e.buttons === Potree.defines.Buttons.LEFT ? 'rotate' : 'pan';
  60311. }
  60312. if (e.drag.startHandled === undefined) {
  60313. e.drag.startHandled = true;
  60314. this.dispatchEvent({type: 'start'});
  60315. }
  60316. let ndrag = e.drag.pointerDelta.clone();//.add(new THREE.Vector2(1,1)).multiplyScalar(0.5)
  60317. ndrag.y *= -1;
  60318. if (mode == 'rotate') {
  60319. this.yawDelta += ndrag.x * this.rotationSpeed;
  60320. this.pitchDelta += ndrag.y * this.rotationSpeed;
  60321. } else if(mode == 'pan'){
  60322. this.panDelta.x += ndrag.x;
  60323. this.panDelta.y += ndrag.y;
  60324. }else if(mode == 'scale-pan'){ //add
  60325. this.dollyEnd.subVectors(e.touches[0].pointer, e.touches[1].pointer);
  60326. var scale = this.dollyEnd.length() / this.dollyStart.length();
  60327. this.dollyStart.copy(this.dollyEnd);
  60328. this.radiusDelta = (1-scale) * this.currentViewport.view.radius;
  60329. //------------------------
  60330. //平移
  60331. let pointer = new Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5);//两个指头的中心点
  60332. let delta = new Vector2().subVectors(pointer, this.lastScalePointer);
  60333. delta.y *= -1;
  60334. this.panDelta.add(delta);
  60335. this.lastScalePointer = pointer.clone();
  60336. //console.log('scale ',scale, this.radiusDelta)
  60337. }
  60338. this.stopTweens();
  60339. };
  60340. let drop = e => {
  60341. if(!this.enabled)return
  60342. this.dispatchEvent({type: 'end'});
  60343. };
  60344. let scroll = (e) => {
  60345. if(!this.enabled)return
  60346. let resolvedRadius = this.currentViewport.view.radius + this.radiusDelta;
  60347. if(resolvedRadius < 0.1 && e.delta>0)return; //防止缩放太小,导致很慢
  60348. this.radiusDelta += -e.delta * resolvedRadius * 0.1;
  60349. this.stopTweens();
  60350. };
  60351. let dblclick = (e) => {
  60352. if(!this.enabled)return
  60353. if(this.doubleClockZoomEnabled){
  60354. this.zoomToLocation(e.mouse);
  60355. }
  60356. };
  60357. let previousTouch = null;
  60358. let touchStart = e => {
  60359. previousTouch = e;
  60360. };
  60361. let touchEnd = e => {
  60362. previousTouch = e;
  60363. };
  60364. let touchMove = e => {
  60365. if(!this.enabled)return
  60366. if (e.touches.length === 2 && previousTouch.touches.length === 2){
  60367. let prev = previousTouch;
  60368. let curr = e;
  60369. let prevDX = prev.touches[0].pageX - prev.touches[1].pageX;
  60370. let prevDY = prev.touches[0].pageY - prev.touches[1].pageY;
  60371. let prevDist = Math.sqrt(prevDX * prevDX + prevDY * prevDY);
  60372. let currDX = curr.touches[0].pageX - curr.touches[1].pageX;
  60373. let currDY = curr.touches[0].pageY - curr.touches[1].pageY;
  60374. let currDist = Math.sqrt(currDX * currDX + currDY * currDY);
  60375. let delta = currDist / prevDist;
  60376. let resolvedRadius = this.currentViewport.view.radius + this.radiusDelta;
  60377. let newRadius = resolvedRadius / delta;
  60378. this.radiusDelta = newRadius - resolvedRadius;
  60379. this.stopTweens();
  60380. }else if(e.touches.length === 3 && previousTouch.touches.length === 3){
  60381. let prev = previousTouch;
  60382. let curr = e;
  60383. let prevMeanX = (prev.touches[0].pageX + prev.touches[1].pageX + prev.touches[2].pageX) / 3;
  60384. let prevMeanY = (prev.touches[0].pageY + prev.touches[1].pageY + prev.touches[2].pageY) / 3;
  60385. let currMeanX = (curr.touches[0].pageX + curr.touches[1].pageX + curr.touches[2].pageX) / 3;
  60386. let currMeanY = (curr.touches[0].pageY + curr.touches[1].pageY + curr.touches[2].pageY) / 3;
  60387. let delta = {
  60388. x: (currMeanX - prevMeanX) / this.renderer.domElement.clientWidth,
  60389. y: (currMeanY - prevMeanY) / this.renderer.domElement.clientHeight
  60390. };
  60391. this.panDelta.x += delta.x;
  60392. this.panDelta.y += delta.y;
  60393. this.stopTweens();
  60394. }
  60395. previousTouch = e;
  60396. };
  60397. this.addEventListener('touchstart', touchStart);
  60398. this.addEventListener('touchend', touchEnd);
  60399. this.addEventListener('touchmove', touchMove);
  60400. this.viewer.addEventListener('global_drag', drag);
  60401. this.viewer.addEventListener('global_drop', drop);
  60402. this.viewer.addEventListener('global_mousewheel', scroll);
  60403. this.viewer.addEventListener('global_dblclick', dblclick);
  60404. this.viewer.addEventListener('global_touchmove', (e)=>{
  60405. if(e.touches.length>1){//单指的就触发上一句
  60406. //console.log('global_touchmove' )
  60407. drag(e);
  60408. }
  60409. });
  60410. let prepareScale = (e)=>{//触屏的scale
  60411. this.dollyStart.subVectors(e.touches[0].pointer, e.touches[1].pointer);
  60412. this.lastScalePointer = new Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5);//两个指头的中心点
  60413. };
  60414. this.viewer.addEventListener('global_touchstart', (e)=>{
  60415. if(this.enabled && e.touches.length==2){//只监听开头两个指头
  60416. prepareScale(e);
  60417. }
  60418. });
  60419. /* this.viewer.addEventListener('global_touchend', (e)=>{
  60420. if(!this.enabled)return
  60421. if(e.touches.length==1){//停止scale,开始rotate
  60422. prepareRotate(e)
  60423. //this.pointerDragStart = null
  60424. //console.log('只剩一个', e.pointer.toArray())
  60425. }
  60426. }) */
  60427. this.viewer.addEventListener('focusOnObject',(o)=>{
  60428. if(o.position && o.CamTarget){
  60429. let distance = o.position.distanceTo(o.CamTarget);
  60430. if(distance < minRadius) minRadius = distance * 0.5; //融合页面当focus一个很小的物体时,需要将minRadius也调小
  60431. }
  60432. });
  60433. }
  60434. setScene (scene) {
  60435. this.scene = scene;
  60436. }
  60437. setCurrentViewport(o={}){//add
  60438. if(!this.enabled && !o.force )return
  60439. if(o.hoverViewport && this.currentViewport != o.hoverViewport ){
  60440. this.currentViewport = o.hoverViewport;
  60441. }
  60442. }
  60443. setEnable(enabled){
  60444. this.enabled = enabled;
  60445. }
  60446. stop(){
  60447. this.yawDelta = 0;
  60448. this.pitchDelta = 0;
  60449. this.radiusDelta = 0;
  60450. this.panDelta.set(0, 0);
  60451. }
  60452. /* zoomToLocation(mouse){
  60453. if(!this.enabled)return
  60454. let camera = this.scene.getActiveCamera();
  60455. let I = Utils.getMousePointCloudIntersection(
  60456. null, mouse, this.viewer.inputHandler.pointer,
  60457. camera,
  60458. this.viewer,
  60459. this.scene.pointclouds,
  60460. {pickClipped: true});
  60461. if (I === null) {
  60462. return;
  60463. }
  60464. let targetRadius = 0;
  60465. {
  60466. let minimumJumpDistance = 0.2;
  60467. let domElement = this.renderer.domElement;
  60468. let ray = Utils.mouseToRay(this.viewer.inputHandler.pointer , camera, domElement.clientWidth, domElement.clientHeight);
  60469. let nodes = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, ray);
  60470. let lastNode = nodes[nodes.length - 1];
  60471. let radius = lastNode.getBoundingSphere(new THREE.Sphere()).radius;
  60472. targetRadius = Math.min(this.currentViewport.view.radius, radius);
  60473. targetRadius = Math.max(minimumJumpDistance, targetRadius);
  60474. }
  60475. let d = this.currentViewport.view.direction.multiplyScalar(-1);
  60476. let cameraTargetPosition = new THREE.Vector3().addVectors(I.location, d.multiplyScalar(targetRadius));
  60477. // TODO Unused: let controlsTargetPosition = I.location;
  60478. let animationDuration = 600;
  60479. let easing = TWEEN.Easing.Quartic.Out;
  60480. { // animate
  60481. let value = {x: 0};
  60482. let tween = new TWEEN.Tween(value).to({x: 1}, animationDuration);
  60483. tween.easing(easing);
  60484. this.tweens.push(tween);
  60485. let startPos = this.currentViewport.view.position.clone();
  60486. let targetPos = cameraTargetPosition.clone();
  60487. let startRadius = this.currentViewport.view.radius;
  60488. let targetRadius = cameraTargetPosition.distanceTo(I.location);
  60489. tween.onUpdate(() => {
  60490. let t = value.x;
  60491. this.currentViewport.view.position.x = (1 - t) * startPos.x + t * targetPos.x;
  60492. this.currentViewport.view.position.y = (1 - t) * startPos.y + t * targetPos.y;
  60493. this.currentViewport.view.position.z = (1 - t) * startPos.z + t * targetPos.z;
  60494. this.currentViewport.view.radius = (1 - t) * startRadius + t * targetRadius;
  60495. this.viewer.setMoveSpeed(this.currentViewport.view.radius);
  60496. });
  60497. tween.onComplete(() => {
  60498. this.tweens = this.tweens.filter(e => e !== tween);
  60499. });
  60500. tween.start();
  60501. }
  60502. } */
  60503. zoomToLocation(mouse){
  60504. let I = viewer.inputHandler.intersect;
  60505. if(!I)return
  60506. let object = I.object || I.pointcloud;
  60507. I = I.location;
  60508. if(!I || !object)return;
  60509. let dis = this.currentViewport.view.position.distanceTo(I);
  60510. let bound = object.boundingBox.clone().applyMatrix4(object.matrixWorld);
  60511. let size = bound.getSize(new Vector3);
  60512. let len = size.length();
  60513. let distance = MathUtils$1.clamp(dis, 0.1, Math.max(len * 0.1, 3) );
  60514. minRadius = distance;
  60515. viewer.focusOnObject({ position:I }, 'point', null, {distance});
  60516. }
  60517. stopTweens () {
  60518. this.tweens.forEach(e => e.stop());
  60519. this.tweens = [];
  60520. }
  60521. update (delta) {
  60522. if(!this.enabled)return
  60523. let view = this.currentViewport.view;//this.currentViewport.view;
  60524. let camera = this.currentViewport.camera;
  60525. { // accelerate while input is given
  60526. let ih = this.viewer.inputHandler;
  60527. let moveForward = this.keys.FORWARD.some(e => ih.pressedKeys[e]);
  60528. let moveBackward = this.keys.BACKWARD.some(e => ih.pressedKeys[e]);
  60529. let moveLeft = this.keys.LEFT.some(e => ih.pressedKeys[e]);
  60530. let moveRight = this.keys.RIGHT.some(e => ih.pressedKeys[e]);
  60531. let moveUp = this.keys.UP.some(e => ih.pressedKeys[e]);
  60532. let moveDown = this.keys.DOWN.some(e => ih.pressedKeys[e]);
  60533. let px = 0 , py = 0, pz = 0;
  60534. if(moveForward){
  60535. py = 1;
  60536. }else if(moveBackward){
  60537. py = -1;
  60538. }
  60539. if(moveLeft){
  60540. px = -1;
  60541. }else if(moveRight){
  60542. px = 1;
  60543. }
  60544. if(moveUp){
  60545. pz = 1;
  60546. }else if(moveDown){
  60547. pz = -1;
  60548. }
  60549. (px!=0 || py!=0 || pz!=0) && view.translate(px, py, pz, true);
  60550. }
  60551. { // apply rotation
  60552. let progression = Math.min(1, this.fadeFactor * delta);
  60553. let yaw = view.yaw;
  60554. let pitch = view.pitch;
  60555. let pivot = view.getPivot();
  60556. yaw -= progression * this.yawDelta;
  60557. pitch -= progression * this.pitchDelta;
  60558. view.yaw = yaw;
  60559. view.pitch = pitch;
  60560. let V = this.currentViewport.view.direction.multiplyScalar(-view.radius);
  60561. let position = new Vector3().addVectors(pivot, V);
  60562. view.position.copy(position);
  60563. }
  60564. if(camera.type != 'OrthographicCamera'){ // apply pan
  60565. /* let progression = Math.min(1, this.fadeFactor * delta);
  60566. let panDistance = progression * view.radius * 3; */
  60567. let panDistance = 2 * view.radius * Math.tan(MathUtils$1.degToRad(camera.fov / 2));//参照4dkk。 平移target(也就是平移镜头位置),但还是难以保证跟手(navvis也不一定跟手,但是很奇怪在居中时中心点居然是跟手的,可能计算方式不同)
  60568. //计算了下确实是这么算的。 平移pivot。
  60569. let px = -this.panDelta.x * panDistance;
  60570. let py = this.panDelta.y * panDistance;
  60571. view.pan(px, py);
  60572. }
  60573. { // apply zoom
  60574. let progression = 1;//Math.min(1, this.fadeFactor * delta);
  60575. // let radius = view.radius + progression * this.radiusDelta * view.radius * 0.1;
  60576. let radius = view.radius + progression * this.radiusDelta;
  60577. let V = view.direction.multiplyScalar(-radius);
  60578. let position = new Vector3().addVectors(view.getPivot(), V);
  60579. if(this.constantlyForward) {// 到达中心点后还能继续向前移动,也就是能推进中心点
  60580. if(radius < minRadius){
  60581. radius = minRadius;
  60582. }
  60583. }
  60584. view.radius = radius;
  60585. view.position.copy(position);
  60586. }
  60587. {
  60588. let speed = view.radius;
  60589. this.viewer.setMoveSpeed && this.viewer.setMoveSpeed(speed);
  60590. }
  60591. { // decelerate over time
  60592. /* let progression = Math.min(1, this.fadeFactor * delta);
  60593. let attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  60594. this.yawDelta *= attenuation;
  60595. this.pitchDelta *= attenuation;
  60596. this.panDelta.multiplyScalar(attenuation);
  60597. // this.radiusDelta *= attenuation;
  60598. this.radiusDelta -= progression * this.radiusDelta; */
  60599. //取消衰减,直接stop
  60600. this.stop();
  60601. }
  60602. }
  60603. };
  60604. const Colors = {
  60605. black : '#161A1A',
  60606. blue: '#3290ff',
  60607. gray: '#878585' ,
  60608. white:'#ffffff'
  60609. };
  60610. let navCubeViewer;
  60611. class base{
  60612. constructor(){
  60613. this.faceDefaultColor = Colors.black;//14936556,
  60614. this.wireframeDefaultColor = 13421772,
  60615. this.faceHighlightColor = 12255212,
  60616. this.wireframeHighlightColor = 3330982;
  60617. }
  60618. createMesh(e) {
  60619. for (var t = new BufferGeometry, i = e.length - 2, n = new Uint32Array(3 * i), o = 0, s = 1; s <= i; s++)
  60620. n[o++] = 0,
  60621. n[o++] = s,
  60622. n[o++] = s + 1;
  60623. var r = new MeshBasicMaterial({
  60624. color: this.faceDefaultColor,
  60625. side: DoubleSide
  60626. })
  60627. , a = new Float32Array(3 * e.length);
  60628. t.setAttribute("position", new BufferAttribute(a,3).copyVector3sArray(e)),
  60629. t.setIndex(new BufferAttribute(n,1));
  60630. var l = new Mesh(t,r);
  60631. return l.componentId = this.componentId,
  60632. l
  60633. }
  60634. createWireframe(e ) {
  60635. let line = LineDraw.createFatLine(e,{
  60636. color: Colors.white ,
  60637. lineWidth : 2,
  60638. viewer: navCubeViewer,
  60639. depthTest:true, depthWrite:true,
  60640. transparent:true
  60641. });
  60642. line.renderOrder = 3;
  60643. return line
  60644. }
  60645. getMesh() {
  60646. return this.mesh
  60647. }
  60648. getWireframe() {
  60649. return this.wireframeMesh
  60650. }
  60651. transparent(e) {
  60652. e.material && (e.material.transparent = !0,
  60653. e.material.opacity = 0);
  60654. }
  60655. opaque(e) {
  60656. e.material && (e.material.transparent = !1,
  60657. e.material.opacity = 1);
  60658. }
  60659. getId() {
  60660. return this.componentId
  60661. }
  60662. }
  60663. /*
  60664. class Edge extends base{
  60665. constructor(t, i, n) {
  60666. super()
  60667. this.highlightWidth = 3,
  60668. this.width = 15,
  60669. this.vertices = t,
  60670. this.indices = i,
  60671. this.componentId = n,
  60672. this.highlightWireframeMesh = null,
  60673. this.testWireframe = null,
  60674. this.build()
  60675. }
  60676. build() {
  60677. var e = this.indices[0]
  60678. , t = this.indices[1]
  60679. , i = this.vertices[e]
  60680. , n = this.vertices[t]
  60681. , o = i.clone().add(n).multiplyScalar(.5).clone().multiplyScalar(-1)
  60682. , s = o.clone().normalize()
  60683. , r = []
  60684. , a = n.clone().sub(i).normalize()
  60685. , l = i.clone().add(a.clone().multiplyScalar(20))
  60686. , h = i.clone().add(a.clone().multiplyScalar(80))
  60687. , c = [];
  60688. if (0 !== o.x) {
  60689. var d = o.x > 0 ? this.width : -this.width;
  60690. c.push((new THREE.Vector3).setX(d).add(s))
  60691. }
  60692. if (0 !== o.y) {
  60693. var u = o.y > 0 ? this.width : -this.width;
  60694. c.push((new THREE.Vector3).setY(u).add(s))
  60695. }
  60696. if (0 !== o.z) {
  60697. var g = o.z > 0 ? this.width : -this.width;
  60698. c.push((new THREE.Vector3).setZ(g).add(s))
  60699. }
  60700. 2 === c.length && (r.push(l.clone().add(s)),
  60701. r.push(l.clone().add(c[0])),
  60702. r.push(h.clone().add(c[0])),
  60703. r.push(h.clone().add(s)),
  60704. r.push(h.clone().add(c[1])),
  60705. r.push(l.clone().add(c[1]))),
  60706. this.mesh = this.createMesh(r)
  60707. this.transparent(this.mesh)
  60708. //this.wireframeMesh = this.createWireframe([l, h]),
  60709. //this.highlightWireframeMesh = this.createHighlightWireframe([l.sub(s), h.sub(s)])
  60710. }
  60711. createHighlightWireframe(e) {
  60712. for (var t = [], i = 0; i < e.length; i++) {
  60713. var n = e[i];
  60714. t.push(n.x, n.y, n.z)
  60715. }
  60716. var o = new THREE.LineGeometry;
  60717. o.setPositions(t);
  60718. var s = new THREE.LineMaterial({
  60719. color: this.wireframeHighlightColor,
  60720. linewidth: this.highlightWidth,
  60721. dashed: !1
  60722. });
  60723. s.resolution.set(160, 160);
  60724. var r = new THREE.Line2(o,s);
  60725. return r.computeLineDistances(),
  60726. r.scale.set(1, 1, 1),
  60727. r.visible = !1,
  60728. r.renderOrder = 100,
  60729. r
  60730. }
  60731. getTestWireframe() {
  60732. return this.testWireframe
  60733. }
  60734. getHighlightWireframeMesh() {
  60735. return this.highlightWireframeMesh
  60736. }
  60737. highlight() {
  60738. this.highlightWireframeMesh.visible = !0,
  60739. this.highlightWireframeMesh.renderOrder = 100
  60740. }
  60741. cancelHighlight() {
  60742. this.highlightWireframeMesh.visible = !1
  60743. }
  60744. }
  60745. */
  60746. class Corner extends base{
  60747. constructor(t, i) {
  60748. super();
  60749. this.length = 20,
  60750. this.vertex = t,
  60751. this.cornerFace = null,
  60752. this.cornerWireframe = null,
  60753. this.componentId = i,
  60754. this.cornerVertices = null,
  60755. this.build();
  60756. }
  60757. build() {
  60758. var e = []
  60759. , t = this.vertex.clone()
  60760. , i = t.clone().multiplyScalar(-1);
  60761. e.push(t);
  60762. var n = this.vertex.clone()
  60763. , o = i.x > 0 ? this.length : -this.length;
  60764. n.x += o,
  60765. e.push(n);
  60766. var s = this.vertex.clone()
  60767. , r = i.y > 0 ? this.length : -this.length;
  60768. s.y += r,
  60769. e.push(s);
  60770. var a = this.vertex.clone()
  60771. , l = i.z > 0 ? this.length : -this.length;
  60772. a.z += l,
  60773. e.push(a),
  60774. this.cornerVertices = e;
  60775. this.mesh = this.createMesh([n, s, a]);
  60776. /* this.wireframeMesh = this.createWireframe([n, s, a, n], 2),
  60777. this.buildCornerFace()
  60778. this.buildCornerWireframe() */
  60779. }
  60780. /* highlight() {
  60781. this.wireframeMesh.material.color.setHex(this.wireframeHighlightColor),
  60782. this.wireframeMesh.renderOrder = 100,
  60783. this.mesh.material.color.setHex(this.faceHighlightColor),
  60784. this.cornerFace.material.color.setHex(this.faceHighlightColor),
  60785. this.cornerFace.material.transparent = !0,
  60786. this.cornerFace.material.opacity = .5,
  60787. this.cornerWireframe.material.color.setHex(this.wireframeHighlightColor),
  60788. this.cornerWireframe.visible = !0
  60789. }
  60790. cancelHighlight() {
  60791. this.wireframeMesh.material.color.setHex(this.wireframeDefaultColor),
  60792. this.wireframeMesh.renderOrder = 0,
  60793. this.mesh.material.color.setHex(this.faceDefaultColor),
  60794. this.transparent(this.cornerFace),
  60795. this.cornerWireframe.visible = !1
  60796. }
  60797. buildCornerFace() {
  60798. if (!this.cornerFace) {
  60799. var e = this.cornerVertices;
  60800. e.push(e[1])
  60801. this.cornerFace = this.createMesh(e)
  60802. this.transparent(this.cornerFace)
  60803. }
  60804. }
  60805. getCornerFace() {
  60806. return this.cornerFace
  60807. }
  60808. getCornerWireframe() {
  60809. return this.cornerWireframe
  60810. }
  60811. buildCornerWireframe() {
  60812. if (!this.cornerWireframe) {
  60813. for (var e = [], t = 1; t < this.cornerVertices.length; t++) {
  60814. var i = this.cornerVertices[0]
  60815. , n = this.cornerVertices[t];
  60816. e.push(i, n)
  60817. }
  60818. this.cornerWireframe = this.createWireframe(e),
  60819. this.cornerWireframe.visible = !1
  60820. }
  60821. }
  60822. */
  60823. }
  60824. class Face extends base{
  60825. constructor(t, i, n, o){
  60826. super();
  60827. this.length = 60;
  60828. this.vertices = t,
  60829. this.indices = i,
  60830. this.componentId = n,
  60831. this.vertexUvs = null,
  60832. this.texture = o,
  60833. this.highlightMesh = null,
  60834. this.wireframeMesh = null,
  60835. this.vertexUvs = [],
  60836. this.vertexUvs.push(new Vector2(0,.2)),
  60837. this.vertexUvs.push(new Vector2(0,.8)),
  60838. this.vertexUvs.push(new Vector2(.2,1)),
  60839. this.vertexUvs.push(new Vector2(.8,1)),
  60840. this.vertexUvs.push(new Vector2(1,.8)),
  60841. this.vertexUvs.push(new Vector2(1,.2)),
  60842. this.vertexUvs.push(new Vector2(.8,0)),
  60843. this.vertexUvs.push(new Vector2(.2,0)),
  60844. this.build();
  60845. }
  60846. build() {
  60847. for (var e = [], t = null, i = null, n = 0, o = this.indices.length; n < o; n++) {
  60848. var s = this.indices[n]
  60849. , r = this.indices[n + 1];
  60850. t = this.vertices[s],
  60851. i = this.vertices[r],
  60852. n === o - 1 && (i = this.vertices[this.indices[0]]);
  60853. var a = i.clone().sub(t).normalize()
  60854. , l = t.clone().add(i).multiplyScalar(.5);
  60855. e.push(l.clone().sub(a.clone().multiplyScalar(this.length / 2))),
  60856. e.push(l.clone().add(a.clone().multiplyScalar(this.length / 2)));
  60857. }
  60858. this.createTexturedMesh(e);
  60859. for (var h = new Box3, c = 0; c < this.indices.length; c++) {
  60860. var d = this.indices[c];
  60861. h.expandByPoint(this.vertices[d]);
  60862. }
  60863. for (var u = h.getCenter(new Vector3).normalize(), g = [], p = 0; p < e.length; p++) {
  60864. var m = e[p];
  60865. g.push(m.clone().add(u));
  60866. }
  60867. /* this.highlightMesh = this.createMesh(g)
  60868. this.highlightMesh.visible = !1
  60869. this.highlightMesh.isHighlightMesh = !0 */
  60870. g.push(g[0]);
  60871. this.wireframeMesh = this.createWireframe(g, 1);
  60872. }
  60873. /* highlight() {
  60874. this.highlightMesh.visible = !0
  60875. this.highlightMesh.material.color.setHex(this.faceHighlightColor)
  60876. this.highlightMesh.material.transparent = !0
  60877. this.highlightMesh.material.opacity = .5
  60878. //this.wireframeMesh.material.color.setHex(this.wireframeHighlightColor)
  60879. }
  60880. cancelHighlight() {
  60881. this.highlightMesh.visible = !1
  60882. //this.wireframeMesh.material.color.setHex(this.wireframeDefaultColor)
  60883. } */
  60884. createTexturedMesh(e) {
  60885. for (var t = e.length - 2, i = new Uint32Array(3 * t), n = 0, o = 1; o <= t; o++)
  60886. i[n++] = 0,
  60887. i[n++] = o,
  60888. i[n++] = o + 1;
  60889. var s = new BufferGeometry
  60890. , r = new Float32Array(3 * e.length)
  60891. , a = new Float32Array(2 * this.vertexUvs.length);
  60892. s.setAttribute("position", new BufferAttribute(r,3).copyVector3sArray(e)),
  60893. s.setAttribute("uv", new BufferAttribute(a,2).copyVector2sArray(this.vertexUvs)),
  60894. s.setIndex(new BufferAttribute(i,1));
  60895. var l = new ShaderMaterial({
  60896. side: DoubleSide,
  60897. transparent: !1,
  60898. uniforms:{
  60899. faceColor: {type:'v3', value: new Color(Colors.black) } ,
  60900. textColor: {type:'v3', value: new Color(Colors.white) } ,
  60901. map: {type: 't', value: this.texture },
  60902. },
  60903. vertexShader:`
  60904. varying vec2 vUv;
  60905. void main() {
  60906. vUv = uv;
  60907. gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  60908. }`,
  60909. fragmentShader:`
  60910. varying vec2 vUv;
  60911. uniform vec3 faceColor;
  60912. uniform vec3 textColor;
  60913. uniform sampler2D map;
  60914. void main() {
  60915. //从图上实测
  60916. const float mapFaceColorR = 0.85; //0.8862745098039215 (取色)
  60917. const float mapTextColotR = 0.66; //0.6431372549019608 (取色)//越高锯齿越强,越低越模糊颜色越灰
  60918. vec4 texColor = texture2D(map, vUv);
  60919. if(texColor.r > mapFaceColorR){
  60920. gl_FragColor = vec4(faceColor, texColor.a);
  60921. }else if(texColor.r<mapTextColotR){
  60922. gl_FragColor = vec4(textColor, texColor.a);
  60923. }else{//抗锯齿 过渡
  60924. float faceRatio = (texColor.r - mapTextColotR) / (mapFaceColorR - mapTextColotR);
  60925. gl_FragColor = vec4( mix(textColor, faceColor, faceRatio), texColor.a);
  60926. }
  60927. }
  60928. `
  60929. });
  60930. this.mesh = new Mesh(s,l),
  60931. this.mesh.componentId = this.componentId;
  60932. }
  60933. /* getHighlightMesh() {
  60934. return this.highlightMesh
  60935. }
  60936. buildVertexUvs(e) {
  60937. var t = []
  60938. , i = (new THREE.Box3).setFromPoints(e)
  60939. , n = i.min
  60940. , o = new THREE.Vector2;
  60941. i.getSize(o);
  60942. for (var s = 0 == o.x ? "x" : 0 == o.y ? "y" : "z", r = 0; r < e.length; r++) {
  60943. var a = e[r]
  60944. , l = (o.x + o.y + o.z) / 2
  60945. , h = a.clone().sub(n).multiplyScalar(1 / l)
  60946. , c = new THREE.Vector2(h.x,h.y);
  60947. "x" == s ? c = new THREE.Vector2(h.y,h.z) : "y" == s && (c = new THREE.Vector2(h.x,h.z)),
  60948. t.push(c)
  60949. }
  60950. return t
  60951. } */
  60952. }
  60953. class NavigationCube{
  60954. constructor(scene, length){
  60955. this.scene = scene;
  60956. this.length = length;
  60957. this.initialize();
  60958. /*this.callback = t
  60959. this.buildEdges() */
  60960. this.buildCorners();
  60961. this.buildFaces();
  60962. }
  60963. initialize(){
  60964. this.enumViewMode = {
  60965. "2673": "Top", //数字是面的faceIndex组合
  60966. "4015": "Bottom",
  60967. "0231": "Front",
  60968. "5764": "Back",
  60969. "1375": "Right",
  60970. "4620": "Left",
  60971. /* 3: "RoofSouthEast",
  60972. 2: "RoofSouthWest",
  60973. 7: "RoofNorthEast",
  60974. 6: "RoofNorthWest",
  60975. 1: "BottomSouthEast",
  60976. 0: "BottomSouthWest",
  60977. 4: "BottomNorthWest",
  60978. 5: "BottomNorthEast",
  60979. 32: "RoofFront",
  60980. 76: "RoofBack",
  60981. 37: "RoofRight",
  60982. 26: "RoofLeft",
  60983. "01": "BottomFront",
  60984. 45: "BottomBack",
  60985. 15: "BottomRight",
  60986. "04": "BottomLeft",
  60987. 13: "SouthEast",
  60988. 20: "SouthWest",
  60989. 57: "NorthEast",
  60990. 64: "NorthWest" */
  60991. };
  60992. this.vertices = [],
  60993. this.vertexIds = [],
  60994. this.edgeIds = [],
  60995. this.edgeIndices = [],
  60996. this.faceIds = [],
  60997. this.faceIndices = [],
  60998. this.componentList = [];
  60999. var e = this.length;
  61000. //立方体八个点
  61001. this.vertices.push(new Vector3(-e / 2,-e / 2,e / 2)),
  61002. this.vertices.push(new Vector3(e / 2,-e / 2,e / 2)),
  61003. this.vertices.push(new Vector3(-e / 2,e / 2,e / 2)),
  61004. this.vertices.push(new Vector3(e / 2,e / 2,e / 2)),
  61005. this.vertices.push(new Vector3(-e / 2,-e / 2,-e / 2)),
  61006. this.vertices.push(new Vector3(e / 2,-e / 2,-e / 2)),
  61007. this.vertices.push(new Vector3(-e / 2,e / 2,-e / 2)),
  61008. this.vertices.push(new Vector3(e / 2,e / 2,-e / 2));
  61009. for (var t = 0; t < 8; t++)
  61010. this.vertexIds.push(t + "");
  61011. //12条边
  61012. /* this.edgeIndices.push([0, 1], [1, 3], [3, 2], [2, 0]),
  61013. this.edgeIndices.push([0, 4], [1, 5], [2, 6], [3, 7]),
  61014. this.edgeIndices.push([4, 5], [5, 7], [7, 6], [6, 4]);
  61015. for (t = 0; t < 12; t++) {
  61016. var i = this.edgeIndices[t];
  61017. this.edgeIds.push(i[0] + "" + i[1])
  61018. } */
  61019. //6个面,每个面2个三角形
  61020. this.faceIndices.push([0, 2, 3, 1]),
  61021. this.faceIndices.push([4, 0, 1, 5]),
  61022. this.faceIndices.push([4, 6, 2, 0]),
  61023. this.faceIndices.push([2, 6, 7, 3]),
  61024. this.faceIndices.push([1, 3, 7, 5]),
  61025. this.faceIndices.push([5, 7, 6, 4]);
  61026. for (t = 0; t < 6; t++) {
  61027. var n = this.faceIndices[t];
  61028. this.faceIds.push(n[0] + "" + n[1] + n[2] + n[3]);
  61029. }
  61030. }
  61031. buildFaces() {
  61032. const directions = {
  61033. Top : {dir: new Vector3(0,0,-1)},
  61034. Bottom : {dir: new Vector3(0,0,1)},
  61035. Left : {dir: new Vector3(1,0,0)},
  61036. Right : {dir: new Vector3(-1,0,0)},
  61037. Front : {dir: new Vector3(0,1,0)},
  61038. Back : {dir: new Vector3(0,-1,0)},
  61039. };
  61040. let view = new ExtendView();
  61041. for(let i in directions){
  61042. view.direction = directions[i].dir;
  61043. directions[i].yaw = view.yaw, directions[i].pitch = view.pitch;
  61044. }
  61045. let texturesLoaded = 0;
  61046. let create = (n)=>{
  61047. let name = this.enumViewMode[this.faceIds[n]];
  61048. var url = Potree.resourcePath+'/textures/navigation/' + name + ".png"
  61049. , r = new TextureLoader;
  61050. r.setCrossOrigin("anonymous");
  61051. r.load(url, (tex)=> {
  61052. var face = new Face(e,t[n], this.faceIds[n], tex);
  61053. this.componentList.push(face);
  61054. let faceMesh = face.getMesh();
  61055. this.scene.add(faceMesh);
  61056. this.scene.add(face.getWireframe()); //每个面是八边形
  61057. /* this.scene.add(face.getHighlightMesh()) */
  61058. //6 == ++texturesLoaded && a.callback && a.callback()
  61059. //不过平板无hover事件
  61060. faceMesh.addEventListener('mouseover', (e)=>{
  61061. if(viewer.mainViewport.view.isFlying())return
  61062. faceMesh.material.uniforms.faceColor.value.set(Colors.blue);
  61063. //console.log('变', name)
  61064. navCubeViewer.dispatchEvent('content_changed');
  61065. });
  61066. faceMesh.addEventListener('mouseleave', (e)=>{
  61067. if(viewer.mainViewport.view.isFlying())return
  61068. faceMesh.material.uniforms.faceColor.value.set(Colors.black);
  61069. //console.log('回', name)
  61070. navCubeViewer.dispatchEvent('content_changed');
  61071. });
  61072. faceMesh.addEventListener('click', (e)=>{
  61073. if(viewer.mainViewport.view.isFlying())return
  61074. let dir = directions[name];
  61075. if(name == 'Top'){
  61076. let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2); //使基准线在俯视图中水平
  61077. let yaw = baseLine ? new Vector2().subVectors(baseLine.points[0], baseLine.points[1]).angle() : 0;
  61078. dir = baseLine ? {dir: new Vector3(0,0,-1),yaw,pitch: -1.5707963267948966} : directions[name];
  61079. }
  61080. navCubeViewer.switchView('ortho', dir, ()=>{
  61081. faceMesh.material.uniforms.faceColor.value.set(Colors.black);
  61082. viewer.dispatchEvent({type:'viewChanged', name });
  61083. });
  61084. faceMesh.material.uniforms.faceColor.value.set(Colors.blue);
  61085. });
  61086. });
  61087. };
  61088. for (var e = this.vertices, t = this.faceIndices, s = 0; s < 6; s++){
  61089. create(s);
  61090. }
  61091. }
  61092. buildCorners() {
  61093. for (var e = this.vertices, t = this.vertexIds, i = 0; i < 8; i++) {
  61094. var n = new Corner(e[i],t[i]);
  61095. this.componentList.push(n);
  61096. this.scene.add(n.getMesh()); //8个三角形
  61097. //this.scene.add(n.getWireframe())
  61098. //this.scene.add(n.getCornerFace())
  61099. //this.scene.add(n.getCornerWireframe())
  61100. }
  61101. }
  61102. /* buildEdges() {
  61103. for (var e = this.vertices, t = this.edgeIndices, i = this.edgeIds, n = 0; n < 12; n++) {
  61104. var o = new Edge(e,t[n],i[n]);
  61105. this.componentList.push(o)
  61106. //this.scene.add(o.getMesh())
  61107. //this.scene.add(o.getWireframe())
  61108. //this.scene.add(o.getHighlightWireframeMesh())
  61109. }
  61110. } */
  61111. getComponent(e) {
  61112. for (var t = 0; t < this.componentList.length; t++) {
  61113. var i = this.componentList[t];
  61114. if (i.getId() == e)
  61115. return i
  61116. }
  61117. return null
  61118. }
  61119. }
  61120. class NavCubeViewer extends ViewerBase{
  61121. constructor(domElement, listenViewport){
  61122. super(domElement, {name:'navCube', antialias:true/* , preserveDrawingBuffer:true */} );
  61123. navCubeViewer = this;
  61124. this.scene = new Scene;
  61125. this.scene.rotation.x = Math.PI/2; //Yup->Zup
  61126. this.listenViewport = listenViewport;
  61127. let w = 200;
  61128. this.camera = new OrthographicCamera(-w/2,w/2,w/2,-w/2 , 1, w*4);
  61129. this.camera.zoom = (domElement.clientWidth || 300) / w * 1.267;//zoom越大视野越小
  61130. this.camera.updateProjectionMatrix();
  61131. this.view = new ExtendView();
  61132. /* this.view.position.set(0,0,0);
  61133. this.view.lookAt(0,0,0) */
  61134. this.viewports = [new Viewport( this.view, this.camera, {
  61135. left:0, bottom:0, width:1, height: 1, name:'navCube'
  61136. }) ];
  61137. this.cube = new NavigationCube(this.scene, w/2 );
  61138. viewer.addEventListener('camera_changed', e => {
  61139. if (e.viewport == listenViewport && (/* e.changeInfo.positionChanged || */e.changeInfo.quaternionChanged)) {
  61140. this.updateCamera();
  61141. }
  61142. });
  61143. this.controls = new OrbitControls(this, this.viewports[0]);
  61144. this.controls.setEnable(true);
  61145. this.controls.setScene(true);
  61146. this.view.radius = this.cube.length * 3;//相机距离
  61147. //事件
  61148. this.inputHandler = new InputHandler(this, this.scene);
  61149. this.inputHandler.name = 'navCube';
  61150. //this.inputHandler.addInputListener(this.controls);
  61151. this.inputHandler.registerInteractiveScene(this.scene);//interactiveScenes
  61152. this.viewports[0].interactiveScenes = this.inputHandler.interactiveScenes;//供viewer的inputHandler使用
  61153. viewer.addEventListener('allLoaded',()=>{
  61154. let viewportProps = [{
  61155. left:0, bottom:0,
  61156. width:1, height:1,
  61157. name : "MainView",
  61158. //axis:["y","z"],
  61159. //direction : new THREE.Vector3(1,0,0),
  61160. active: true,
  61161. //相机位置在x轴负向 右下角屏
  61162. viewContainsPoints:[new Vector3(0,0,0)],
  61163. margin:{x:300, y:250} ,
  61164. } ];
  61165. viewer.splitScreen.splitStart(viewportProps);
  61166. viewer.images360.addEventListener('beginChangeMode',(e)=>{
  61167. if(e.mode == 'showPanos'){
  61168. this.switchView('perspective',{}, ()=>{
  61169. Potree.settings.displayMode = viewer.images360.latestRequestMode;
  61170. });
  61171. }
  61172. });
  61173. //外部传消息,使进入俯视
  61174. this.addEventListener('enterTopView',()=>{
  61175. let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2); //使基准线在俯视图中水平
  61176. let yaw = baseLine ? new Vector2().subVectors(baseLine.points[0], baseLine.points[1]).angle() : 0;
  61177. this.switchView('ortho', {dir: new Vector3(0,0,-1),yaw,pitch: -1.5707963267948966}, ()=>{
  61178. viewer.dispatchEvent({type:'viewChanged', name:'Top' });
  61179. });
  61180. });
  61181. this.addEventListener('leaveTopView',()=>{
  61182. if(this.lastView){
  61183. this.switchView2(this.lastView);
  61184. }
  61185. });
  61186. });
  61187. }
  61188. render(){
  61189. this.renderer.render(this.scene, this.camera);
  61190. }
  61191. update(delta){
  61192. this.updateScreenSize();
  61193. this.controls.update(delta);
  61194. this.view.applyToCamera(this.camera);
  61195. let changed = this.cameraChanged();
  61196. if(changed || this.needRender){
  61197. this.needRender = false;
  61198. this.render();
  61199. this.applyToMainView();
  61200. }
  61201. }
  61202. updateCamera(){
  61203. let view = this.listenViewport.view;
  61204. this.view.quaternion = view.quaternion; //this.view.rotation = view.rotation
  61205. this.view.yaw = view.yaw;
  61206. var dir = view.direction; //相机朝向
  61207. this.view.position.copy(dir.multiplyScalar(this.view.radius).negate()); //相机绕着指南针中心(000)转动
  61208. }
  61209. applyToMainView(){
  61210. let view = this.listenViewport.view;
  61211. view.quaternion = this.view.quaternion;
  61212. }
  61213. pushHomeBtn(){
  61214. this.switchView('perspective');
  61215. }
  61216. switchView(type, {yaw, pitch, dir}={}, done){
  61217. if(viewer.mainViewport.view.isFlying())return
  61218. let view = viewer.mainViewport.view;
  61219. let oldlastPerspect = this.lastPerspectView;
  61220. this.lastView = view.clone();
  61221. if(viewer.mainViewport.camera.type == 'OrthographicCamera'){
  61222. this.lastView.isOrtho = true;
  61223. this.lastView.zoom = viewer.mainViewport.camera.zoom;
  61224. }else {
  61225. this.lastPerspectView = this.lastView;
  61226. }
  61227. if(type == 'ortho'){
  61228. let startCamera, endCamera;
  61229. if(viewer.mainViewport.camera != viewer.scene.cameraO){
  61230. startCamera = viewer.scene.cameraP;
  61231. endCamera = viewer.scene.cameraO;
  61232. viewer.scene.cameraO.position.copy(viewer.mainViewport.camera.position);
  61233. viewer.scene.cameraO.quaternion.copy(viewer.mainViewport.camera.quaternion);
  61234. viewer.mainViewport.camera = viewer.scene.cameraO; //先设置为cameraO, 才能计算top
  61235. viewer.setCameraMode(CameraMode.ORTHOGRAPHIC); //updateScreenSize set cameraO.top
  61236. this.controls.setEnable(false);
  61237. //假设保持到目前中心的视角范围不变
  61238. viewer.splitScreen.setShiftTarget(viewer.mainViewport, viewer.bound.center);
  61239. let dis = new Vector3().subVectors(viewer.mainViewport.shiftTarget, viewer.scene.cameraO.position).length() ; //-nearestPano[0].score
  61240. //根据2d->3d的式子逆求zoom
  61241. let halfHeight = Math.abs(dis) * Math.tan( MathUtils$1.degToRad(viewer.scene.cameraP.fov/2));
  61242. viewer.scene.cameraO.zoom = viewer.scene.cameraO.top / halfHeight;
  61243. viewer.scene.cameraO.updateProjectionMatrix();
  61244. }
  61245. console.log('变成正交');
  61246. viewer.focusOnObject(viewer.bound, 'boundingBox', 1000, {
  61247. endPitch: pitch, endYaw: yaw , dir, startCamera, endCamera
  61248. }).promise.done(()=>{
  61249. let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2);
  61250. baseLine && Potree.Utils.updateVisible(baseLine,'enterOrthoView',true);//基准线仅在正交视图可见
  61251. done && done();
  61252. navCubeViewer.dispatchEvent('content_changed');
  61253. });
  61254. }else {
  61255. if(viewer.mainViewport.camera == viewer.scene.cameraO){
  61256. return this.switchView2(oldlastPerspect, done)
  61257. //viewer.scene.cameraP.position.copy(viewer.mainViewport.camera.position)
  61258. //viewer.scene.cameraP.quaternion.copy(viewer.mainViewport.camera.quaternion)
  61259. viewer.mainViewport.camera = viewer.scene.cameraP;
  61260. viewer.setCameraMode(CameraMode.PERSPECTIVE);
  61261. //假设保持到目前中心的视角范围不变
  61262. viewer.splitScreen.setShiftTarget(viewer.mainViewport, viewer.bound.center);
  61263. let halfHeight = viewer.scene.cameraO.top/viewer.scene.cameraO.zoom;
  61264. let dis = halfHeight / Math.tan( MathUtils$1.degToRad(viewer.scene.cameraP.fov/2));
  61265. let position = new Vector3().copy(viewer.mainViewport.shiftTarget).sub(view.direction.clone().multiplyScalar(dis));
  61266. //view.position.copy(viewer.mainViewport.shiftTarget).sub(view.direction.clone().multiplyScalar(dis));
  61267. this.controls.setEnable(true);
  61268. //viewer.dispatchEvent('leaveTopView')
  61269. console.log('变回透视');
  61270. view.tranCamera(viewer.mainViewport, { position ,
  61271. callback:()=>{
  61272. done && done();
  61273. viewer.dispatchEvent({type:'viewChanged', name:'perspective' });
  61274. }, startCamera:viewer.scene.cameraO, endCamera:viewer.scene.cameraP, midCamera:viewer.scene.cameraBasic
  61275. }, 500);
  61276. }
  61277. }
  61278. }
  61279. switchView2(viewInfo, done){ //直接输入view改变
  61280. let view = viewer.mainViewport.view;
  61281. let startCamera, endCamera;
  61282. if(viewInfo.isOrtho){
  61283. if(viewer.mainViewport.camera != viewer.scene.cameraO){
  61284. startCamera = viewer.scene.cameraP;
  61285. endCamera = viewer.scene.cameraO;
  61286. }else {
  61287. view.moveOrthoCamera(viewer.mainViewport, {endPosition:viewInfo.position,
  61288. endPitch: viewInfo.pitch, endYaw: viewInfo.yaw , zoom: viewInfo.zoom,
  61289. callback:()=>{
  61290. done && done();
  61291. },
  61292. }, 800);
  61293. }
  61294. }else {
  61295. if(viewer.mainViewport.camera == viewer.scene.cameraO){
  61296. startCamera = viewer.scene.cameraO;
  61297. endCamera = viewer.scene.cameraP;
  61298. let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2);
  61299. baseLine && Potree.Utils.updateVisible(baseLine,'enterOrthoView',false); //基准线仅在正交视图可见
  61300. }else {
  61301. console.log('switchView2', 'not ortho');
  61302. view.setView({ position:viewInfo.position,
  61303. endPitch: viewInfo.pitch, endYaw: viewInfo.yaw ,
  61304. startCamera, endCamera,
  61305. callback:()=>{
  61306. },
  61307. }, 800);
  61308. }
  61309. }
  61310. if(startCamera){
  61311. if(endCamera == viewer.scene.cameraO){
  61312. this.controls.setEnable(false);
  61313. }
  61314. this.controls.setEnable(false);
  61315. view.tranCamera(viewer.mainViewport, { position:viewInfo.position,
  61316. endPitch: viewInfo.pitch, endYaw: viewInfo.yaw ,
  61317. startCamera, endCamera, midCamera:viewer.scene.cameraBasic ,
  61318. callback:()=>{
  61319. if(endCamera != viewer.scene.cameraO){
  61320. this.controls.setEnable(true);
  61321. viewer.dispatchEvent({type:'viewChanged', name:'perspective' });
  61322. }else {
  61323. viewer.dispatchEvent({type:'viewChanged', name:'perspective' });
  61324. }
  61325. done && done();
  61326. },
  61327. }, 800);
  61328. }
  61329. }
  61330. rotateSideCamera(angle){
  61331. viewer.splitScreen.rotateSideCamera(viewer.mainViewport,angle);
  61332. }
  61333. }
  61334. /**
  61335. *
  61336. * @author sigeom sa / http://sigeom.ch
  61337. * @author Ioda-Net Sàrl / https://www.ioda-net.ch/
  61338. * @author Markus Schütz / http://potree.org
  61339. *
  61340. */
  61341. class GeoJSONExporter{
  61342. static measurementToFeatures (measurement) {
  61343. let coords = measurement.points.map(e => e.position.toArray());
  61344. let features = [];
  61345. if (coords.length === 1) {
  61346. let feature = {
  61347. type: 'Feature',
  61348. geometry: {
  61349. type: 'Point',
  61350. coordinates: coords[0]
  61351. },
  61352. properties: {
  61353. name: measurement.name
  61354. }
  61355. };
  61356. features.push(feature);
  61357. } else if (coords.length > 1 && !measurement.closed) {
  61358. let object = {
  61359. 'type': 'Feature',
  61360. 'geometry': {
  61361. 'type': 'LineString',
  61362. 'coordinates': coords
  61363. },
  61364. 'properties': {
  61365. name: measurement.name
  61366. }
  61367. };
  61368. features.push(object);
  61369. } else if (coords.length > 1 && measurement.closed) {
  61370. let object = {
  61371. 'type': 'Feature',
  61372. 'geometry': {
  61373. 'type': 'Polygon',
  61374. 'coordinates': [[...coords, coords[0]]]
  61375. },
  61376. 'properties': {
  61377. name: measurement.name
  61378. }
  61379. };
  61380. features.push(object);
  61381. }
  61382. if (measurement.showDistances) {
  61383. measurement.edgeLabels.forEach((label) => {
  61384. let labelPoint = {
  61385. type: 'Feature',
  61386. geometry: {
  61387. type: 'Point',
  61388. coordinates: label.position.toArray()
  61389. },
  61390. properties: {
  61391. distance: label.text
  61392. }
  61393. };
  61394. features.push(labelPoint);
  61395. });
  61396. }
  61397. if (measurement.showArea) {
  61398. let point = measurement.areaLabel.position;
  61399. let labelArea = {
  61400. type: 'Feature',
  61401. geometry: {
  61402. type: 'Point',
  61403. coordinates: point.toArray()
  61404. },
  61405. properties: {
  61406. area: measurement.areaLabel.text
  61407. }
  61408. };
  61409. features.push(labelArea);
  61410. }
  61411. return features;
  61412. }
  61413. static toString (measurements) {
  61414. if (!(measurements instanceof Array)) {
  61415. measurements = [measurements];
  61416. }
  61417. measurements = measurements.filter(m => m instanceof Measure);
  61418. let features = [];
  61419. for (let measure of measurements) {
  61420. let f = GeoJSONExporter.measurementToFeatures(measure);
  61421. features = features.concat(f);
  61422. }
  61423. let geojson = {
  61424. 'type': 'FeatureCollection',
  61425. 'features': features
  61426. };
  61427. return JSON.stringify(geojson, null, '\t');
  61428. }
  61429. }
  61430. /**
  61431. *
  61432. * @author sigeom sa / http://sigeom.ch
  61433. * @author Ioda-Net Sàrl / https://www.ioda-net.ch/
  61434. * @author Markus Schuetz / http://potree.org
  61435. *
  61436. */
  61437. class DXFExporter {
  61438. static measurementPointSection (measurement) {
  61439. let position = measurement.points[0].position;
  61440. if (!position) {
  61441. return '';
  61442. }
  61443. let dxfSection = `0
  61444. CIRCLE
  61445. 8
  61446. layer_point
  61447. 10
  61448. ${position.x}
  61449. 20
  61450. ${position.y}
  61451. 30
  61452. ${position.z}
  61453. 40
  61454. 1.0
  61455. `;
  61456. return dxfSection;
  61457. }
  61458. static measurementPolylineSection (measurement) {
  61459. // bit code for polygons/polylines:
  61460. // https://www.autodesk.com/techpubs/autocad/acad2000/dxf/polyline_dxf_06.htm
  61461. let geomCode = 8;
  61462. if (measurement.closed) {
  61463. geomCode += 1;
  61464. }
  61465. let dxfSection = `0
  61466. POLYLINE
  61467. 8
  61468. layer_polyline
  61469. 62
  61470. 1
  61471. 66
  61472. 1
  61473. 10
  61474. 0.0
  61475. 20
  61476. 0.0
  61477. 30
  61478. 0.0
  61479. 70
  61480. ${geomCode}
  61481. `;
  61482. let xMax = 0.0;
  61483. let yMax = 0.0;
  61484. let zMax = 0.0;
  61485. for (let point of measurement.points) {
  61486. point = point.position;
  61487. xMax = Math.max(xMax, point.x);
  61488. yMax = Math.max(yMax, point.y);
  61489. zMax = Math.max(zMax, point.z);
  61490. dxfSection += `0
  61491. VERTEX
  61492. 8
  61493. 0
  61494. 10
  61495. ${point.x}
  61496. 20
  61497. ${point.y}
  61498. 30
  61499. ${point.z}
  61500. 70
  61501. 32
  61502. `;
  61503. }
  61504. dxfSection += `0
  61505. SEQEND
  61506. `;
  61507. return dxfSection;
  61508. }
  61509. static measurementSection (measurement) {
  61510. // if(measurement.points.length <= 1){
  61511. // return "";
  61512. // }
  61513. if (measurement.points.length === 0) {
  61514. return '';
  61515. } else if (measurement.points.length === 1) {
  61516. return DXFExporter.measurementPointSection(measurement);
  61517. } else if (measurement.points.length >= 2) {
  61518. return DXFExporter.measurementPolylineSection(measurement);
  61519. }
  61520. }
  61521. static toString(measurements){
  61522. if (!(measurements instanceof Array)) {
  61523. measurements = [measurements];
  61524. }
  61525. measurements = measurements.filter(m => m instanceof Measure);
  61526. let points = measurements.filter(m => (m instanceof Measure))
  61527. .map(m => m.points)
  61528. .reduce((a, v) => a.concat(v))
  61529. .map(p => p.position);
  61530. let min = new Vector3(Infinity, Infinity, Infinity);
  61531. let max = new Vector3(-Infinity, -Infinity, -Infinity);
  61532. for (let point of points) {
  61533. min.min(point);
  61534. max.max(point);
  61535. }
  61536. let dxfHeader = `999
  61537. DXF created from potree
  61538. 0
  61539. SECTION
  61540. 2
  61541. HEADER
  61542. 9
  61543. $ACADVER
  61544. 1
  61545. AC1006
  61546. 9
  61547. $INSBASE
  61548. 10
  61549. 0.0
  61550. 20
  61551. 0.0
  61552. 30
  61553. 0.0
  61554. 9
  61555. $EXTMIN
  61556. 10
  61557. ${min.x}
  61558. 20
  61559. ${min.y}
  61560. 30
  61561. ${min.z}
  61562. 9
  61563. $EXTMAX
  61564. 10
  61565. ${max.x}
  61566. 20
  61567. ${max.y}
  61568. 30
  61569. ${max.z}
  61570. 0
  61571. ENDSEC
  61572. `;
  61573. let dxfBody = `0
  61574. SECTION
  61575. 2
  61576. ENTITIES
  61577. `;
  61578. for (let measurement of measurements) {
  61579. dxfBody += DXFExporter.measurementSection(measurement);
  61580. }
  61581. dxfBody += `0
  61582. ENDSEC
  61583. `;
  61584. let dxf = dxfHeader + dxfBody + '0\nEOF';
  61585. return dxf;
  61586. }
  61587. }
  61588. class MeasurePanel{
  61589. constructor(viewer, measurement, propertiesPanel){
  61590. this.viewer = viewer;
  61591. this.measurement = measurement;
  61592. this.propertiesPanel = propertiesPanel;
  61593. this._update = () => { this.update(); };
  61594. }
  61595. createCoordinatesTable(points){
  61596. let table = $(`
  61597. <table class="measurement_value_table">
  61598. <tr>
  61599. <th>x</th>
  61600. <th>y</th>
  61601. <th>z</th>
  61602. <th></th>
  61603. </tr>
  61604. </table>
  61605. `);
  61606. let copyIconPath = Potree.resourcePath + '/icons/copy.svg';
  61607. for (let point of points) {
  61608. let x = Utils.addCommas(point.x.toFixed(3));
  61609. let y = Utils.addCommas(point.y.toFixed(3));
  61610. let z = Utils.addCommas(point.z.toFixed(3));
  61611. let row = $(`
  61612. <tr>
  61613. <td><span>${x}</span></td>
  61614. <td><span>${y}</span></td>
  61615. <td><span>${z}</span></td>
  61616. <td align="right" style="width: 25%">
  61617. <img name="copy" title="copy" class="button-icon" src="${copyIconPath}" style="width: 16px; height: 16px"/>
  61618. </td>
  61619. </tr>
  61620. `);
  61621. this.elCopy = row.find("img[name=copy]");
  61622. this.elCopy.click( () => {
  61623. let msg = point.toArray().map(c => c.toFixed(3)).join(", ");
  61624. Utils.clipboardCopy(msg);
  61625. this.viewer.postMessage(
  61626. `Copied value to clipboard: <br>'${msg}'`,
  61627. {duration: 3000});
  61628. });
  61629. table.append(row);
  61630. }
  61631. return table;
  61632. };
  61633. createAttributesTable(){
  61634. let elTable = $('<table class="measurement_value_table"></table>');
  61635. let point = this.measurement.points[0];
  61636. /* for(let attributeName of Object.keys(point)){
  61637. if(attributeName === "position"){
  61638. }else if(attributeName === "rgba"){
  61639. let color = point.rgba;
  61640. let text = color.join(', ');
  61641. elTable.append($(`
  61642. <tr>
  61643. <td>rgb</td>
  61644. <td>${text}</td>
  61645. </tr>
  61646. `));
  61647. }else{
  61648. let value = point[attributeName];
  61649. let text = value.join(', ');
  61650. elTable.append($(`
  61651. <tr>
  61652. <td>${attributeName}</td>
  61653. <td>${text}</td>
  61654. </tr>
  61655. `));
  61656. }
  61657. } */
  61658. return elTable;
  61659. }
  61660. update(){
  61661. }
  61662. };
  61663. class DistancePanel extends MeasurePanel{
  61664. constructor(viewer, measurement, propertiesPanel){
  61665. super(viewer, measurement, propertiesPanel);
  61666. let removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61667. this.elContent = $(`
  61668. <div class="measurement_content selectable">
  61669. <span class="coordinates_table_container"></span>
  61670. <br>
  61671. <table id="distances_table" class="measurement_value_table"></table>
  61672. <!-- ACTIONS -->
  61673. <div style="display: flex; margin-top: 12px">
  61674. <span>
  61675. <input type="button" name="make_profile" value="profile from measure" />
  61676. </span>
  61677. <span style="flex-grow: 1"></span>
  61678. <img name="remove" class="button-icon" src="${removeIconPath}" style="width: 16px; height: 16px"/>
  61679. </div>
  61680. </div>
  61681. `);
  61682. this.elRemove = this.elContent.find("img[name=remove]");
  61683. this.elRemove.click( () => {
  61684. this.viewer.scene.removeMeasurement(measurement);
  61685. });
  61686. this.elMakeProfile = this.elContent.find("input[name=make_profile]");
  61687. this.elMakeProfile.click( () => {
  61688. //measurement.points;
  61689. const profile = new Profile();
  61690. profile.name = measurement.name;
  61691. profile.width = measurement.getTotalDistance() / 50;
  61692. for(const point of measurement.points){
  61693. profile.addMarker(point.position.clone());
  61694. }
  61695. this.viewer.scene.addProfile(profile);
  61696. });
  61697. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61698. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61699. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61700. this.update();
  61701. }
  61702. update(){
  61703. let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61704. elCoordiantesContainer.empty();
  61705. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
  61706. let positions = this.measurement.points.map(p => p.position);
  61707. let distances = [];
  61708. for (let i = 0; i < positions.length - 1; i++) {
  61709. let d = positions[i].distanceTo(positions[i + 1]);
  61710. distances.push(d.toFixed(3));
  61711. }
  61712. let totalDistance = this.measurement.getTotalDistance().toFixed(3);
  61713. let elDistanceTable = this.elContent.find(`#distances_table`);
  61714. elDistanceTable.empty();
  61715. for (let i = 0; i < distances.length; i++) {
  61716. let label = (i === 0) ? 'Distances: ' : '';
  61717. let distance = distances[i];
  61718. let elDistance = $(`
  61719. <tr>
  61720. <th>${label}</th>
  61721. <td style="width: 100%; padding-left: 10px">${distance}</td>
  61722. </tr>`);
  61723. elDistanceTable.append(elDistance);
  61724. }
  61725. let elTotal = $(`
  61726. <tr>
  61727. <th>Total: </td><td style="width: 100%; padding-left: 10px">${totalDistance}</th>
  61728. </tr>`);
  61729. elDistanceTable.append(elTotal);
  61730. }
  61731. };
  61732. class PointPanel extends MeasurePanel{
  61733. constructor(viewer, measurement, propertiesPanel){
  61734. super(viewer, measurement, propertiesPanel);
  61735. let removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61736. this.elContent = $(`
  61737. <div class="measurement_content selectable">
  61738. <span class="coordinates_table_container"></span>
  61739. <br>
  61740. <span class="attributes_table_container"></span>
  61741. <!-- ACTIONS -->
  61742. <div style="display: flex; margin-top: 12px">
  61743. <span></span>
  61744. <span style="flex-grow: 1"></span>
  61745. <img name="remove" class="button-icon" src="${removeIconPath}" style="width: 16px; height: 16px"/>
  61746. </div>
  61747. </div>
  61748. `);
  61749. this.elRemove = this.elContent.find("img[name=remove]");
  61750. this.elRemove.click( () => {
  61751. this.viewer.scene.removeMeasurement(measurement);
  61752. });
  61753. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61754. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61755. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61756. this.update();
  61757. }
  61758. update(){
  61759. let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61760. elCoordiantesContainer.empty();
  61761. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
  61762. let elAttributesContainer = this.elContent.find('.attributes_table_container');
  61763. elAttributesContainer.empty();
  61764. elAttributesContainer.append(this.createAttributesTable());
  61765. }
  61766. };
  61767. class AreaPanel extends MeasurePanel{
  61768. constructor(viewer, measurement, propertiesPanel){
  61769. super(viewer, measurement, propertiesPanel);
  61770. let removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61771. this.elContent = $(`
  61772. <div class="measurement_content selectable">
  61773. <span class="coordinates_table_container"></span>
  61774. <br>
  61775. <span style="font-weight: bold">Area: </span>
  61776. <span id="measurement_area"></span>
  61777. <!-- ACTIONS -->
  61778. <div style="display: flex; margin-top: 12px">
  61779. <span></span>
  61780. <span style="flex-grow: 1"></span>
  61781. <img name="remove" class="button-icon" src="${removeIconPath}" style="width: 16px; height: 16px"/>
  61782. </div>
  61783. </div>
  61784. `);
  61785. this.elRemove = this.elContent.find("img[name=remove]");
  61786. this.elRemove.click( () => {
  61787. this.viewer.scene.removeMeasurement(measurement);
  61788. });
  61789. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61790. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61791. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61792. this.update();
  61793. }
  61794. update(){
  61795. let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61796. elCoordiantesContainer.empty();
  61797. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
  61798. let elArea = this.elContent.find(`#measurement_area`);
  61799. elArea.html(this.measurement.area.value.toFixed(3));
  61800. }
  61801. };
  61802. class AnglePanel extends MeasurePanel{
  61803. constructor(viewer, measurement, propertiesPanel){
  61804. super(viewer, measurement, propertiesPanel);
  61805. let removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61806. this.elContent = $(`
  61807. <div class="measurement_content selectable">
  61808. <span class="coordinates_table_container"></span>
  61809. <br>
  61810. <table class="measurement_value_table">
  61811. <tr>
  61812. <th>\u03b1</th>
  61813. <th>\u03b2</th>
  61814. <th>\u03b3</th>
  61815. </tr>
  61816. <tr>
  61817. <td align="center" id="angle_cell_alpha" style="width: 33%"></td>
  61818. <td align="center" id="angle_cell_betta" style="width: 33%"></td>
  61819. <td align="center" id="angle_cell_gamma" style="width: 33%"></td>
  61820. </tr>
  61821. </table>
  61822. <!-- ACTIONS -->
  61823. <div style="display: flex; margin-top: 12px">
  61824. <span></span>
  61825. <span style="flex-grow: 1"></span>
  61826. <img name="remove" class="button-icon" src="${removeIconPath}" style="width: 16px; height: 16px"/>
  61827. </div>
  61828. </div>
  61829. `);
  61830. this.elRemove = this.elContent.find("img[name=remove]");
  61831. this.elRemove.click( () => {
  61832. this.viewer.scene.removeMeasurement(measurement);
  61833. });
  61834. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61835. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61836. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61837. this.update();
  61838. }
  61839. update(){
  61840. let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61841. elCoordiantesContainer.empty();
  61842. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
  61843. let angles = [];
  61844. for(let i = 0; i < this.measurement.points.length; i++){
  61845. angles.push(this.measurement.getAngle(i) * (180.0 / Math.PI));
  61846. }
  61847. angles = angles.map(a => a.toFixed(1) + '\u00B0');
  61848. let elAlpha = this.elContent.find(`#angle_cell_alpha`);
  61849. let elBetta = this.elContent.find(`#angle_cell_betta`);
  61850. let elGamma = this.elContent.find(`#angle_cell_gamma`);
  61851. elAlpha.html(angles[0]);
  61852. elBetta.html(angles[1]);
  61853. elGamma.html(angles[2]);
  61854. }
  61855. };
  61856. class CirclePanel extends MeasurePanel{
  61857. constructor(viewer, measurement, propertiesPanel){
  61858. super(viewer, measurement, propertiesPanel);
  61859. let removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61860. this.elContent = $(`
  61861. <div class="measurement_content selectable">
  61862. <span class="coordinates_table_container"></span>
  61863. <br>
  61864. <table id="infos_table" class="measurement_value_table"></table>
  61865. <!-- ACTIONS -->
  61866. <div style="display: flex; margin-top: 12px">
  61867. <span></span>
  61868. <span style="flex-grow: 1"></span>
  61869. <img name="remove" class="button-icon" src="${removeIconPath}" style="width: 16px; height: 16px"/>
  61870. </div>
  61871. </div>
  61872. `);
  61873. this.elRemove = this.elContent.find("img[name=remove]");
  61874. this.elRemove.click( () => {
  61875. this.viewer.scene.removeMeasurement(measurement);
  61876. });
  61877. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61878. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61879. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61880. this.update();
  61881. }
  61882. update(){
  61883. let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61884. elCoordiantesContainer.empty();
  61885. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
  61886. const elInfos = this.elContent.find(`#infos_table`);
  61887. if(this.measurement.points.length !== 3){
  61888. elInfos.empty();
  61889. return;
  61890. }
  61891. const A = this.measurement.points[0].position;
  61892. const B = this.measurement.points[1].position;
  61893. const C = this.measurement.points[2].position;
  61894. const center = Potree.Utils.computeCircleCenter(A, B, C);
  61895. const radius = center.distanceTo(A);
  61896. const circumference = 2 * Math.PI * radius;
  61897. const format = (number) => {
  61898. return Potree.Utils.addCommas(number.toFixed(3));
  61899. };
  61900. const txtCenter = `${format(center.x)} ${format(center.y)} ${format(center.z)}`;
  61901. const txtRadius = format(radius);
  61902. const txtCircumference = format(circumference);
  61903. const thStyle = `style="text-align: left"`;
  61904. const tdStyle = `style="width: 100%; padding: 5px;"`;
  61905. elInfos.html(`
  61906. <tr>
  61907. <th ${thStyle}>Center: </th>
  61908. <td ${tdStyle}></td>
  61909. </tr>
  61910. <tr>
  61911. <td ${tdStyle} colspan="2">
  61912. ${txtCenter}
  61913. </td>
  61914. </tr>
  61915. <tr>
  61916. <th ${thStyle}>Radius: </th>
  61917. <td ${tdStyle}>${txtRadius}</td>
  61918. </tr>
  61919. <tr>
  61920. <th ${thStyle}>Circumference: </th>
  61921. <td ${tdStyle}>${txtCircumference}</td>
  61922. </tr>
  61923. `);
  61924. }
  61925. };
  61926. class HeightPanel extends MeasurePanel{
  61927. constructor(viewer, measurement, propertiesPanel){
  61928. super(viewer, measurement, propertiesPanel);
  61929. let removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61930. this.elContent = $(`
  61931. <div class="measurement_content selectable">
  61932. <span class="coordinates_table_container"></span>
  61933. <br>
  61934. <span id="height_label">Height: </span><br>
  61935. <!-- ACTIONS -->
  61936. <div style="display: flex; margin-top: 12px">
  61937. <span></span>
  61938. <span style="flex-grow: 1"></span>
  61939. <img name="remove" class="button-icon" src="${removeIconPath}" style="width: 16px; height: 16px"/>
  61940. </div>
  61941. </div>
  61942. `);
  61943. this.elRemove = this.elContent.find("img[name=remove]");
  61944. this.elRemove.click( () => {
  61945. this.viewer.scene.removeMeasurement(measurement);
  61946. });
  61947. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61948. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61949. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61950. this.update();
  61951. }
  61952. update(){
  61953. let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61954. elCoordiantesContainer.empty();
  61955. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
  61956. {
  61957. let points = this.measurement.points;
  61958. let sorted = points.slice().sort((a, b) => a.position.z - b.position.z);
  61959. let lowPoint = sorted[0].position.clone();
  61960. let highPoint = sorted[sorted.length - 1].position.clone();
  61961. let min = lowPoint.z;
  61962. let max = highPoint.z;
  61963. let height = max - min;
  61964. height = height.toFixed(3);
  61965. this.elHeightLabel = this.elContent.find(`#height_label`);
  61966. this.elHeightLabel.html(`<b>Height:</b> ${height}`);
  61967. }
  61968. }
  61969. };
  61970. class VolumePanel extends MeasurePanel{
  61971. constructor(viewer, measurement, propertiesPanel){
  61972. super(viewer, measurement, propertiesPanel);
  61973. let copyIconPath = Potree.resourcePath + '/icons/copy.svg';
  61974. let removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61975. let lblLengthText = new Map([
  61976. [BoxVolume, "length"],
  61977. [SphereVolume$1, "rx"],
  61978. ]).get(measurement.constructor);
  61979. let lblWidthText = new Map([
  61980. [BoxVolume, "width"],
  61981. [SphereVolume$1, "ry"],
  61982. ]).get(measurement.constructor);
  61983. let lblHeightText = new Map([
  61984. [BoxVolume, "height"],
  61985. [SphereVolume$1, "rz"],
  61986. ]).get(measurement.constructor);
  61987. this.elContent = $(`
  61988. <div class="measurement_content selectable">
  61989. <span class="coordinates_table_container"></span>
  61990. <table class="measurement_value_table">
  61991. <tr>
  61992. <th>\u03b1</th>
  61993. <th>\u03b2</th>
  61994. <th>\u03b3</th>
  61995. <th></th>
  61996. </tr>
  61997. <tr>
  61998. <td align="center" id="angle_cell_alpha" style="width: 33%"></td>
  61999. <td align="center" id="angle_cell_betta" style="width: 33%"></td>
  62000. <td align="center" id="angle_cell_gamma" style="width: 33%"></td>
  62001. <td align="right" style="width: 25%">
  62002. <img name="copyRotation" title="copy" class="button-icon" src="${copyIconPath}" style="width: 16px; height: 16px"/>
  62003. </td>
  62004. </tr>
  62005. </table>
  62006. <table class="measurement_value_table">
  62007. <tr>
  62008. <th>${lblLengthText}</th>
  62009. <th>${lblWidthText}</th>
  62010. <th>${lblHeightText}</th>
  62011. <th></th>
  62012. </tr>
  62013. <tr>
  62014. <td align="center" id="cell_length" style="width: 33%"></td>
  62015. <td align="center" id="cell_width" style="width: 33%"></td>
  62016. <td align="center" id="cell_height" style="width: 33%"></td>
  62017. <td align="right" style="width: 25%">
  62018. <img name="copyScale" title="copy" class="button-icon" src="${copyIconPath}" style="width: 16px; height: 16px"/>
  62019. </td>
  62020. </tr>
  62021. </table>
  62022. <br>
  62023. <span style="font-weight: bold">Volume: </span>
  62024. <span id="measurement_volume"></span>
  62025. <!--
  62026. <li>
  62027. <label style="whitespace: nowrap">
  62028. <input id="volume_show" type="checkbox"/>
  62029. <span>show volume</span>
  62030. </label>
  62031. </li>-->
  62032. <li>
  62033. <label style="whitespace: nowrap">
  62034. <input id="volume_clip" type="checkbox"/>
  62035. <span>make clip volume</span>
  62036. </label>
  62037. </li>
  62038. <li style="margin-top: 10px">
  62039. <input name="download_volume" type="button" value="prepare download" style="width: 100%" />
  62040. <div name="download_message"></div>
  62041. </li>
  62042. <!-- ACTIONS -->
  62043. <li style="display: grid; grid-template-columns: auto auto; grid-column-gap: 5px; margin-top: 10px">
  62044. <input id="volume_reset_orientation" type="button" value="reset orientation"/>
  62045. <input id="volume_make_uniform" type="button" value="make uniform"/>
  62046. </li>
  62047. <div style="display: flex; margin-top: 12px">
  62048. <span></span>
  62049. <span style="flex-grow: 1"></span>
  62050. <img name="remove" class="button-icon" src="${removeIconPath}" style="width: 16px; height: 16px"/>
  62051. </div>
  62052. </div>
  62053. `);
  62054. { // download
  62055. this.elDownloadButton = this.elContent.find("input[name=download_volume]");
  62056. if(this.propertiesPanel.viewer.server){
  62057. this.elDownloadButton.click(() => this.download());
  62058. } else {
  62059. this.elDownloadButton.hide();
  62060. }
  62061. }
  62062. this.elCopyRotation = this.elContent.find("img[name=copyRotation]");
  62063. this.elCopyRotation.click( () => {
  62064. let rotation = this.measurement.rotation.toArray().slice(0, 3);
  62065. let msg = rotation.map(c => c.toFixed(3)).join(", ");
  62066. Utils.clipboardCopy(msg);
  62067. this.viewer.postMessage(
  62068. `Copied value to clipboard: <br>'${msg}'`,
  62069. {duration: 3000});
  62070. });
  62071. this.elCopyScale = this.elContent.find("img[name=copyScale]");
  62072. this.elCopyScale.click( () => {
  62073. let scale = this.measurement.scale.toArray();
  62074. let msg = scale.map(c => c.toFixed(3)).join(", ");
  62075. Utils.clipboardCopy(msg);
  62076. this.viewer.postMessage(
  62077. `Copied value to clipboard: <br>'${msg}'`,
  62078. {duration: 3000});
  62079. });
  62080. this.elRemove = this.elContent.find("img[name=remove]");
  62081. this.elRemove.click( () => {
  62082. this.viewer.scene.removeVolume(measurement);
  62083. });
  62084. this.elContent.find("#volume_reset_orientation").click(() => {
  62085. measurement.rotation.set(0, 0, 0);
  62086. });
  62087. this.elContent.find("#volume_make_uniform").click(() => {
  62088. let mean = (measurement.scale.x + measurement.scale.y + measurement.scale.z) / 3;
  62089. measurement.scale.set(mean, mean, mean);
  62090. });
  62091. this.elCheckClip = this.elContent.find('#volume_clip');
  62092. this.elCheckClip.click(event => {
  62093. this.measurement.clip = event.target.checked;
  62094. });
  62095. this.elCheckShow = this.elContent.find('#volume_show');
  62096. this.elCheckShow.click(event => {
  62097. this.measurement.visible = event.target.checked;
  62098. });
  62099. this.propertiesPanel.addVolatileListener(measurement, "position_changed", this._update);
  62100. this.propertiesPanel.addVolatileListener(measurement, "orientation_changed", this._update);
  62101. this.propertiesPanel.addVolatileListener(measurement, "scale_changed", this._update);
  62102. this.propertiesPanel.addVolatileListener(measurement, "clip_changed", this._update);
  62103. this.update();
  62104. }
  62105. async download(){
  62106. let clipBox = this.measurement;
  62107. let regions = [];
  62108. //for(let clipBox of boxes){
  62109. {
  62110. let toClip = clipBox.matrixWorld;
  62111. let px = new Vector3(+0.5, 0, 0).applyMatrix4(toClip);
  62112. let nx = new Vector3(-0.5, 0, 0).applyMatrix4(toClip);
  62113. let py = new Vector3(0, +0.5, 0).applyMatrix4(toClip);
  62114. let ny = new Vector3(0, -0.5, 0).applyMatrix4(toClip);
  62115. let pz = new Vector3(0, 0, +0.5).applyMatrix4(toClip);
  62116. let nz = new Vector3(0, 0, -0.5).applyMatrix4(toClip);
  62117. let pxN = new Vector3().subVectors(nx, px).normalize();
  62118. let nxN = pxN.clone().multiplyScalar(-1);
  62119. let pyN = new Vector3().subVectors(ny, py).normalize();
  62120. let nyN = pyN.clone().multiplyScalar(-1);
  62121. let pzN = new Vector3().subVectors(nz, pz).normalize();
  62122. let nzN = pzN.clone().multiplyScalar(-1);
  62123. let planes = [
  62124. new Plane().setFromNormalAndCoplanarPoint(pxN, px),
  62125. new Plane().setFromNormalAndCoplanarPoint(nxN, nx),
  62126. new Plane().setFromNormalAndCoplanarPoint(pyN, py),
  62127. new Plane().setFromNormalAndCoplanarPoint(nyN, ny),
  62128. new Plane().setFromNormalAndCoplanarPoint(pzN, pz),
  62129. new Plane().setFromNormalAndCoplanarPoint(nzN, nz),
  62130. ];
  62131. let planeQueryParts = [];
  62132. for(let plane of planes){
  62133. let part = [plane.normal.toArray(), plane.constant].join(",");
  62134. part = `[${part}]`;
  62135. planeQueryParts.push(part);
  62136. }
  62137. let region = "[" + planeQueryParts.join(",") + "]";
  62138. regions.push(region);
  62139. }
  62140. let regionsArg = regions.join(",");
  62141. let pointcloudArgs = [];
  62142. for(let pointcloud of this.viewer.scene.pointclouds){
  62143. if(!pointcloud.visible){
  62144. continue;
  62145. }
  62146. let offset = pointcloud.pcoGeometry.offset.clone();
  62147. let negateOffset = new Matrix4().makeTranslation(...offset.multiplyScalar(-1).toArray());
  62148. let matrixWorld = pointcloud.matrixWorld;
  62149. let transform = new Matrix4().multiplyMatrices(matrixWorld, negateOffset);
  62150. let path = `${window.location.pathname}/../${pointcloud.pcoGeometry.url}`;
  62151. let arg = {
  62152. path: path,
  62153. transform: transform.elements,
  62154. };
  62155. let argString = JSON.stringify(arg);
  62156. pointcloudArgs.push(argString);
  62157. }
  62158. let pointcloudsArg = pointcloudArgs.join(",");
  62159. let elMessage = this.elContent.find("div[name=download_message]");
  62160. let error = (message) => {
  62161. elMessage.html(`<div style="color: #ff0000">ERROR: ${message}</div>`);
  62162. };
  62163. let info = (message) => {
  62164. elMessage.html(`${message}`);
  62165. };
  62166. let handle = null;
  62167. { // START FILTER
  62168. let url = `${viewer.server}/create_regions_filter?pointclouds=[${pointcloudsArg}]&regions=[${regionsArg}]`;
  62169. //console.log(url);
  62170. info("estimating results ...");
  62171. let response = await fetch(url);
  62172. let jsResponse = await response.json();
  62173. //console.log(jsResponse);
  62174. if(!jsResponse.handle){
  62175. error(jsResponse.message);
  62176. return;
  62177. }else {
  62178. handle = jsResponse.handle;
  62179. }
  62180. }
  62181. { // WAIT, CHECK PROGRESS, HANDLE FINISH
  62182. let url = `${viewer.server}/check_regions_filter?handle=${handle}`;
  62183. let sleep = (function(duration){
  62184. return new Promise( (res, rej) => {
  62185. setTimeout(() => {
  62186. res();
  62187. }, duration);
  62188. });
  62189. });
  62190. let handleFiltering = (jsResponse) => {
  62191. let {progress, estimate} = jsResponse;
  62192. let progressFract = progress["processed points"] / estimate.points;
  62193. let progressPercents = parseInt(progressFract * 100);
  62194. info(`progress: ${progressPercents}%`);
  62195. };
  62196. let handleFinish = (jsResponse) => {
  62197. let message = "downloads ready: <br>";
  62198. message += "<ul>";
  62199. for(let i = 0; i < jsResponse.pointclouds.length; i++){
  62200. let url = `${viewer.server}/download_regions_filter_result?handle=${handle}&index=${i}`;
  62201. message += `<li><a href="${url}">result_${i}.las</a> </li>\n`;
  62202. }
  62203. let reportURL = `${viewer.server}/download_regions_filter_report?handle=${handle}`;
  62204. message += `<li> <a href="${reportURL}">report.json</a> </li>\n`;
  62205. message += "</ul>";
  62206. info(message);
  62207. };
  62208. let handleUnexpected = (jsResponse) => {
  62209. let message = `Unexpected Response. <br>status: ${jsResponse.status} <br>message: ${jsResponse.message}`;
  62210. info(message);
  62211. };
  62212. let handleError = (jsResponse) => {
  62213. let message = `ERROR: ${jsResponse.message}`;
  62214. error(message);
  62215. throw new Error(message);
  62216. };
  62217. let start = Date.now();
  62218. while(true){
  62219. let response = await fetch(url);
  62220. let jsResponse = await response.json();
  62221. if(jsResponse.status === "ERROR"){
  62222. handleError(jsResponse);
  62223. }else if(jsResponse.status === "FILTERING"){
  62224. handleFiltering(jsResponse);
  62225. }else if(jsResponse.status === "FINISHED"){
  62226. handleFinish(jsResponse);
  62227. break;
  62228. }else {
  62229. handleUnexpected(jsResponse);
  62230. }
  62231. let durationS = (Date.now() - start) / 1000;
  62232. let sleepAmountMS = durationS < 10 ? 100 : 1000;
  62233. await sleep(sleepAmountMS);
  62234. }
  62235. }
  62236. }
  62237. update(){
  62238. let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  62239. elCoordiantesContainer.empty();
  62240. elCoordiantesContainer.append(this.createCoordinatesTable([this.measurement.position]));
  62241. {
  62242. let angles = this.measurement.rotation.toVector3();
  62243. angles = angles.toArray();
  62244. //angles = [angles.z, angles.x, angles.y];
  62245. angles = angles.map(v => 180 * v / Math.PI);
  62246. angles = angles.map(a => a.toFixed(1) + '\u00B0');
  62247. let elAlpha = this.elContent.find(`#angle_cell_alpha`);
  62248. let elBetta = this.elContent.find(`#angle_cell_betta`);
  62249. let elGamma = this.elContent.find(`#angle_cell_gamma`);
  62250. elAlpha.html(angles[0]);
  62251. elBetta.html(angles[1]);
  62252. elGamma.html(angles[2]);
  62253. }
  62254. {
  62255. let dimensions = this.measurement.scale.toArray();
  62256. dimensions = dimensions.map(v => Utils.addCommas(v.toFixed(2)));
  62257. let elLength = this.elContent.find(`#cell_length`);
  62258. let elWidth = this.elContent.find(`#cell_width`);
  62259. let elHeight = this.elContent.find(`#cell_height`);
  62260. elLength.html(dimensions[0]);
  62261. elWidth.html(dimensions[1]);
  62262. elHeight.html(dimensions[2]);
  62263. }
  62264. {
  62265. let elVolume = this.elContent.find(`#measurement_volume`);
  62266. let volume = this.measurement.getVolume();
  62267. elVolume.html(Utils.addCommas(volume.toFixed(2)));
  62268. }
  62269. this.elCheckClip.prop("checked", this.measurement.clip);
  62270. this.elCheckShow.prop("checked", this.measurement.visible);
  62271. }
  62272. };
  62273. class ProfilePanel extends MeasurePanel{
  62274. constructor(viewer, measurement, propertiesPanel){
  62275. super(viewer, measurement, propertiesPanel);
  62276. let removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  62277. this.elContent = $(`
  62278. <div class="measurement_content selectable">
  62279. <span class="coordinates_table_container"></span>
  62280. <br>
  62281. <span style="display:flex">
  62282. <span style="display:flex; align-items: center; padding-right: 10px">Width: </span>
  62283. <input id="sldProfileWidth" name="sldProfileWidth" value="5.06" style="flex-grow: 1; width:100%">
  62284. </span>
  62285. <br>
  62286. <li style="margin-top: 10px">
  62287. <input name="download_profile" type="button" value="prepare download" style="width: 100%" />
  62288. <div name="download_message"></div>
  62289. </li>
  62290. <br>
  62291. <input type="button" id="show_2d_profile" value="show 2d profile" style="width: 100%"/>
  62292. <!-- ACTIONS -->
  62293. <div style="display: flex; margin-top: 12px">
  62294. <span></span>
  62295. <span style="flex-grow: 1"></span>
  62296. <img name="remove" class="button-icon" src="${removeIconPath}" style="width: 16px; height: 16px"/>
  62297. </div>
  62298. </div>
  62299. `);
  62300. this.elRemove = this.elContent.find("img[name=remove]");
  62301. this.elRemove.click( () => {
  62302. this.viewer.scene.removeProfile(measurement);
  62303. });
  62304. { // download
  62305. this.elDownloadButton = this.elContent.find(`input[name=download_profile]`);
  62306. if(this.propertiesPanel.viewer.server){
  62307. this.elDownloadButton.click(() => this.download());
  62308. } else {
  62309. this.elDownloadButton.hide();
  62310. }
  62311. }
  62312. { // width spinner
  62313. let elWidthSlider = this.elContent.find(`#sldProfileWidth`);
  62314. elWidthSlider.spinner({
  62315. min: 0, max: 10 * 1000 * 1000, step: 0.01,
  62316. numberFormat: 'n',
  62317. start: () => {},
  62318. spin: (event, ui) => {
  62319. let value = elWidthSlider.spinner('value');
  62320. measurement.setWidth(value);
  62321. },
  62322. change: (event, ui) => {
  62323. let value = elWidthSlider.spinner('value');
  62324. measurement.setWidth(value);
  62325. },
  62326. stop: (event, ui) => {
  62327. let value = elWidthSlider.spinner('value');
  62328. measurement.setWidth(value);
  62329. },
  62330. incremental: (count) => {
  62331. let value = elWidthSlider.spinner('value');
  62332. let step = elWidthSlider.spinner('option', 'step');
  62333. let delta = value * 0.05;
  62334. let increments = Math.max(1, parseInt(delta / step));
  62335. return increments;
  62336. }
  62337. });
  62338. elWidthSlider.spinner('value', measurement.getWidth());
  62339. elWidthSlider.spinner('widget').css('width', '100%');
  62340. let widthListener = (event) => {
  62341. let value = elWidthSlider.spinner('value');
  62342. if (value !== measurement.getWidth()) {
  62343. elWidthSlider.spinner('value', measurement.getWidth());
  62344. }
  62345. };
  62346. this.propertiesPanel.addVolatileListener(measurement, "width_changed", widthListener);
  62347. }
  62348. let elShow2DProfile = this.elContent.find(`#show_2d_profile`);
  62349. elShow2DProfile.click(() => {
  62350. this.propertiesPanel.viewer.profileWindow.show();
  62351. this.propertiesPanel.viewer.profileWindowController.setProfile(measurement);
  62352. });
  62353. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  62354. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  62355. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  62356. this.update();
  62357. }
  62358. update(){
  62359. let elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  62360. elCoordiantesContainer.empty();
  62361. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
  62362. }
  62363. async download(){
  62364. let profile = this.measurement;
  62365. let regions = [];
  62366. {
  62367. let segments = profile.getSegments();
  62368. let width = profile.width;
  62369. for(let segment of segments){
  62370. let start = segment.start.clone().multiply(new Vector3(1, 1, 0));
  62371. let end = segment.end.clone().multiply(new Vector3(1, 1, 0));
  62372. let center = new Vector3().addVectors(start, end).multiplyScalar(0.5);
  62373. let startEndDir = new Vector3().subVectors(end, start).normalize();
  62374. let endStartDir = new Vector3().subVectors(start, end).normalize();
  62375. let upDir = new Vector3(0, 0, 1);
  62376. let rightDir = new Vector3().crossVectors(startEndDir, upDir);
  62377. let leftDir = new Vector3().crossVectors(endStartDir, upDir);
  62378. console.log(leftDir);
  62379. let right = rightDir.clone().multiplyScalar(width * 0.5).add(center);
  62380. let left = leftDir.clone().multiplyScalar(width * 0.5).add(center);
  62381. let planes = [
  62382. new Plane().setFromNormalAndCoplanarPoint(startEndDir, start),
  62383. new Plane().setFromNormalAndCoplanarPoint(endStartDir, end),
  62384. new Plane().setFromNormalAndCoplanarPoint(leftDir, right),
  62385. new Plane().setFromNormalAndCoplanarPoint(rightDir, left),
  62386. ];
  62387. let planeQueryParts = [];
  62388. for(let plane of planes){
  62389. let part = [plane.normal.toArray(), plane.constant].join(",");
  62390. part = `[${part}]`;
  62391. planeQueryParts.push(part);
  62392. }
  62393. let region = "[" + planeQueryParts.join(",") + "]";
  62394. regions.push(region);
  62395. }
  62396. }
  62397. let regionsArg = regions.join(",");
  62398. let pointcloudArgs = [];
  62399. for(let pointcloud of this.viewer.scene.pointclouds){
  62400. if(!pointcloud.visible){
  62401. continue;
  62402. }
  62403. let offset = pointcloud.pcoGeometry.offset.clone();
  62404. let negateOffset = new Matrix4().makeTranslation(...offset.multiplyScalar(-1).toArray());
  62405. let matrixWorld = pointcloud.matrixWorld;
  62406. let transform = new Matrix4().multiplyMatrices(matrixWorld, negateOffset);
  62407. let path = `${window.location.pathname}/../${pointcloud.pcoGeometry.url}`;
  62408. let arg = {
  62409. path: path,
  62410. transform: transform.elements,
  62411. };
  62412. let argString = JSON.stringify(arg);
  62413. pointcloudArgs.push(argString);
  62414. }
  62415. let pointcloudsArg = pointcloudArgs.join(",");
  62416. let elMessage = this.elContent.find("div[name=download_message]");
  62417. let error = (message) => {
  62418. elMessage.html(`<div style="color: #ff0000">ERROR: ${message}</div>`);
  62419. };
  62420. let info = (message) => {
  62421. elMessage.html(`${message}`);
  62422. };
  62423. let handle = null;
  62424. { // START FILTER
  62425. let url = `${viewer.server}/create_regions_filter?pointclouds=[${pointcloudsArg}]&regions=[${regionsArg}]`;
  62426. //console.log(url);
  62427. info("estimating results ...");
  62428. let response = await fetch(url);
  62429. let jsResponse = await response.json();
  62430. //console.log(jsResponse);
  62431. if(!jsResponse.handle){
  62432. error(jsResponse.message);
  62433. return;
  62434. }else {
  62435. handle = jsResponse.handle;
  62436. }
  62437. }
  62438. { // WAIT, CHECK PROGRESS, HANDLE FINISH
  62439. let url = `${viewer.server}/check_regions_filter?handle=${handle}`;
  62440. let sleep = (function(duration){
  62441. return new Promise( (res, rej) => {
  62442. setTimeout(() => {
  62443. res();
  62444. }, duration);
  62445. });
  62446. });
  62447. let handleFiltering = (jsResponse) => {
  62448. let {progress, estimate} = jsResponse;
  62449. let progressFract = progress["processed points"] / estimate.points;
  62450. let progressPercents = parseInt(progressFract * 100);
  62451. info(`progress: ${progressPercents}%`);
  62452. };
  62453. let handleFinish = (jsResponse) => {
  62454. let message = "downloads ready: <br>";
  62455. message += "<ul>";
  62456. for(let i = 0; i < jsResponse.pointclouds.length; i++){
  62457. let url = `${viewer.server}/download_regions_filter_result?handle=${handle}&index=${i}`;
  62458. message += `<li><a href="${url}">result_${i}.las</a> </li>\n`;
  62459. }
  62460. let reportURL = `${viewer.server}/download_regions_filter_report?handle=${handle}`;
  62461. message += `<li> <a href="${reportURL}">report.json</a> </li>\n`;
  62462. message += "</ul>";
  62463. info(message);
  62464. };
  62465. let handleUnexpected = (jsResponse) => {
  62466. let message = `Unexpected Response. <br>status: ${jsResponse.status} <br>message: ${jsResponse.message}`;
  62467. info(message);
  62468. };
  62469. let handleError = (jsResponse) => {
  62470. let message = `ERROR: ${jsResponse.message}`;
  62471. error(message);
  62472. throw new Error(message);
  62473. };
  62474. let start = Date.now();
  62475. while(true){
  62476. let response = await fetch(url);
  62477. let jsResponse = await response.json();
  62478. if(jsResponse.status === "ERROR"){
  62479. handleError(jsResponse);
  62480. }else if(jsResponse.status === "FILTERING"){
  62481. handleFiltering(jsResponse);
  62482. }else if(jsResponse.status === "FINISHED"){
  62483. handleFinish(jsResponse);
  62484. break;
  62485. }else {
  62486. handleUnexpected(jsResponse);
  62487. }
  62488. let durationS = (Date.now() - start) / 1000;
  62489. let sleepAmountMS = durationS < 10 ? 100 : 1000;
  62490. await sleep(sleepAmountMS);
  62491. }
  62492. }
  62493. }
  62494. };
  62495. class CameraPanel{
  62496. constructor(viewer, propertiesPanel){
  62497. this.viewer = viewer;
  62498. this.propertiesPanel = propertiesPanel;
  62499. this._update = () => { this.update(); };
  62500. let copyIconPath = Potree.resourcePath + '/icons/copy.svg';
  62501. this.elContent = $(`
  62502. <div class="propertypanel_content">
  62503. <table>
  62504. <tr>
  62505. <th colspan="3">position</th>
  62506. <th></th>
  62507. </tr>
  62508. <tr>
  62509. <td align="center" id="camera_position_x" style="width: 25%"></td>
  62510. <td align="center" id="camera_position_y" style="width: 25%"></td>
  62511. <td align="center" id="camera_position_z" style="width: 25%"></td>
  62512. <td align="right" id="copy_camera_position" style="width: 25%">
  62513. <img name="copyPosition" title="copy" class="button-icon" src="${copyIconPath}" style="width: 16px; height: 16px"/>
  62514. </td>
  62515. </tr>
  62516. <tr>
  62517. <th colspan="3">target</th>
  62518. <th></th>
  62519. </tr>
  62520. <tr>
  62521. <td align="center" id="camera_target_x" style="width: 25%"></td>
  62522. <td align="center" id="camera_target_y" style="width: 25%"></td>
  62523. <td align="center" id="camera_target_z" style="width: 25%"></td>
  62524. <td align="right" id="copy_camera_target" style="width: 25%">
  62525. <img name="copyTarget" title="copy" class="button-icon" src="${copyIconPath}" style="width: 16px; height: 16px"/>
  62526. </td>
  62527. </tr>
  62528. </table>
  62529. </div>
  62530. `);
  62531. this.elCopyPosition = this.elContent.find("img[name=copyPosition]");
  62532. this.elCopyPosition.click( () => {
  62533. let pos = this.viewer.scene.getActiveCamera().position.toArray();
  62534. let msg = pos.map(c => c.toFixed(3)).join(", ");
  62535. Utils.clipboardCopy(msg);
  62536. this.viewer.postMessage(
  62537. `Copied value to clipboard: <br>'${msg}'`,
  62538. {duration: 3000});
  62539. });
  62540. this.elCopyTarget = this.elContent.find("img[name=copyTarget]");
  62541. this.elCopyTarget.click( () => {
  62542. let pos = this.viewer.scene.view.getPivot().toArray();
  62543. let msg = pos.map(c => c.toFixed(3)).join(", ");
  62544. Utils.clipboardCopy(msg);
  62545. this.viewer.postMessage(
  62546. `Copied value to clipboard: <br>'${msg}'`,
  62547. {duration: 3000});
  62548. });
  62549. this.propertiesPanel.addVolatileListener(viewer, "camera_changed", this._update);
  62550. this.update();
  62551. }
  62552. update(){
  62553. //console.log("updating camera panel");
  62554. let camera = this.viewer.scene.getActiveCamera();
  62555. let view = this.viewer.scene.view;
  62556. let pos = camera.position.toArray().map(c => Utils.addCommas(c.toFixed(3)));
  62557. this.elContent.find("#camera_position_x").html(pos[0]);
  62558. this.elContent.find("#camera_position_y").html(pos[1]);
  62559. this.elContent.find("#camera_position_z").html(pos[2]);
  62560. let target = view.getPivot().toArray().map(c => Utils.addCommas(c.toFixed(3)));
  62561. this.elContent.find("#camera_target_x").html(target[0]);
  62562. this.elContent.find("#camera_target_y").html(target[1]);
  62563. this.elContent.find("#camera_target_z").html(target[2]);
  62564. }
  62565. };
  62566. class AnnotationPanel{
  62567. constructor(viewer, propertiesPanel, annotation){
  62568. this.viewer = viewer;
  62569. this.propertiesPanel = propertiesPanel;
  62570. this.annotation = annotation;
  62571. this._update = () => { this.update(); };
  62572. let copyIconPath = `${Potree.resourcePath}/icons/copy.svg`;
  62573. this.elContent = $(`
  62574. <div class="propertypanel_content">
  62575. <table>
  62576. <tr>
  62577. <th colspan="3">position</th>
  62578. <th></th>
  62579. </tr>
  62580. <tr>
  62581. <td align="center" id="annotation_position_x" style="width: 25%"></td>
  62582. <td align="center" id="annotation_position_y" style="width: 25%"></td>
  62583. <td align="center" id="annotation_position_z" style="width: 25%"></td>
  62584. <td align="right" id="copy_annotation_position" style="width: 25%">
  62585. <img name="copyPosition" title="copy" class="button-icon" src="${copyIconPath}" style="width: 16px; height: 16px"/>
  62586. </td>
  62587. </tr>
  62588. </table>
  62589. <div>
  62590. <div class="heading">Title</div>
  62591. <div id="annotation_title" contenteditable="true">
  62592. Annotation Title
  62593. </div>
  62594. <div class="heading">Description</div>
  62595. <div id="annotation_description" contenteditable="true">
  62596. A longer description of this annotation.
  62597. Can be multiple lines long. TODO: the user should be able
  62598. to modify title and description.
  62599. </div>
  62600. </div>
  62601. </div>
  62602. `);
  62603. this.elCopyPosition = this.elContent.find("img[name=copyPosition]");
  62604. this.elCopyPosition.click( () => {
  62605. let pos = this.annotation.position.toArray();
  62606. let msg = pos.map(c => c.toFixed(3)).join(", ");
  62607. Utils.clipboardCopy(msg);
  62608. this.viewer.postMessage(
  62609. `Copied value to clipboard: <br>'${msg}'`,
  62610. {duration: 3000});
  62611. });
  62612. this.elTitle = this.elContent.find("#annotation_title").html(annotation.title);
  62613. this.elDescription = this.elContent.find("#annotation_description").html(annotation.description);
  62614. this.elTitle[0].addEventListener("input", () => {
  62615. const title = this.elTitle.html();
  62616. annotation.title = title;
  62617. }, false);
  62618. this.elDescription[0].addEventListener("input", () => {
  62619. const description = this.elDescription.html();
  62620. annotation.description = description;
  62621. }, false);
  62622. this.update();
  62623. }
  62624. update(){
  62625. const {annotation, elContent, elTitle, elDescription} = this;
  62626. let pos = annotation.position.toArray().map(c => Utils.addCommas(c.toFixed(3)));
  62627. elContent.find("#annotation_position_x").html(pos[0]);
  62628. elContent.find("#annotation_position_y").html(pos[1]);
  62629. elContent.find("#annotation_position_z").html(pos[2]);
  62630. elTitle.html(annotation.title);
  62631. elDescription.html(annotation.description);
  62632. }
  62633. };
  62634. class CameraAnimationPanel{
  62635. constructor(viewer, propertiesPanel, animation){
  62636. this.viewer = viewer;
  62637. this.propertiesPanel = propertiesPanel;
  62638. this.animation = animation;
  62639. this.elContent = $(`
  62640. <div class="propertypanel_content">
  62641. <span id="animation_keyframes"></span>
  62642. <span>
  62643. <span style="display:flex">
  62644. <span style="display:flex; align-items: center; padding-right: 10px">Duration: </span>
  62645. <input name="spnDuration" value="5.0" style="flex-grow: 1; width:100%">
  62646. </span>
  62647. <span>Time: </span><span id="lblTime"></span> <div id="sldTime"></div>
  62648. <input name="play" type="button" value="play"/>
  62649. </span>
  62650. </div>
  62651. `);
  62652. const elPlay = this.elContent.find("input[name=play]");
  62653. elPlay.click( () => {
  62654. animation.play();
  62655. });
  62656. const elSlider = this.elContent.find('#sldTime');
  62657. elSlider.slider({
  62658. value: 0,
  62659. min: 0,
  62660. max: 1,
  62661. step: 0.001,
  62662. slide: (event, ui) => {
  62663. animation.set(ui.value);
  62664. animation.updateFrustum();
  62665. }
  62666. });
  62667. let elDuration = this.elContent.find(`input[name=spnDuration]`);
  62668. elDuration.spinner({
  62669. min: 0, max: 300, step: 0.01,
  62670. numberFormat: 'n',
  62671. start: () => {},
  62672. spin: (event, ui) => {
  62673. let value = elDuration.spinner('value');
  62674. animation.setDuration(value);
  62675. },
  62676. change: (event, ui) => {
  62677. let value = elDuration.spinner('value');
  62678. animation.setDuration(value);
  62679. },
  62680. stop: (event, ui) => {
  62681. let value = elDuration.spinner('value');
  62682. animation.setDuration(value);
  62683. },
  62684. incremental: (count) => {
  62685. let value = elDuration.spinner('value');
  62686. let step = elDuration.spinner('option', 'step');
  62687. let delta = value * 0.05;
  62688. let increments = Math.max(1, parseInt(delta / step));
  62689. return increments;
  62690. }
  62691. });
  62692. elDuration.spinner('value', animation.getDuration());
  62693. elDuration.spinner('widget').css('width', '100%');
  62694. const elKeyframes = this.elContent.find("#animation_keyframes");
  62695. const updateKeyframes = () => {
  62696. elKeyframes.empty();
  62697. //let index = 0;
  62698. // <span style="flex-grow: 0;">
  62699. // <img name="add" src="${Potree.resourcePath}/icons/add.svg" style="width: 1.5em; height: 1.5em"/>
  62700. // </span>
  62701. const addNewKeyframeItem = (index) => {
  62702. let elNewKeyframe = $(`
  62703. <div style="display: flex; margin: 0.2em 0em">
  62704. <span style="flex-grow: 1"></span>
  62705. <input type="button" name="add" value="insert control point" />
  62706. <span style="flex-grow: 1"></span>
  62707. </div>
  62708. `);
  62709. const elAdd = elNewKeyframe.find("input[name=add]");
  62710. elAdd.click( () => {
  62711. animation.createControlPoint(index);
  62712. animation.changeCallback();
  62713. });
  62714. elKeyframes.append(elNewKeyframe);
  62715. };
  62716. const addKeyframeItem = (index) => {
  62717. let elKeyframe = $(`
  62718. <div style="display: flex; margin: 0.2em 0em">
  62719. <span style="flex-grow: 0;">
  62720. <img name="assign" src="${Potree.resourcePath}/icons/assign.svg" style="width: 1.5em; height: 1.5em"/>
  62721. </span>
  62722. <span style="flex-grow: 0;">
  62723. <img name="move" src="${Potree.resourcePath}/icons/circled_dot.svg" style="width: 1.5em; height: 1.5em"/>
  62724. </span>
  62725. <span style="flex-grow: 0; width: 1.5em; height: 1.5em"></span>
  62726. <span style="flex-grow: 0; font-size: 1.5em">keyframe</span>
  62727. <span style="flex-grow: 1"></span>
  62728. <span style="flex-grow: 0;">
  62729. <img name="delete" src="${Potree.resourcePath}/icons/remove.svg" style="width: 1.5em; height: 1.5em"/>
  62730. </span>
  62731. </div>
  62732. `);
  62733. const elAssign = elKeyframe.find("img[name=assign]");
  62734. const elMove = elKeyframe.find("img[name=move]");
  62735. const elDelete = elKeyframe.find("img[name=delete]");
  62736. elAssign.click( () => {
  62737. animation.posCurve.points[index].copy(viewer.scene.view.position);
  62738. animation.targetCurve.points[index].copy(viewer.scene.view.getPivot());
  62739. animation.changeCallback();
  62740. });
  62741. elMove.click( () => {
  62742. viewer.scene.view.position.copy(animation.posCurve.points[index]);
  62743. viewer.scene.view.lookAt(animation.targetCurve.points[index]);
  62744. });
  62745. elDelete.click( () => {
  62746. animation.removeControlPoint(index);
  62747. animation.changeCallback();
  62748. });
  62749. elKeyframes.append(elKeyframe);
  62750. };
  62751. let index = 0;
  62752. addNewKeyframeItem(index);
  62753. animation.posCurve.points.forEach(e=>{
  62754. addKeyframeItem(index);
  62755. index++;
  62756. addNewKeyframeItem(index);
  62757. });
  62758. };
  62759. updateKeyframes();
  62760. animation.addEventListener("controlpoint_added", updateKeyframes);
  62761. animation.addEventListener("controlpoint_removed", updateKeyframes);
  62762. // this._update = () => { this.update(); };
  62763. // this.update();
  62764. }
  62765. update(){
  62766. }
  62767. };
  62768. class PropertiesPanel{
  62769. constructor(container, viewer){
  62770. this.container = container;
  62771. this.viewer = viewer;
  62772. this.object = null;
  62773. this.cleanupTasks = [];
  62774. this.scene = null;
  62775. }
  62776. setScene(scene){
  62777. this.scene = scene;
  62778. }
  62779. set(object){
  62780. if(this.object === object){
  62781. return;
  62782. }
  62783. this.object = object;
  62784. for(let task of this.cleanupTasks){
  62785. task();
  62786. }
  62787. this.cleanupTasks = [];
  62788. this.container.empty();
  62789. if(object instanceof PointCloudTree){
  62790. this.setPointCloud(object);
  62791. }else if(object instanceof Measure || object instanceof Profile || object instanceof Volume){
  62792. this.setMeasurement(object);
  62793. }else if(object instanceof Camera){
  62794. this.setCamera(object);
  62795. }else if(object instanceof Annotation){
  62796. this.setAnnotation(object);
  62797. }/* else if(object instanceof CameraAnimation){//改
  62798. this.setCameraAnimation(object);
  62799. } */
  62800. }
  62801. //
  62802. // Used for events that should be removed when the property object changes.
  62803. // This is for listening to materials, scene, point clouds, etc.
  62804. // not required for DOM listeners, since they are automatically cleared by removing the DOM subtree.
  62805. //
  62806. addVolatileListener(target, type, callback){
  62807. target.addEventListener(type, callback);
  62808. this.cleanupTasks.push(() => {
  62809. target.removeEventListener(type, callback);
  62810. });
  62811. }
  62812. setPointCloud(pointcloud){
  62813. let material = pointcloud.material;
  62814. let panel = $(`
  62815. <div class="scene_content selectable">
  62816. <ul class="pv-menu-list">
  62817. <li>
  62818. <span data-i18n="appearance.point_size"></span>:&nbsp;<span id="lblPointSize"></span> <div id="sldPointSize"></div>
  62819. </li>
  62820. <li>
  62821. <span data-i18n="appearance.min_point_size"></span>:&nbsp;<span id="lblMinPointSize"></span> <div id="sldMinPointSize"></div>
  62822. </li>
  62823. <!-- SIZE TYPE -->
  62824. <li>
  62825. <label for="optPointSizing" class="pv-select-label" data-i18n="appearance.point_size_type">Point Sizing </label>
  62826. <select id="optPointSizing" name="optPointSizing">
  62827. <option>FIXED</option>
  62828. <option>ATTENUATED</option>
  62829. <option>ADAPTIVE</option>
  62830. </select>
  62831. </li>
  62832. <!-- SHAPE -->
  62833. <li>
  62834. <label for="optShape" class="pv-select-label" data-i18n="appearance.point_shape"></label><br>
  62835. <select id="optShape" name="optShape">
  62836. <option>SQUARE</option>
  62837. <option>CIRCLE</option>
  62838. <option>PARABOLOID</option>
  62839. </select>
  62840. </li>
  62841. <li id="materials_backface_container">
  62842. <label><input id="set_backface_culling" type="checkbox" /><span data-i18n="appearance.backface_culling"></span></label>
  62843. </li>
  62844. <!-- OPACITY -->
  62845. <li><span data-i18n="appearance.point_opacity"></span>:<span id="lblOpacity"></span><div id="sldOpacity"></div></li>
  62846. <div class="divider">
  62847. <span>Attribute</span>
  62848. </div>
  62849. <li>
  62850. <select id="optMaterial" name="optMaterial"></select>
  62851. </li>
  62852. <div id="materials.composite_weight_container">
  62853. <div class="divider">
  62854. <span>Attribute Weights</span>
  62855. </div>
  62856. <li>RGB: <span id="lblWeightRGB"></span> <div id="sldWeightRGB"></div> </li>
  62857. <li>Intensity: <span id="lblWeightIntensity"></span> <div id="sldWeightIntensity"></div> </li>
  62858. <li>Elevation: <span id="lblWeightElevation"></span> <div id="sldWeightElevation"></div> </li>
  62859. <li>Classification: <span id="lblWeightClassification"></span> <div id="sldWeightClassification"></div> </li>
  62860. <li>Return Number: <span id="lblWeightReturnNumber"></span> <div id="sldWeightReturnNumber"></div> </li>
  62861. <li>Source ID: <span id="lblWeightSourceID"></span> <div id="sldWeightSourceID"></div> </li>
  62862. </div>
  62863. <div id="materials.rgb_container">
  62864. <div class="divider">
  62865. <span>RGB</span>
  62866. </div>
  62867. <li>Gamma: <span id="lblRGBGamma"></span> <div id="sldRGBGamma"></div> </li>
  62868. <li>Brightness: <span id="lblRGBBrightness"></span> <div id="sldRGBBrightness"></div> </li>
  62869. <li>Contrast: <span id="lblRGBContrast"></span> <div id="sldRGBContrast"></div> </li>
  62870. </div>
  62871. <div id="materials.extra_container">
  62872. <div class="divider">
  62873. <span>Extra Attribute</span>
  62874. </div>
  62875. <li><span data-i18n="appearance.extra_range"></span>: <span id="lblExtraRange"></span> <div id="sldExtraRange"></div></li>
  62876. <li>Gamma: <span id="lblExtraGamma"></span> <div id="sldExtraGamma"></div></li>
  62877. <li>Brightness: <span id="lblExtraBrightness"></span> <div id="sldExtraBrightness"></div></li>
  62878. <li>Contrast: <span id="lblExtraContrast"></span> <div id="sldExtraContrast"></div></li>
  62879. </div>
  62880. <div id="materials.matcap_container">
  62881. <div class="divider">
  62882. <span>MATCAP</span>
  62883. </div>
  62884. <li>
  62885. <div id="matcap_scheme_selection" style="display: flex; flex-wrap: wrap;"> </div>
  62886. </li>
  62887. </div>
  62888. <div id="materials.color_container">
  62889. <div class="divider">
  62890. <span>Color</span>
  62891. </div>
  62892. <input id="materials.color.picker" />
  62893. </div>
  62894. <div id="materials.elevation_container">
  62895. <div class="divider">
  62896. <span>Elevation</span>
  62897. </div>
  62898. <li><span data-i18n="appearance.elevation_range"></span>: <span id="lblHeightRange"></span> <div id="sldHeightRange"></div> </li>
  62899. <li>
  62900. <selectgroup id="gradient_repeat_option">
  62901. <option id="gradient_repeat_clamp" value="CLAMP">Clamp</option>
  62902. <option id="gradient_repeat_repeat" value="REPEAT">Repeat</option>
  62903. <option id="gradient_repeat_mirrored_repeat" value="MIRRORED_REPEAT">Mirrored Repeat</option>
  62904. </selectgroup>
  62905. </li>
  62906. <li>
  62907. <span>Gradient Scheme:</span>
  62908. <div id="elevation_gradient_scheme_selection" style="display: flex; padding: 1em 0em">
  62909. </div>
  62910. </li>
  62911. </div>
  62912. <div id="materials.transition_container">
  62913. <div class="divider">
  62914. <span>Transition</span>
  62915. </div>
  62916. <li>transition: <span id="lblTransition"></span> <div id="sldTransition"></div> </li>
  62917. </div>
  62918. <div id="materials.intensity_container">
  62919. <div class="divider">
  62920. <span>Intensity</span>
  62921. </div>
  62922. <li>Range: <span id="lblIntensityRange"></span> <div id="sldIntensityRange"></div> </li>
  62923. <li>Gamma: <span id="lblIntensityGamma"></span> <div id="sldIntensityGamma"></div> </li>
  62924. <li>Brightness: <span id="lblIntensityBrightness"></span> <div id="sldIntensityBrightness"></div> </li>
  62925. <li>Contrast: <span id="lblIntensityContrast"></span> <div id="sldIntensityContrast"></div> </li>
  62926. </div>
  62927. <div id="materials.gpstime_container">
  62928. <div class="divider">
  62929. <span>GPS Time</span>
  62930. </div>
  62931. </div>
  62932. <div id="materials.index_container">
  62933. <div class="divider">
  62934. <span>Indices</span>
  62935. </div>
  62936. </div>
  62937. </ul>
  62938. </div>
  62939. `);
  62940. panel.i18n();
  62941. this.container.append(panel);
  62942. { // POINT SIZE
  62943. let sldPointSize = panel.find(`#sldPointSize`);
  62944. let lblPointSize = panel.find(`#lblPointSize`);
  62945. sldPointSize.slider({
  62946. value: material.size,
  62947. min: 0,
  62948. max: 3,
  62949. step: 0.01,
  62950. slide: function (event, ui) { material.size = ui.value; }
  62951. });
  62952. let update = (e) => {
  62953. lblPointSize.html(material.size.toFixed(2));
  62954. sldPointSize.slider({value: material.size});
  62955. };
  62956. this.addVolatileListener(material, "point_size_changed", update);
  62957. update();
  62958. }
  62959. { // MINIMUM POINT SIZE
  62960. let sldMinPointSize = panel.find(`#sldMinPointSize`);
  62961. let lblMinPointSize = panel.find(`#lblMinPointSize`);
  62962. sldMinPointSize.slider({
  62963. value: material.size,
  62964. min: 0,
  62965. max: 3,
  62966. step: 0.01,
  62967. slide: function (event, ui) { material.minSize = ui.value; }
  62968. });
  62969. let update = (e) => {
  62970. lblMinPointSize.html(material.minSize.toFixed(2));
  62971. sldMinPointSize.slider({value: material.minSize});
  62972. };
  62973. this.addVolatileListener(material, "point_size_changed", update);
  62974. update();
  62975. }
  62976. { // POINT SIZING
  62977. let strSizeType = Object.keys(PointSizeType)[material.pointSizeType];
  62978. let opt = panel.find(`#optPointSizing`);
  62979. opt.selectmenu();
  62980. opt.val(strSizeType).selectmenu('refresh');
  62981. opt.selectmenu({
  62982. change: (event, ui) => {
  62983. material.pointSizeType = PointSizeType[ui.item.value];
  62984. }
  62985. });
  62986. }
  62987. { // SHAPE
  62988. let opt = panel.find(`#optShape`);
  62989. opt.selectmenu({
  62990. change: (event, ui) => {
  62991. let value = ui.item.value;
  62992. material.shape = PointShape$1[value];
  62993. }
  62994. });
  62995. let update = () => {
  62996. let typename = Object.keys(PointShape$1)[material.shape];
  62997. opt.selectmenu().val(typename).selectmenu('refresh');
  62998. };
  62999. this.addVolatileListener(material, "point_shape_changed", update);
  63000. update();
  63001. }
  63002. { // BACKFACE CULLING
  63003. let opt = panel.find(`#set_backface_culling`);
  63004. opt.click(() => {
  63005. material.backfaceCulling = opt.prop("checked");
  63006. });
  63007. let update = () => {
  63008. let value = material.backfaceCulling;
  63009. opt.prop("checked", value);
  63010. };
  63011. this.addVolatileListener(material, "backface_changed", update);
  63012. update();
  63013. let blockBackface = $('#materials_backface_container');
  63014. blockBackface.css('display', 'none');
  63015. const pointAttributes = pointcloud.pcoGeometry.pointAttributes;
  63016. const hasNormals = pointAttributes.hasNormals ? pointAttributes.hasNormals() : false;
  63017. if(hasNormals) {
  63018. blockBackface.css('display', 'block');
  63019. }
  63020. /*
  63021. opt.checkboxradio({
  63022. clicked: (event, ui) => {
  63023. // let value = ui.item.value;
  63024. let value = ui.item.checked;
  63025. console.log(value);
  63026. material.backfaceCulling = value; // $('#set_freeze').prop("checked");
  63027. }
  63028. });
  63029. */
  63030. }
  63031. { // OPACITY
  63032. let sldOpacity = panel.find(`#sldOpacity`);
  63033. let lblOpacity = panel.find(`#lblOpacity`);
  63034. sldOpacity.slider({
  63035. value: material.opacity,
  63036. min: 0,
  63037. max: 1,
  63038. step: 0.001,
  63039. slide: function (event, ui) {
  63040. material.opacity = ui.value;
  63041. }
  63042. });
  63043. let update = (e) => {
  63044. lblOpacity.html(material.opacity.toFixed(2));
  63045. sldOpacity.slider({value: material.opacity});
  63046. };
  63047. this.addVolatileListener(material, "opacity_changed", update);
  63048. update();
  63049. }
  63050. {
  63051. const attributes = pointcloud.pcoGeometry.pointAttributes.attributes;
  63052. let options = [];
  63053. options.push(...attributes.map(a => a.name));
  63054. const intensityIndex = options.indexOf("intensity");
  63055. if(intensityIndex >= 0){
  63056. options.splice(intensityIndex + 1, 0, "intensity gradient");
  63057. }
  63058. options.push(
  63059. "elevation",
  63060. "color",
  63061. 'matcap',
  63062. 'indices',
  63063. 'level of detail',
  63064. 'composite'
  63065. );
  63066. const blacklist = [
  63067. "POSITION_CARTESIAN",
  63068. "position",
  63069. ];
  63070. options = options.filter(o => !blacklist.includes(o));
  63071. let attributeSelection = panel.find('#optMaterial');
  63072. for(let option of options){
  63073. let elOption = $(`<option>${option}</option>`);
  63074. attributeSelection.append(elOption);
  63075. }
  63076. let updateMaterialPanel = (event, ui) => {
  63077. let selectedValue = attributeSelection.selectmenu().val();
  63078. material.activeAttributeName = selectedValue;
  63079. let attribute = pointcloud.getAttribute(selectedValue);
  63080. if(selectedValue === "intensity gradient"){
  63081. attribute = pointcloud.getAttribute("intensity");
  63082. }
  63083. const isIntensity = attribute ? ["intensity", "intensity gradient"].includes(attribute.name) : false;
  63084. if(isIntensity){
  63085. if(pointcloud.material.intensityRange[0] === Infinity){
  63086. pointcloud.material.intensityRange = attribute.range;
  63087. }
  63088. const [min, max] = attribute.range;
  63089. panel.find('#sldIntensityRange').slider({
  63090. range: true,
  63091. min: min, max: max, step: 0.01,
  63092. values: [min, max],
  63093. slide: (event, ui) => {
  63094. let min = ui.values[0];
  63095. let max = ui.values[1];
  63096. material.intensityRange = [min, max];
  63097. }
  63098. });
  63099. } else if(attribute){
  63100. const [min, max] = attribute.range;
  63101. let selectedRange = material.getRange(attribute.name);
  63102. if(!selectedRange){
  63103. selectedRange = [...attribute.range];
  63104. }
  63105. let minMaxAreNumbers = typeof min === "number" && typeof max === "number";
  63106. if(minMaxAreNumbers){
  63107. panel.find('#sldExtraRange').slider({
  63108. range: true,
  63109. min: min,
  63110. max: max,
  63111. step: 0.01,
  63112. values: selectedRange,
  63113. slide: (event, ui) => {
  63114. let [a, b] = ui.values;
  63115. material.setRange(attribute.name, [a, b]);
  63116. }
  63117. });
  63118. }
  63119. }
  63120. let blockWeights = $('#materials\\.composite_weight_container');
  63121. let blockElevation = $('#materials\\.elevation_container');
  63122. let blockRGB = $('#materials\\.rgb_container');
  63123. let blockExtra = $('#materials\\.extra_container');
  63124. let blockColor = $('#materials\\.color_container');
  63125. let blockIntensity = $('#materials\\.intensity_container');
  63126. let blockIndex = $('#materials\\.index_container');
  63127. let blockTransition = $('#materials\\.transition_container');
  63128. let blockGps = $('#materials\\.gpstime_container');
  63129. let blockMatcap = $('#materials\\.matcap_container');
  63130. blockIndex.css('display', 'none');
  63131. blockIntensity.css('display', 'none');
  63132. blockElevation.css('display', 'none');
  63133. blockRGB.css('display', 'none');
  63134. blockExtra.css('display', 'none');
  63135. blockColor.css('display', 'none');
  63136. blockWeights.css('display', 'none');
  63137. blockTransition.css('display', 'none');
  63138. blockMatcap.css('display', 'none');
  63139. blockGps.css('display', 'none');
  63140. if (selectedValue === 'composite') {
  63141. blockWeights.css('display', 'block');
  63142. blockElevation.css('display', 'block');
  63143. blockRGB.css('display', 'block');
  63144. blockIntensity.css('display', 'block');
  63145. } else if (selectedValue === 'elevation') {
  63146. blockElevation.css('display', 'block');
  63147. } else if (selectedValue === 'RGB and Elevation') {
  63148. blockRGB.css('display', 'block');
  63149. blockElevation.css('display', 'block');
  63150. } else if (selectedValue === 'rgba') {
  63151. blockRGB.css('display', 'block');
  63152. } else if (selectedValue === 'color') {
  63153. blockColor.css('display', 'block');
  63154. } else if (selectedValue === 'intensity') {
  63155. blockIntensity.css('display', 'block');
  63156. } else if (selectedValue === 'intensity gradient') {
  63157. blockIntensity.css('display', 'block');
  63158. } else if (selectedValue === "indices" ){
  63159. blockIndex.css('display', 'block');
  63160. } else if (selectedValue === "matcap" ){
  63161. blockMatcap.css('display', 'block');
  63162. } else if (selectedValue === "classification" ){
  63163. // add classification color selctor?
  63164. } else if (selectedValue === "gps-time" ){
  63165. blockGps.css('display', 'block');
  63166. } else if(selectedValue === "number of returns"){
  63167. } else if(selectedValue === "return number"){
  63168. } else if(["source id", "point source id"].includes(selectedValue)){
  63169. } else {
  63170. blockExtra.css('display', 'block');
  63171. }
  63172. };
  63173. attributeSelection.selectmenu({change: updateMaterialPanel});
  63174. let update = () => {
  63175. attributeSelection.val(material.activeAttributeName).selectmenu('refresh');
  63176. };
  63177. this.addVolatileListener(material, "point_color_type_changed", update);
  63178. this.addVolatileListener(material, "active_attribute_changed", update);
  63179. update();
  63180. updateMaterialPanel();
  63181. }
  63182. {
  63183. const schemes = Object.keys(Potree.Gradients).map(name => ({name: name, values: Gradients[name]}));
  63184. let elSchemeContainer = panel.find("#elevation_gradient_scheme_selection");
  63185. for(let scheme of schemes){
  63186. let elScheme = $(`
  63187. <span style="flex-grow: 1;">
  63188. </span>
  63189. `);
  63190. const svg = Potree.Utils.createSvgGradient(scheme.values);
  63191. svg.setAttributeNS(null, "class", `button-icon`);
  63192. elScheme.append($(svg));
  63193. elScheme.click( () => {
  63194. material.gradient = Gradients[scheme.name];
  63195. });
  63196. elSchemeContainer.append(elScheme);
  63197. }
  63198. }
  63199. {
  63200. let matcaps = [
  63201. {name: "Normals", icon: `${Potree.resourcePath}/icons/matcap/check_normal+y.jpg`},
  63202. {name: "Basic 1", icon: `${Potree.resourcePath}/icons/matcap/basic_1.jpg`},
  63203. {name: "Basic 2", icon: `${Potree.resourcePath}/icons/matcap/basic_2.jpg`},
  63204. {name: "Basic Dark", icon: `${Potree.resourcePath}/icons/matcap/basic_dark.jpg`},
  63205. {name: "Basic Side", icon: `${Potree.resourcePath}/icons/matcap/basic_side.jpg`},
  63206. {name: "Ceramic Dark", icon: `${Potree.resourcePath}/icons/matcap/ceramic_dark.jpg`},
  63207. {name: "Ceramic Lightbulb", icon: `${Potree.resourcePath}/icons/matcap/ceramic_lightbulb.jpg`},
  63208. {name: "Clay Brown", icon: `${Potree.resourcePath}/icons/matcap/clay_brown.jpg`},
  63209. {name: "Clay Muddy", icon: `${Potree.resourcePath}/icons/matcap/clay_muddy.jpg`},
  63210. {name: "Clay Studio", icon: `${Potree.resourcePath}/icons/matcap/clay_studio.jpg`},
  63211. {name: "Resin", icon: `${Potree.resourcePath}/icons/matcap/resin.jpg`},
  63212. {name: "Skin", icon: `${Potree.resourcePath}/icons/matcap/skin.jpg`},
  63213. {name: "Jade", icon: `${Potree.resourcePath}/icons/matcap/jade.jpg`},
  63214. {name: "Metal_ Anisotropic", icon: `${Potree.resourcePath}/icons/matcap/metal_anisotropic.jpg`},
  63215. {name: "Metal Carpaint", icon: `${Potree.resourcePath}/icons/matcap/metal_carpaint.jpg`},
  63216. {name: "Metal Lead", icon: `${Potree.resourcePath}/icons/matcap/metal_lead.jpg`},
  63217. {name: "Metal Shiny", icon: `${Potree.resourcePath}/icons/matcap/metal_shiny.jpg`},
  63218. {name: "Pearl", icon: `${Potree.resourcePath}/icons/matcap/pearl.jpg`},
  63219. {name: "Toon", icon: `${Potree.resourcePath}/icons/matcap/toon.jpg`},
  63220. {name: "Check Rim Light", icon: `${Potree.resourcePath}/icons/matcap/check_rim_light.jpg`},
  63221. {name: "Check Rim Dark", icon: `${Potree.resourcePath}/icons/matcap/check_rim_dark.jpg`},
  63222. {name: "Contours 1", icon: `${Potree.resourcePath}/icons/matcap/contours_1.jpg`},
  63223. {name: "Contours 2", icon: `${Potree.resourcePath}/icons/matcap/contours_2.jpg`},
  63224. {name: "Contours 3", icon: `${Potree.resourcePath}/icons/matcap/contours_3.jpg`},
  63225. {name: "Reflection Check Horizontal", icon: `${Potree.resourcePath}/icons/matcap/reflection_check_horizontal.jpg`},
  63226. {name: "Reflection Check Vertical", icon: `${Potree.resourcePath}/icons/matcap/reflection_check_vertical.jpg`},
  63227. ];
  63228. let elMatcapContainer = panel.find("#matcap_scheme_selection");
  63229. for(let matcap of matcaps){
  63230. let elMatcap = $(`
  63231. <img src="${matcap.icon}" class="button-icon" style="width: 25%;" />
  63232. `);
  63233. elMatcap.click( () => {
  63234. material.matcap = matcap.icon.substring(matcap.icon.lastIndexOf('/'));
  63235. });
  63236. elMatcapContainer.append(elMatcap);
  63237. }
  63238. }
  63239. {
  63240. panel.find('#sldRGBGamma').slider({
  63241. value: material.rgbGamma,
  63242. min: 0, max: 4, step: 0.01,
  63243. slide: (event, ui) => {material.rgbGamma = ui.value;}
  63244. });
  63245. panel.find('#sldRGBContrast').slider({
  63246. value: material.rgbContrast,
  63247. min: -1, max: 1, step: 0.01,
  63248. slide: (event, ui) => {material.rgbContrast = ui.value;}
  63249. });
  63250. panel.find('#sldRGBBrightness').slider({
  63251. value: material.rgbBrightness,
  63252. min: -1, max: 1, step: 0.01,
  63253. slide: (event, ui) => {material.rgbBrightness = ui.value;}
  63254. });
  63255. panel.find('#sldExtraGamma').slider({
  63256. value: material.extraGamma,
  63257. min: 0, max: 4, step: 0.01,
  63258. slide: (event, ui) => {material.extraGamma = ui.value;}
  63259. });
  63260. panel.find('#sldExtraBrightness').slider({
  63261. value: material.extraBrightness,
  63262. min: -1, max: 1, step: 0.01,
  63263. slide: (event, ui) => {material.extraBrightness = ui.value;}
  63264. });
  63265. panel.find('#sldExtraContrast').slider({
  63266. value: material.extraContrast,
  63267. min: -1, max: 1, step: 0.01,
  63268. slide: (event, ui) => {material.extraContrast = ui.value;}
  63269. });
  63270. panel.find('#sldHeightRange').slider({
  63271. range: true,
  63272. min: 0, max: 1000, step: 0.01,
  63273. values: [0, 1000],
  63274. slide: (event, ui) => {
  63275. material.heightMin = ui.values[0];
  63276. material.heightMax = ui.values[1];
  63277. }
  63278. });
  63279. panel.find('#sldIntensityGamma').slider({
  63280. value: material.intensityGamma,
  63281. min: 0, max: 4, step: 0.01,
  63282. slide: (event, ui) => {material.intensityGamma = ui.value;}
  63283. });
  63284. panel.find('#sldIntensityContrast').slider({
  63285. value: material.intensityContrast,
  63286. min: -1, max: 1, step: 0.01,
  63287. slide: (event, ui) => {material.intensityContrast = ui.value;}
  63288. });
  63289. panel.find('#sldIntensityBrightness').slider({
  63290. value: material.intensityBrightness,
  63291. min: -1, max: 1, step: 0.01,
  63292. slide: (event, ui) => {material.intensityBrightness = ui.value;}
  63293. });
  63294. panel.find('#sldWeightRGB').slider({
  63295. value: material.weightRGB,
  63296. min: 0, max: 1, step: 0.01,
  63297. slide: (event, ui) => {material.weightRGB = ui.value;}
  63298. });
  63299. panel.find('#sldWeightIntensity').slider({
  63300. value: material.weightIntensity,
  63301. min: 0, max: 1, step: 0.01,
  63302. slide: (event, ui) => {material.weightIntensity = ui.value;}
  63303. });
  63304. panel.find('#sldWeightElevation').slider({
  63305. value: material.weightElevation,
  63306. min: 0, max: 1, step: 0.01,
  63307. slide: (event, ui) => {material.weightElevation = ui.value;}
  63308. });
  63309. panel.find('#sldWeightClassification').slider({
  63310. value: material.weightClassification,
  63311. min: 0, max: 1, step: 0.01,
  63312. slide: (event, ui) => {material.weightClassification = ui.value;}
  63313. });
  63314. panel.find('#sldWeightReturnNumber').slider({
  63315. value: material.weightReturnNumber,
  63316. min: 0, max: 1, step: 0.01,
  63317. slide: (event, ui) => {material.weightReturnNumber = ui.value;}
  63318. });
  63319. panel.find('#sldWeightSourceID').slider({
  63320. value: material.weightSourceID,
  63321. min: 0, max: 1, step: 0.01,
  63322. slide: (event, ui) => {material.weightSourceID = ui.value;}
  63323. });
  63324. panel.find(`#materials\\.color\\.picker`).spectrum({
  63325. flat: true,
  63326. showInput: true,
  63327. preferredFormat: 'rgb',
  63328. cancelText: '',
  63329. chooseText: 'Apply',
  63330. color: `#${material.color.getHexString()}`,
  63331. move: color => {
  63332. let cRGB = color.toRgb();
  63333. let tc = new Color().setRGB(cRGB.r / 255, cRGB.g / 255, cRGB.b / 255);
  63334. material.color = tc;
  63335. },
  63336. change: color => {
  63337. let cRGB = color.toRgb();
  63338. let tc = new Color().setRGB(cRGB.r / 255, cRGB.g / 255, cRGB.b / 255);
  63339. material.color = tc;
  63340. }
  63341. });
  63342. this.addVolatileListener(material, "color_changed", () => {
  63343. panel.find(`#materials\\.color\\.picker`)
  63344. .spectrum('set', `#${material.color.getHexString()}`);
  63345. });
  63346. let updateHeightRange = function () {
  63347. let aPosition = pointcloud.getAttribute("position");
  63348. let bMin, bMax;
  63349. if(aPosition){
  63350. // for new format 2.0 and loader that contain precomputed min/max of attributes
  63351. let min = aPosition.range[0][2];
  63352. let max = aPosition.range[1][2];
  63353. let width = max - min;
  63354. bMin = min - 0.2 * width;
  63355. bMax = max + 0.2 * width;
  63356. }else {
  63357. // for format up until exlusive 2.0
  63358. let box = [pointcloud.pcoGeometry.tightBoundingBox, pointcloud.getBoundingBoxWorld()]
  63359. .find(v => v !== undefined);
  63360. pointcloud.updateMatrixWorld(true);
  63361. box = Utils.computeTransformedBoundingBox(box, pointcloud.matrixWorld);
  63362. let bWidth = box.max.z - box.min.z;
  63363. bMin = box.min.z - 0.2 * bWidth;
  63364. bMax = box.max.z + 0.2 * bWidth;
  63365. }
  63366. let range = material.elevationRange;
  63367. panel.find('#lblHeightRange').html(`${range[0].toFixed(2)} to ${range[1].toFixed(2)}`);
  63368. panel.find('#sldHeightRange').slider({min: bMin, max: bMax, values: range});
  63369. };
  63370. let updateExtraRange = function () {
  63371. let attributeName = material.activeAttributeName;
  63372. let attribute = pointcloud.getAttribute(attributeName);
  63373. if(attribute == null){
  63374. return;
  63375. }
  63376. let range = material.getRange(attributeName);
  63377. if(range == null){
  63378. range = attribute.range;
  63379. }
  63380. // currently only supporting scalar ranges.
  63381. // rgba, normals, positions, etc have vector ranges, however
  63382. let isValidRange = (typeof range[0] === "number") && (typeof range[1] === "number");
  63383. if(!isValidRange){
  63384. return;
  63385. }
  63386. if(range){
  63387. let msg = `${range[0].toFixed(2)} to ${range[1].toFixed(2)}`;
  63388. panel.find('#lblExtraRange').html(msg);
  63389. }else {
  63390. panel.find("could not deduce range");
  63391. }
  63392. };
  63393. let updateIntensityRange = function () {
  63394. let range = material.intensityRange;
  63395. panel.find('#lblIntensityRange').html(`${parseInt(range[0])} to ${parseInt(range[1])}`);
  63396. };
  63397. {
  63398. updateHeightRange();
  63399. panel.find(`#sldHeightRange`).slider('option', 'min');
  63400. panel.find(`#sldHeightRange`).slider('option', 'max');
  63401. }
  63402. {
  63403. let elGradientRepeat = panel.find("#gradient_repeat_option");
  63404. elGradientRepeat.selectgroup({title: "Gradient"});
  63405. elGradientRepeat.find("input").click( (e) => {
  63406. this.viewer.setElevationGradientRepeat(ElevationGradientRepeat[e.target.value]);
  63407. });
  63408. let current = Object.keys(ElevationGradientRepeat)
  63409. .filter(key => ElevationGradientRepeat[key] === this.viewer.elevationGradientRepeat);
  63410. elGradientRepeat.find(`input[value=${current}]`).trigger("click");
  63411. }
  63412. let onIntensityChange = () => {
  63413. let gamma = material.intensityGamma;
  63414. let contrast = material.intensityContrast;
  63415. let brightness = material.intensityBrightness;
  63416. updateIntensityRange();
  63417. panel.find('#lblIntensityGamma').html(gamma.toFixed(2));
  63418. panel.find('#lblIntensityContrast').html(contrast.toFixed(2));
  63419. panel.find('#lblIntensityBrightness').html(brightness.toFixed(2));
  63420. panel.find('#sldIntensityGamma').slider({value: gamma});
  63421. panel.find('#sldIntensityContrast').slider({value: contrast});
  63422. panel.find('#sldIntensityBrightness').slider({value: brightness});
  63423. };
  63424. let onRGBChange = () => {
  63425. let gamma = material.rgbGamma;
  63426. let contrast = material.rgbContrast;
  63427. let brightness = material.rgbBrightness;
  63428. panel.find('#lblRGBGamma').html(gamma.toFixed(2));
  63429. panel.find('#lblRGBContrast').html(contrast.toFixed(2));
  63430. panel.find('#lblRGBBrightness').html(brightness.toFixed(2));
  63431. panel.find('#sldRGBGamma').slider({value: gamma});
  63432. panel.find('#sldRGBContrast').slider({value: contrast});
  63433. panel.find('#sldRGBBrightness').slider({value: brightness});
  63434. };
  63435. this.addVolatileListener(material, "material_property_changed", updateExtraRange);
  63436. this.addVolatileListener(material, "material_property_changed", updateHeightRange);
  63437. this.addVolatileListener(material, "material_property_changed", onIntensityChange);
  63438. this.addVolatileListener(material, "material_property_changed", onRGBChange);
  63439. updateExtraRange();
  63440. updateHeightRange();
  63441. onIntensityChange();
  63442. onRGBChange();
  63443. }
  63444. }
  63445. setMeasurement(object){
  63446. let TYPE = {
  63447. DISTANCE: {panel: DistancePanel},
  63448. AREA: {panel: AreaPanel},
  63449. POINT: {panel: PointPanel},
  63450. ANGLE: {panel: AnglePanel},
  63451. HEIGHT: {panel: HeightPanel},
  63452. PROFILE: {panel: ProfilePanel},
  63453. VOLUME: {panel: VolumePanel},
  63454. CIRCLE: {panel: CirclePanel},
  63455. OTHER: {panel: PointPanel},
  63456. };
  63457. let getType = (measurement) => {
  63458. if (measurement instanceof Measure) {
  63459. if (measurement.showDistances && !measurement.showArea && !measurement.showAngles) {
  63460. return TYPE.DISTANCE;
  63461. } else if (measurement.showDistances && measurement.showArea && !measurement.showAngles) {
  63462. return TYPE.AREA;
  63463. } else if (measurement.maxMarkers === 1) {
  63464. return TYPE.POINT;
  63465. } else if (!measurement.showDistances && !measurement.showArea && measurement.showAngles) {
  63466. return TYPE.ANGLE;
  63467. } else if (measurement.showHeight) {
  63468. return TYPE.HEIGHT;
  63469. } else if (measurement.showCircle) {
  63470. return TYPE.CIRCLE;
  63471. } else {
  63472. return TYPE.OTHER;
  63473. }
  63474. } else if (measurement instanceof Profile) {
  63475. return TYPE.PROFILE;
  63476. } else if (measurement instanceof Volume) {
  63477. return TYPE.VOLUME;
  63478. }
  63479. };
  63480. //this.container.html("measurement");
  63481. let type = getType(object);
  63482. let Panel = type.panel;
  63483. let panel = new Panel(this.viewer, object, this);
  63484. this.container.append(panel.elContent);
  63485. }
  63486. setCamera(camera){
  63487. let panel = new CameraPanel(this.viewer, this);
  63488. this.container.append(panel.elContent);
  63489. }
  63490. setAnnotation(annotation){
  63491. let panel = new AnnotationPanel(this.viewer, this, annotation);
  63492. this.container.append(panel.elContent);
  63493. }
  63494. setCameraAnimation(animation){
  63495. let panel = new CameraAnimationPanel(this.viewer, this, animation);
  63496. this.container.append(panel.elContent);
  63497. }
  63498. }
  63499. function addCommas(nStr){
  63500. nStr += '';
  63501. let x = nStr.split('.');
  63502. let x1 = x[0];
  63503. let x2 = x.length > 1 ? '.' + x[1] : '';
  63504. let rgx = /(\d+)(\d{3})/;
  63505. while (rgx.test(x1)) {
  63506. x1 = x1.replace(rgx, '$1' + ',' + '$2');
  63507. }
  63508. return x1 + x2;
  63509. };
  63510. function format(value){
  63511. return addCommas(value.toFixed(3));
  63512. };
  63513. class HierarchicalSlider{
  63514. constructor(params = {}){
  63515. this.element = document.createElement("div");
  63516. this.labels = [];
  63517. this.sliders = [];
  63518. this.range = params.range != null ? params.range : [0, 1];
  63519. this.slide = params.slide != null ? params.slide : null;
  63520. this.step = params.step != null ? params.step : 0.0001;
  63521. let levels = params.levels != null ? params.levels : 1;
  63522. for(let level = 0; level < levels; level++){
  63523. this.addLevel();
  63524. }
  63525. }
  63526. setRange(range){
  63527. this.range = [...range];
  63528. { // root slider
  63529. let slider = this.sliders[0];
  63530. $(slider).slider({
  63531. min: range[0],
  63532. max: range[1],
  63533. });
  63534. }
  63535. for(let i = 1; i < this.sliders.length; i++){
  63536. let parentSlider = this.sliders[i - 1];
  63537. let slider = this.sliders[i];
  63538. let parentValues = $(parentSlider).slider("option", "values");
  63539. let childRange = [...parentValues];
  63540. $(slider).slider({
  63541. min: childRange[0],
  63542. max: childRange[1],
  63543. });
  63544. }
  63545. this.updateLabels();
  63546. }
  63547. setValues(values){
  63548. for(let slider of this.sliders){
  63549. $(slider).slider({
  63550. values: [...values],
  63551. });
  63552. }
  63553. this.updateLabels();
  63554. }
  63555. addLevel(){
  63556. const elLevel = document.createElement("li");
  63557. const elRange = document.createTextNode("Range: ");
  63558. const label = document.createElement("span");
  63559. const slider = document.createElement("div");
  63560. let level = this.sliders.length;
  63561. let [min, max] = [0, 0];
  63562. if(this.sliders.length === 0){
  63563. [min, max] = this.range;
  63564. }else {
  63565. let parentSlider = this.sliders[this.sliders.length - 1];
  63566. [min, max] = $(parentSlider).slider("option", "values");
  63567. }
  63568. $(slider).slider({
  63569. range: true,
  63570. min: min,
  63571. max: max,
  63572. step: this.step,
  63573. values: [min, max],
  63574. slide: (event, ui) => {
  63575. // set all descendants to same range
  63576. let levels = this.sliders.length;
  63577. for(let i = level + 1; i < levels; i++){
  63578. let descendant = this.sliders[i];
  63579. $(descendant).slider({
  63580. range: true,
  63581. min: ui.values[0],
  63582. max: ui.values[1],
  63583. values: [...ui.values],
  63584. });
  63585. }
  63586. if(this.slide){
  63587. let values = [...ui.values];
  63588. this.slide({
  63589. target: this,
  63590. range: this.range,
  63591. values: values,
  63592. });
  63593. }
  63594. this.updateLabels();
  63595. },
  63596. });
  63597. elLevel.append(elRange, label, slider);
  63598. this.sliders.push(slider);
  63599. this.labels.push(label);
  63600. this.element.append(elLevel);
  63601. this.updateLabels();
  63602. }
  63603. removeLevel(){
  63604. }
  63605. updateSliders(){
  63606. }
  63607. updateLabels(){
  63608. let levels = this.sliders.length;
  63609. for(let i = 0; i < levels; i++){
  63610. let slider = this.sliders[i];
  63611. let label = this.labels[i];
  63612. let [min, max] = $(slider).slider("option", "values");
  63613. let strMin = format(min);
  63614. let strMax = format(max);
  63615. let strLabel = `${strMin} to ${strMax}`;
  63616. label.innerHTML = strLabel;
  63617. }
  63618. }
  63619. }
  63620. class OrientedImageControls extends EventDispatcher$1{
  63621. constructor(viewer){
  63622. super();
  63623. this.viewer = viewer;
  63624. this.renderer = viewer.renderer;
  63625. this.originalCam = viewer.scene.getActiveCamera();
  63626. this.shearCam = viewer.scene.getActiveCamera().clone();
  63627. this.shearCam.rotation.set(this.originalCam.rotation.toArray());
  63628. this.shearCam.updateProjectionMatrix();
  63629. this.shearCam.updateProjectionMatrix = () => {
  63630. return this.shearCam.projectionMatrix;
  63631. };
  63632. this.image = null;
  63633. this.fadeFactor = 20;
  63634. this.fovDelta = 0;
  63635. this.fovMin = 0.1;
  63636. this.fovMax = 120;
  63637. this.shear = [0, 0];
  63638. // const style = ``;
  63639. this.elUp = $(`<input type="button" value="🡅" style="position: absolute; top: 10px; left: calc(50%); z-index: 1000" />`);
  63640. this.elRight = $(`<input type="button" value="🡆" style="position: absolute; top: calc(50%); right: 10px; z-index: 1000" />`);
  63641. this.elDown = $(`<input type="button" value="🡇" style="position: absolute; bottom: 10px; left: calc(50%); z-index: 1000" />`);
  63642. this.elLeft = $(`<input type="button" value="🡄" style="position: absolute; top: calc(50%); left: 10px; z-index: 1000" />`);
  63643. this.elExit = $(`<input type="button" value="Back to 3D view" style="position: absolute; bottom: 10px; right: 10px; z-index: 1000" />`);
  63644. this.elExit.click( () => {
  63645. this.release();
  63646. });
  63647. this.elUp.click(() => {
  63648. const fovY = viewer.getFOV();
  63649. const top = Math.tan(MathUtils$1.degToRad(fovY / 2));
  63650. this.shear[1] += 0.1 * top;
  63651. });
  63652. this.elRight.click(() => {
  63653. const fovY = viewer.getFOV();
  63654. const top = Math.tan(MathUtils$1.degToRad(fovY / 2));
  63655. this.shear[0] += 0.1 * top;
  63656. });
  63657. this.elDown.click(() => {
  63658. const fovY = viewer.getFOV();
  63659. const top = Math.tan(MathUtils$1.degToRad(fovY / 2));
  63660. this.shear[1] -= 0.1 * top;
  63661. });
  63662. this.elLeft.click(() => {
  63663. const fovY = viewer.getFOV();
  63664. const top = Math.tan(MathUtils$1.degToRad(fovY / 2));
  63665. this.shear[0] -= 0.1 * top;
  63666. });
  63667. this.scene = null;
  63668. this.sceneControls = new Scene();
  63669. let scroll = (e) => {
  63670. this.fovDelta += -e.delta * 1.0;
  63671. };
  63672. this.addEventListener('mousewheel', scroll);
  63673. //this.addEventListener("mousemove", onMove);
  63674. }
  63675. hasSomethingCaptured(){
  63676. return this.image !== null;
  63677. }
  63678. capture(image){
  63679. if(this.hasSomethingCaptured()){
  63680. return;
  63681. }
  63682. this.image = image;
  63683. this.originalFOV = this.viewer.getFOV();
  63684. this.originalControls = this.viewer.getControls();
  63685. this.viewer.setControls(this);
  63686. this.viewer.scene.overrideCamera = this.shearCam;
  63687. const elCanvas = this.viewer.renderer.domElement;
  63688. const elRoot = $(elCanvas.parentElement);
  63689. this.shear = [0, 0];
  63690. elRoot.append(this.elUp);
  63691. elRoot.append(this.elRight);
  63692. elRoot.append(this.elDown);
  63693. elRoot.append(this.elLeft);
  63694. elRoot.append(this.elExit);
  63695. }
  63696. release(){
  63697. this.image = null;
  63698. this.viewer.scene.overrideCamera = null;
  63699. this.elUp.detach();
  63700. this.elRight.detach();
  63701. this.elDown.detach();
  63702. this.elLeft.detach();
  63703. this.elExit.detach();
  63704. this.viewer.setFOV(this.originalFOV);
  63705. this.viewer.setControls(this.originalControls);
  63706. }
  63707. setScene (scene) {
  63708. this.scene = scene;
  63709. }
  63710. update (delta) {
  63711. // const view = this.scene.view;
  63712. // let prevTotal = this.shearCam.projectionMatrix.elements.reduce( (a, i) => a + i, 0);
  63713. //const progression = Math.min(1, this.fadeFactor * delta);
  63714. //const attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  63715. const progression = 1;
  63716. const attenuation = 0;
  63717. const oldFov = this.viewer.getFOV();
  63718. let fovProgression = progression * this.fovDelta;
  63719. let newFov = oldFov * ((1 + fovProgression / 10));
  63720. newFov = Math.max(this.fovMin, newFov);
  63721. newFov = Math.min(this.fovMax, newFov);
  63722. let diff = newFov / oldFov;
  63723. const mouse = this.viewer.inputHandler.mouse;
  63724. const canvasSize = this.viewer.renderer.getSize(new Vector2());
  63725. const uv = [
  63726. (mouse.x / canvasSize.x),
  63727. ((canvasSize.y - mouse.y) / canvasSize.y)
  63728. ];
  63729. const fovY = newFov;
  63730. const aspect = canvasSize.x / canvasSize.y;
  63731. const top = Math.tan(MathUtils$1.degToRad(fovY / 2));
  63732. const height = 2 * top;
  63733. const width = aspect * height;
  63734. const shearRangeX = [
  63735. this.shear[0] - 0.5 * width,
  63736. this.shear[0] + 0.5 * width,
  63737. ];
  63738. const shearRangeY = [
  63739. this.shear[1] - 0.5 * height,
  63740. this.shear[1] + 0.5 * height,
  63741. ];
  63742. const shx = (1 - uv[0]) * shearRangeX[0] + uv[0] * shearRangeX[1];
  63743. const shy = (1 - uv[1]) * shearRangeY[0] + uv[1] * shearRangeY[1];
  63744. const shu = (1 - diff);
  63745. const newShear = [
  63746. (1 - shu) * this.shear[0] + shu * shx,
  63747. (1 - shu) * this.shear[1] + shu * shy,
  63748. ];
  63749. this.shear = newShear;
  63750. this.viewer.setFOV(newFov);
  63751. const {originalCam, shearCam} = this;
  63752. originalCam.fov = newFov;
  63753. originalCam.updateMatrixWorld();
  63754. originalCam.updateProjectionMatrix();
  63755. shearCam.copy(originalCam);
  63756. shearCam.rotation.set(...originalCam.rotation.toArray());
  63757. shearCam.updateMatrixWorld();
  63758. shearCam.projectionMatrix.copy(originalCam.projectionMatrix);
  63759. const [sx, sy] = this.shear;
  63760. const mShear = new Matrix4().set(
  63761. 1, 0, sx, 0,
  63762. 0, 1, sy, 0,
  63763. 0, 0, 1, 0,
  63764. 0, 0, 0, 1,
  63765. );
  63766. const proj = shearCam.projectionMatrix;
  63767. proj.multiply(mShear);
  63768. shearCam.projectionMatrixInverse.copy(proj).invert();
  63769. let total = shearCam.projectionMatrix.elements.reduce( (a, i) => a + i, 0);
  63770. this.fovDelta *= attenuation;
  63771. }
  63772. };
  63773. // https://support.pix4d.com/hc/en-us/articles/205675256-How-are-yaw-pitch-roll-defined
  63774. // https://support.pix4d.com/hc/en-us/articles/202558969-How-are-omega-phi-kappa-defined
  63775. function createMaterial(){
  63776. let vertexShader = `
  63777. uniform float uNear;
  63778. varying vec2 vUV;
  63779. varying vec4 vDebug;
  63780. void main(){
  63781. vDebug = vec4(0.0, 1.0, 0.0, 1.0);
  63782. vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
  63783. // make sure that this mesh is at least in front of the near plane
  63784. modelViewPosition.xyz += normalize(modelViewPosition.xyz) * uNear;
  63785. gl_Position = projectionMatrix * modelViewPosition;
  63786. vUV = uv;
  63787. }
  63788. `;
  63789. let fragmentShader = `
  63790. uniform sampler2D tColor;
  63791. uniform float uOpacity;
  63792. varying vec2 vUV;
  63793. varying vec4 vDebug;
  63794. void main(){
  63795. vec4 color = texture2D(tColor, vUV);
  63796. gl_FragColor = color;
  63797. gl_FragColor.a = uOpacity;
  63798. }
  63799. `;
  63800. const material = new ShaderMaterial( {
  63801. uniforms: {
  63802. // time: { value: 1.0 },
  63803. // resolution: { value: new THREE.Vector2() }
  63804. tColor: {value: new Texture() },
  63805. uNear: {value: 0.0},
  63806. uOpacity: {value: 1.0},
  63807. },
  63808. vertexShader: vertexShader,
  63809. fragmentShader: fragmentShader,
  63810. side: DoubleSide,
  63811. } );
  63812. material.side = DoubleSide;
  63813. return material;
  63814. }
  63815. const planeGeometry = new PlaneGeometry(1, 1);
  63816. const lineGeometry = new Geometry();
  63817. lineGeometry.vertices.push(
  63818. new Vector3(-0.5, -0.5, 0),
  63819. new Vector3( 0.5, -0.5, 0),
  63820. new Vector3( 0.5, 0.5, 0),
  63821. new Vector3(-0.5, 0.5, 0),
  63822. new Vector3(-0.5, -0.5, 0),
  63823. );
  63824. class OrientedImage{
  63825. constructor(id){
  63826. this.id = id;
  63827. this.fov = 1.0;
  63828. this.position = new Vector3();
  63829. this.rotation = new Vector3();
  63830. this.width = 0;
  63831. this.height = 0;
  63832. this.fov = 1.0;
  63833. const material = createMaterial();
  63834. const lineMaterial = new LineBasicMaterial( { color: 0x00ff00 } );
  63835. this.mesh = new Mesh(planeGeometry, material);
  63836. this.line = new Line(lineGeometry, lineMaterial);
  63837. this.texture = null;
  63838. this.mesh.orientedImage = this;
  63839. }
  63840. set(position, rotation, dimension, fov){
  63841. let radians = rotation.map(MathUtils$1.degToRad);
  63842. this.position.set(...position);
  63843. this.mesh.position.set(...position);
  63844. this.rotation.set(...radians);
  63845. this.mesh.rotation.set(...radians);
  63846. [this.width, this.height] = dimension;
  63847. this.mesh.scale.set(this.width / this.height, 1, 1);
  63848. this.fov = fov;
  63849. this.updateTransform();
  63850. }
  63851. updateTransform(){
  63852. let {mesh, line, fov} = this;
  63853. mesh.updateMatrixWorld();
  63854. const dir = mesh.getWorldDirection();
  63855. const alpha = MathUtils$1.degToRad(fov / 2);
  63856. const d = -0.5 / Math.tan(alpha);
  63857. const move = dir.clone().multiplyScalar(d);
  63858. mesh.position.add(move);
  63859. line.position.copy(mesh.position);
  63860. line.scale.copy(mesh.scale);
  63861. line.rotation.copy(mesh.rotation);
  63862. }
  63863. };
  63864. class OrientedImages extends EventDispatcher$1{
  63865. constructor(){
  63866. super();
  63867. this.node = null;
  63868. this.cameraParams = null;
  63869. this.imageParams = null;
  63870. this.images = null;
  63871. this._visible = true;
  63872. }
  63873. set visible(visible){
  63874. if(this._visible === visible){
  63875. return;
  63876. }
  63877. for(const image of this.images){
  63878. image.mesh.visible = visible;
  63879. image.line.visible = visible;
  63880. }
  63881. this._visible = visible;
  63882. this.dispatchEvent({
  63883. type: "visibility_changed",
  63884. images: this,
  63885. });
  63886. }
  63887. get visible(){
  63888. return this._visible;
  63889. }
  63890. };
  63891. class OrientedImageLoader{
  63892. static async loadCameraParams(path){
  63893. const res = await fetch(path);
  63894. const text = await res.text();
  63895. const parser = new DOMParser();
  63896. const doc = parser.parseFromString(text, "application/xml");
  63897. const width = parseInt(doc.getElementsByTagName("width")[0].textContent);
  63898. const height = parseInt(doc.getElementsByTagName("height")[0].textContent);
  63899. const f = parseFloat(doc.getElementsByTagName("f")[0].textContent);
  63900. let a = (height / 2) / f;
  63901. let fov = 2 * MathUtils$1.radToDeg(Math.atan(a));
  63902. const params = {
  63903. path: path,
  63904. width: width,
  63905. height: height,
  63906. f: f,
  63907. fov: fov,
  63908. };
  63909. return params;
  63910. }
  63911. static async loadImageParams(path){
  63912. const response = await fetch(path);
  63913. if(!response.ok){
  63914. console.error(`failed to load ${path}`);
  63915. return;
  63916. }
  63917. const content = await response.text();
  63918. const lines = content.split(/\r?\n/);
  63919. const imageParams = [];
  63920. for(let i = 1; i < lines.length; i++){
  63921. const line = lines[i];
  63922. if(line.startsWith("#")){
  63923. continue;
  63924. }
  63925. const tokens = line.split(/\s+/);
  63926. if(tokens.length < 6){
  63927. continue;
  63928. }
  63929. const params = {
  63930. id: tokens[0],
  63931. x: Number.parseFloat(tokens[1]),
  63932. y: Number.parseFloat(tokens[2]),
  63933. z: Number.parseFloat(tokens[3]),
  63934. omega: Number.parseFloat(tokens[4]),
  63935. phi: Number.parseFloat(tokens[5]),
  63936. kappa: Number.parseFloat(tokens[6]),
  63937. };
  63938. // const whitelist = ["47518.jpg"];
  63939. // if(whitelist.includes(params.id)){
  63940. // imageParams.push(params);
  63941. // }
  63942. imageParams.push(params);
  63943. }
  63944. // debug
  63945. //return [imageParams[50]];
  63946. return imageParams;
  63947. }
  63948. static async load(cameraParamsPath, imageParamsPath, viewer){
  63949. const tStart = performance.now();
  63950. const [cameraParams, imageParams] = await Promise.all([
  63951. OrientedImageLoader.loadCameraParams(cameraParamsPath),
  63952. OrientedImageLoader.loadImageParams(imageParamsPath),
  63953. ]);
  63954. const orientedImageControls = new OrientedImageControls(viewer);
  63955. const raycaster = new Raycaster();
  63956. const tEnd = performance.now();
  63957. console.log(tEnd - tStart);
  63958. // const sp = new THREE.PlaneGeometry(1, 1);
  63959. // const lg = new THREE.Geometry();
  63960. // lg.vertices.push(
  63961. // new THREE.Vector3(-0.5, -0.5, 0),
  63962. // new THREE.Vector3( 0.5, -0.5, 0),
  63963. // new THREE.Vector3( 0.5, 0.5, 0),
  63964. // new THREE.Vector3(-0.5, 0.5, 0),
  63965. // new THREE.Vector3(-0.5, -0.5, 0),
  63966. // );
  63967. const {width, height} = cameraParams;
  63968. const orientedImages = [];
  63969. const sceneNode = new Object3D();
  63970. sceneNode.name = "oriented_images";
  63971. for(const params of imageParams){
  63972. // const material = createMaterial();
  63973. // const lm = new THREE.LineBasicMaterial( { color: 0x00ff00 } );
  63974. // const mesh = new THREE.Mesh(sp, material);
  63975. const {x, y, z, omega, phi, kappa} = params;
  63976. // const [rx, ry, rz] = [omega, phi, kappa]
  63977. // .map(THREE.Math.degToRad);
  63978. // mesh.position.set(x, y, z);
  63979. // mesh.scale.set(width / height, 1, 1);
  63980. // mesh.rotation.set(rx, ry, rz);
  63981. // {
  63982. // mesh.updateMatrixWorld();
  63983. // const dir = mesh.getWorldDirection();
  63984. // const alpha = THREE.Math.degToRad(cameraParams.fov / 2);
  63985. // const d = -0.5 / Math.tan(alpha);
  63986. // const move = dir.clone().multiplyScalar(d);
  63987. // mesh.position.add(move);
  63988. // }
  63989. // sceneNode.add(mesh);
  63990. // const line = new THREE.Line(lg, lm);
  63991. // line.position.copy(mesh.position);
  63992. // line.scale.copy(mesh.scale);
  63993. // line.rotation.copy(mesh.rotation);
  63994. // sceneNode.add(line);
  63995. let orientedImage = new OrientedImage(params.id);
  63996. // orientedImage.setPosition(x, y, z);
  63997. // orientedImage.setRotation(omega, phi, kappa);
  63998. // orientedImage.setDimension(width, height);
  63999. let position = [x, y, z];
  64000. let rotation = [omega, phi, kappa];
  64001. let dimension = [width, height];
  64002. orientedImage.set(position, rotation, dimension, cameraParams.fov);
  64003. sceneNode.add(orientedImage.mesh);
  64004. sceneNode.add(orientedImage.line);
  64005. orientedImages.push(orientedImage);
  64006. }
  64007. let hoveredElement = null;
  64008. let clipVolume = null;
  64009. const onMouseMove = (evt) => {
  64010. const tStart = performance.now();
  64011. if(hoveredElement){
  64012. hoveredElement.line.material.color.setRGB(0, 1, 0);
  64013. }
  64014. evt.preventDefault();
  64015. //var array = getMousePosition( container, evt.clientX, evt.clientY );
  64016. const rect = viewer.renderer.domElement.getBoundingClientRect();
  64017. const [x, y] = [evt.clientX, evt.clientY];
  64018. const array = [
  64019. ( x - rect.left ) / rect.width,
  64020. ( y - rect.top ) / rect.height
  64021. ];
  64022. const onClickPosition = new Vector2(...array);
  64023. //const intersects = getIntersects(onClickPosition, scene.children);
  64024. const camera = viewer.scene.getActiveCamera();
  64025. const mouse = new Vector3(
  64026. + ( onClickPosition.x * 2 ) - 1,
  64027. - ( onClickPosition.y * 2 ) + 1 );
  64028. const objects = orientedImages.map(i => i.mesh);
  64029. raycaster.setFromCamera( mouse, camera );
  64030. const intersects = raycaster.intersectObjects( objects );
  64031. let selectionChanged = false;
  64032. if ( intersects.length > 0){
  64033. //console.log(intersects);
  64034. const intersection = intersects[0];
  64035. const orientedImage = intersection.object.orientedImage;
  64036. orientedImage.line.material.color.setRGB(1, 0, 0);
  64037. selectionChanged = hoveredElement !== orientedImage;
  64038. hoveredElement = orientedImage;
  64039. }else {
  64040. hoveredElement = null;
  64041. }
  64042. let shouldRemoveClipVolume = clipVolume !== null && hoveredElement === null;
  64043. let shouldAddClipVolume = clipVolume === null && hoveredElement !== null;
  64044. if(clipVolume !== null && (hoveredElement === null || selectionChanged)){
  64045. // remove existing
  64046. viewer.scene.removePolygonClipVolume(clipVolume);
  64047. clipVolume = null;
  64048. }
  64049. if(shouldAddClipVolume || selectionChanged){
  64050. const img = hoveredElement;
  64051. const fov = cameraParams.fov;
  64052. const aspect = cameraParams.width / cameraParams.height;
  64053. const near = 1.0;
  64054. const far = 1000 * 1000;
  64055. const camera = new PerspectiveCamera(fov, aspect, near, far);
  64056. camera.rotation.order = viewer.scene.getActiveCamera().rotation.order;
  64057. camera.rotation.copy(img.mesh.rotation);
  64058. {
  64059. const mesh = img.mesh;
  64060. const dir = mesh.getWorldDirection();
  64061. const pos = mesh.position;
  64062. const alpha = MathUtils$1.degToRad(fov / 2);
  64063. const d = 0.5 / Math.tan(alpha);
  64064. const newCamPos = pos.clone().add(dir.clone().multiplyScalar(d));
  64065. const newCamDir = pos.clone().sub(newCamPos);
  64066. const newCamTarget = new Vector3().addVectors(
  64067. newCamPos,
  64068. newCamDir.clone().multiplyScalar(viewer.getMoveSpeed()));
  64069. camera.position.copy(newCamPos);
  64070. }
  64071. let volume = new Potree.PolygonClipVolume(camera);
  64072. let m0 = new Mesh();
  64073. let m1 = new Mesh();
  64074. let m2 = new Mesh();
  64075. let m3 = new Mesh();
  64076. m0.position.set(-1, -1, 0);
  64077. m1.position.set( 1, -1, 0);
  64078. m2.position.set( 1, 1, 0);
  64079. m3.position.set(-1, 1, 0);
  64080. volume.markers.push(m0, m1, m2, m3);
  64081. volume.initialized = true;
  64082. viewer.scene.addPolygonClipVolume(volume);
  64083. clipVolume = volume;
  64084. }
  64085. const tEnd = performance.now();
  64086. //console.log(tEnd - tStart);
  64087. };
  64088. const moveToImage = (image) => {
  64089. console.log("move to image " + image.id);
  64090. const mesh = image.mesh;
  64091. const newCamPos = image.position.clone();
  64092. const newCamTarget = mesh.position.clone();
  64093. viewer.scene.view.setView(newCamPos, newCamTarget, 500, () => {
  64094. orientedImageControls.capture(image);
  64095. });
  64096. if(image.texture === null){
  64097. const target = image;
  64098. const tmpImagePath = `${Potree.resourcePath}/images/loading.jpg`;
  64099. new TextureLoader().load(tmpImagePath,
  64100. (texture) => {
  64101. if(target.texture === null){
  64102. target.texture = texture;
  64103. target.mesh.material.uniforms.tColor.value = texture;
  64104. mesh.material.needsUpdate = true;
  64105. }
  64106. }
  64107. );
  64108. const imagePath = `${imageParamsPath}/../${target.id}`;
  64109. new TextureLoader().load(imagePath,
  64110. (texture) => {
  64111. target.texture = texture;
  64112. target.mesh.material.uniforms.tColor.value = texture;
  64113. mesh.material.needsUpdate = true;
  64114. }
  64115. );
  64116. }
  64117. };
  64118. const onMouseClick = (evt) => {
  64119. if(orientedImageControls.hasSomethingCaptured()){
  64120. return;
  64121. }
  64122. if(hoveredElement){
  64123. moveToImage(hoveredElement);
  64124. }
  64125. };
  64126. viewer.renderer.domElement.addEventListener( 'mousemove', onMouseMove, false );
  64127. viewer.renderer.domElement.addEventListener( 'mousedown', onMouseClick, false );
  64128. viewer.addEventListener("update", () => {
  64129. for(const image of orientedImages){
  64130. const world = image.mesh.matrixWorld;
  64131. const {width, height} = image;
  64132. const aspect = width / height;
  64133. const camera = viewer.scene.getActiveCamera();
  64134. const imgPos = image.mesh.getWorldPosition(new Vector3());
  64135. const camPos = camera.position;
  64136. const d = camPos.distanceTo(imgPos);
  64137. const minSize = 1; // in degrees of fov
  64138. const a = MathUtils$1.degToRad(minSize);
  64139. let r = d * Math.tan(a);
  64140. r = Math.max(r, 1);
  64141. image.mesh.scale.set(r * aspect, r, 1);
  64142. image.line.scale.set(r * aspect, r, 1);
  64143. image.mesh.material.uniforms.uNear.value = camera.near;
  64144. }
  64145. });
  64146. const images = new OrientedImages();
  64147. images.node = sceneNode;
  64148. images.cameraParamsPath = cameraParamsPath;
  64149. images.imageParamsPath = imageParamsPath;
  64150. images.cameraParams = cameraParams;
  64151. images.imageParams = imageParams;
  64152. images.images = orientedImages;
  64153. Potree.debug.moveToImage = moveToImage;
  64154. return images;
  64155. }
  64156. }
  64157. const prefixVertex ="precision highp float;\nprecision highp int;\n\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\n";
  64158. const prefixFragment ="precision highp float;\nprecision highp int;\n\nuniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n";
  64159. let shader = {
  64160. uniforms: {
  64161. opacity: {
  64162. type: "f",
  64163. // value: 1
  64164. },
  64165. progress: {
  64166. type: "f",
  64167. value: 0
  64168. },
  64169. pano0Map: {
  64170. type: "t",
  64171. value: null
  64172. },
  64173. pano1Map: {
  64174. type: "t",
  64175. value: null
  64176. },
  64177. depthMap0: {
  64178. type: "t",
  64179. value: null
  64180. },
  64181. depthMap1: {
  64182. type: "t",
  64183. value: null
  64184. },
  64185. pano0Position: {
  64186. type: "v3",
  64187. value: new Vector3
  64188. },
  64189. pano0Matrix: {
  64190. type: "m4",
  64191. value: new Matrix4
  64192. },
  64193. pano1Position: {
  64194. type: "v3",
  64195. value: new Vector3
  64196. },
  64197. pano1Matrix: {
  64198. type: "m4",
  64199. value: new Matrix4
  64200. },
  64201. /* pano1Matrix2: {
  64202. type: "m4",
  64203. value: new THREE.Matrix4
  64204. },
  64205. */
  64206. inverseProjectionMatrix: {
  64207. value: new Matrix4
  64208. },
  64209. /* projectionMatrix:{//需要再写一遍吗
  64210. value: new THREE.Matrix4
  64211. }, */
  64212. viewport: {
  64213. value: new Vector4
  64214. },
  64215. //如 {x: 0, y: 0, z: 428, w: 969} xy应该是offset, zw是宽高
  64216. cameraHeight0: {
  64217. type: "f",
  64218. value: 1
  64219. },
  64220. cameraHeight1: {
  64221. type: "f",
  64222. value: 1
  64223. },
  64224. ceilHeight0:{
  64225. type: "f",
  64226. value: 2
  64227. },
  64228. ceilHeight1:{
  64229. type: "f",
  64230. value: 2
  64231. },
  64232. },
  64233. vertexShader: prefixVertex + `
  64234. uniform vec3 pano0Position;
  64235. uniform mat4 pano0Matrix;
  64236. uniform vec3 pano1Position;
  64237. uniform mat4 pano1Matrix;
  64238. //uniform mat4 pano1Matrix2;
  64239. varying vec2 vUv;
  64240. varying vec3 vWorldPosition0;
  64241. varying vec3 vWorldPosition1;
  64242. varying vec3 vWorldPosition12;
  64243. vec3 transformAxis( vec3 direction ) //navvis->4dkk
  64244. {
  64245. float y = direction.y;
  64246. direction.y = direction.z;
  64247. direction.z = -y;
  64248. return direction;
  64249. }
  64250. void main() {
  64251. vUv = uv;
  64252. vec4 worldPosition = modelMatrix * vec4(position, 1.0);
  64253. vec3 positionLocalToPanoCenter0 = worldPosition.xyz - pano0Position;
  64254. vWorldPosition0 = (vec4(positionLocalToPanoCenter0, 1.0) * pano0Matrix).xyz;
  64255. vWorldPosition0.x *= -1.0;
  64256. vWorldPosition0 = transformAxis(vWorldPosition0);
  64257. vec3 positionLocalToPanoCenter1 = worldPosition.xyz - pano1Position;
  64258. vWorldPosition1 = (vec4(positionLocalToPanoCenter1, 1.0) * pano1Matrix).xyz;
  64259. vWorldPosition1.x *= -1.0;
  64260. vWorldPosition1 = transformAxis(vWorldPosition1);
  64261. /*
  64262. vec3 positionLocalToPanoCenter12 = worldPosition.xyz - pano1Position;
  64263. vWorldPosition12 = (vec4(positionLocalToPanoCenter12, 1.0) * pano1Matrix2).xyz;
  64264. vWorldPosition12.x *= -1.0;
  64265. vWorldPosition12 = transformAxis(vWorldPosition12);
  64266. */
  64267. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  64268. }
  64269. `,
  64270. fragmentShader: prefixFragment + `
  64271. #extension GL_EXT_frag_depth : enable
  64272. #define PI 3.141592653
  64273. uniform float modelAlpha;
  64274. uniform float opacity;
  64275. uniform float progress;
  64276. uniform int blackout;
  64277. uniform vec3 pano0Position;
  64278. uniform vec3 pano1Position;
  64279. uniform float maxDistance;
  64280. uniform float minDistance;
  64281. uniform float minOpa;
  64282. uniform sampler2D pano0Map;
  64283. uniform sampler2D pano1Map;
  64284. /* uniform samplerCube pano0Map;
  64285. uniform samplerCube pano1Map;*/
  64286. varying vec2 vUv;
  64287. varying vec3 vWorldPosition0;
  64288. varying vec3 vWorldPosition1;
  64289. //varying vec3 vWorldPosition12;
  64290. /* vec2 getSamplerCoord( vec3 direction )
  64291. {
  64292. direction = normalize(direction);
  64293. float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;
  64294. float ty=acos(direction.z)/PI;
  64295. return vec2(tx,ty);
  64296. } */
  64297. vec2 getSamplerCoord2( vec3 direction )
  64298. {
  64299. direction = normalize(direction);
  64300. float tx=atan(direction.x,direction.z)/(PI*2.0)+0.5;
  64301. float ty=acos(direction.y)/PI;
  64302. return vec2(tx,ty);
  64303. }
  64304. #if defined(GL_EXT_frag_depth) && defined(hasDepthTex)
  64305. uniform sampler2D depthMap0;
  64306. uniform sampler2D depthMap1;
  64307. uniform mat4 inverseProjectionMatrix;
  64308. uniform mat4 projectionMatrix;
  64309. uniform vec4 viewport;
  64310. uniform float cameraHeight0;
  64311. uniform float cameraHeight1;
  64312. uniform float ceilHeight0;
  64313. uniform float ceilHeight1;
  64314. vec2 getDepth(vec3 dir, sampler2D depthMap, float heightDown, float heightUp, vec4 eyePos){
  64315. vec2 depthValue = vec2(0.0, 0.0);
  64316. vec2 uv2 = getSamplerCoord2( dir.xyz); //暂时只用基于目标漫游点的方向
  64317. uv2.x -= 0.25; //全景图和Cube的水平采样起始坐标相差90度,这里矫正 0.25 个采样偏移
  64318. vec4 depth = texture2D(depthMap, uv2);
  64319. //float distance = depth.r + 256. * (depth.g + 256. * depth.b);
  64320. //distance *= 255. * .001; // distance is now in meters
  64321. //更改
  64322. float distance = (depth.g + depth.r / 256.) * 255.; //为什么要乘以255
  64323. if(distance == 0.0){//漫游点底部识别不到的区域,给一个地板高度
  64324. if(uv2.y < depthTexUVyLimit) distance = heightUp / dir.y;
  64325. else if(uv2.y > 1.0 - depthTexUVyLimit) distance = heightDown / -dir.y;
  64326. else distance = 100000.0;//给个超级远的值
  64327. }
  64328. if(distance == 0.0)distance = 100000.0;//给个超级远的值
  64329. depthValue.x = distance;
  64330. // return r[1] + r[0] / 256
  64331. distance += .1; // add a safety margin
  64332. vec4 eyePos2 = vec4(normalize(eyePos.xyz) * distance, 1.);
  64333. vec4 clipPos2 = projectionMatrix * eyePos2;
  64334. vec4 ndcPos2 = clipPos2 * 1. / clipPos2.w;
  64335. depthValue.y = 0.5 * ((gl_DepthRange.far - gl_DepthRange.near) * ndcPos2.z
  64336. + gl_DepthRange.near + gl_DepthRange.far);
  64337. return depthValue;
  64338. }
  64339. //注:未加载好的话,depth为0,导致第一次漫游过去的时候许多mesh会立刻被遮挡,所以要确保加载完
  64340. #endif
  64341. void main()
  64342. {
  64343. vec3 vWorldPosition0N;
  64344. vec4 colorFromPano0 = vec4(0.0,0.0,0.0,0.0);
  64345. if(progress < 1.0){//通常是1
  64346. vWorldPosition0N = normalize(vWorldPosition0);
  64347. vec3 vWorldPosition0N = normalize(vWorldPosition0);
  64348. vec2 samplerCoord0 = getSamplerCoord2(vWorldPosition0N.xyz);
  64349. colorFromPano0 = texture2D(pano0Map,samplerCoord0);
  64350. }
  64351. vec3 vWorldPosition1N = normalize(vWorldPosition1);
  64352. vec2 samplerCoord1 = getSamplerCoord2(vWorldPosition1N.xyz);
  64353. vec4 colorFromPano1 = texture2D(pano1Map,samplerCoord1);
  64354. gl_FragColor=mix(colorFromPano0,colorFromPano1,progress);
  64355. //深度图修改深度
  64356. #if defined(GL_EXT_frag_depth) && defined(hasDepthTex)
  64357. vec4 ndcPos;
  64358. ndcPos.xy = ((2.0 * gl_FragCoord.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1.;
  64359. ndcPos.z = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
  64360. (gl_DepthRange.far - gl_DepthRange.near);
  64361. ndcPos.w = 1.0;
  64362. vec4 clipPos = ndcPos / gl_FragCoord.w;
  64363. vec4 eyePos = inverseProjectionMatrix * clipPos;
  64364. vec2 depth0 = vec2(0.0,0.0);
  64365. if(progress < 1.0){
  64366. depth0 = getDepth(vWorldPosition0N, depthMap0, cameraHeight0, ceilHeight0, eyePos);
  64367. }
  64368. vec2 depth1 = getDepth(vWorldPosition1N, depthMap1, cameraHeight1, ceilHeight1, eyePos);
  64369. /* if(progress < 1.0 && depth1.x == 0.0 && depth0.x > 0.0){
  64370. gl_FragDepthEXT = depth0.y;
  64371. }else{ */
  64372. gl_FragDepthEXT = mix(depth0.y,depth1.y,progress);
  64373. //}
  64374. gl_FragDepthEXT = clamp(gl_FragDepthEXT, 0.0, 1.0); //防止部分手机出现黑块。ios 16 。 因为我给的超远值超出范围
  64375. #endif
  64376. }
  64377. `
  64378. };
  64379. //注:gl_FragDepthEXT 修改了确实能像真实mesh那样遮挡住在后面的物体。但是为过渡时不能直接像有模型那样,和角度有关。
  64380. class ModelTextureMaterial extends RawShaderMaterial {
  64381. constructor( ){
  64382. let defines = {depthTexUVyLimit: Potree.config.depthTexUVyLimit};
  64383. super({
  64384. fragmentShader: shader.fragmentShader,
  64385. vertexShader: shader.vertexShader,
  64386. uniforms: UniformsUtils.clone(shader.uniforms),
  64387. side:DoubleSide,
  64388. name: "ModelTextureMaterial",
  64389. defines
  64390. });
  64391. let setSize = (e)=>{
  64392. let viewport = e.viewport;
  64393. //let viewportOffset = viewport.offset || new Vector2()
  64394. let resolution = viewport.resolution2;
  64395. //this.uniforms.viewport.value.set(viewportOffset.x, viewportOffset.y, resolution.x, resolution.y)
  64396. this.uniforms.viewport.value.set(0,0, resolution.x, resolution.y);// xy是在viewport中的left和bottom,和整个窗口没有关系,所以不是viewportOffset。几乎都是0,0
  64397. };
  64398. let viewport = viewer.mainViewport;
  64399. setSize({viewport});
  64400. viewer.addEventListener('resize',(e)=>{
  64401. if(e.viewport.name != "MainView")return
  64402. setSize(e);
  64403. });
  64404. //var supportExtDepth = !!Features.EXT_DEPTH.isSupported()
  64405. {
  64406. //add
  64407. viewer.addEventListener('camera_changed', (e)=>{
  64408. if(e.viewport.name != "MainView")return
  64409. //this.uniforms.projectionMatrix.value.copy(e.camera.projectionMatrix)
  64410. e.camera && this.uniforms.inverseProjectionMatrix.value.copy(e.camera.projectionMatrixInverse);
  64411. });
  64412. }
  64413. //-------------------------------------
  64414. }
  64415. /**
  64416. *
  64417. * @param {Panorama} pano0
  64418. * @param {Panorama} pano1
  64419. * @param {boolean} flag
  64420. 更新全景图的材质uniforms
  64421. */
  64422. setProjectedPanos(pano0, pano1, progressValue ){
  64423. progressValue!=void 0 && (this.uniforms.progress.value = progressValue);
  64424. //pano0.ensureSkyboxReadyForRender();
  64425. if(pano0){
  64426. this.uniforms.pano0Map.value = pano0.entered ? pano0.skyboxTex : null;
  64427. this.uniforms.pano0Position.value.copy(pano0.position);
  64428. this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix/* pano0.mesh.matrixWorld */ );
  64429. }
  64430. this.uniforms.pano1Map.value = pano1.skyboxTex;
  64431. this.uniforms.pano1Position.value.copy(pano1.position);
  64432. this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix /* pano1.mesh.matrixWorld */ );
  64433. this.pano0 = pano0;
  64434. this.pano1 = pano1;
  64435. this.updateDepthTex(pano0);
  64436. this.updateDepthTex(pano1);
  64437. //console.log('setProjectedPanos', pano0&&pano0.id, pano1&&pano1.id)
  64438. this.needsUpdate = true;
  64439. }
  64440. updateDepthTex(pano, extra){
  64441. if( !Potree.settings.useDepthTex || !pano || !pano.depthTex || pano!=this.pano0 && pano!=this.pano1)return
  64442. //console.log('updateDepthTex', pano.id, this.pano0 && this.pano0.id, this.pano1 && this.pano1.id)
  64443. if(this.pano0){
  64444. this.uniforms.depthMap0.value = this.pano0.entered ? this.pano0.depthTex : null; //dispose了就不要赋值否则dispose会失败
  64445. this.uniforms.cameraHeight0.value = this.pano0.floorPosition.distanceTo(this.pano0.position);
  64446. this.uniforms.ceilHeight0.value = this.pano0.getCeilHeight() - this.pano0.position.z;
  64447. }
  64448. if(this.pano1){
  64449. this.uniforms.depthMap1.value = this.pano1.depthTex;
  64450. this.uniforms.cameraHeight1.value = this.pano1.floorPosition.distanceTo(this.pano1.position);
  64451. this.uniforms.ceilHeight1.value = this.pano1.getCeilHeight() - this.pano1.position.z;
  64452. }
  64453. this.updateDepthTexEnable();
  64454. }
  64455. updateDepthTexEnable(){
  64456. let hasDepthTex = this.pano0 && this.pano1 && this.pano0.pointcloud.hasDepthTex && this.pano1.pointcloud.hasDepthTex; //暂时不知道一个有图一个没图怎么写所以
  64457. Potree.Utils.addOrRemoveDefine(this, 'hasDepthTex', hasDepthTex?'add':'remove' );
  64458. }
  64459. /* EnableDepthTex(){//开启DepthTex
  64460. if(this.defines['hasDepthTex']){
  64461. return
  64462. }
  64463. this.defines['hasDepthTex'] = ''
  64464. this.needsUpdate = true;
  64465. } */
  64466. }
  64467. let { PanoramaEvents } = Potree.defines;
  64468. var texLoader$4 = new TextureLoader();
  64469. const markerOpacitys ={
  64470. default : 0.5,
  64471. hovered : 1,
  64472. };
  64473. const labelProp = {
  64474. sizeInfo: {minSize : 200 , maxSize : 250, nearBound : 0.8, farBound : 10},
  64475. backgroundColor:{r: 255, g: 255, b: 255, a: 0.4 },
  64476. textColor:{r: 0, g: 0, b: 0, a: 1 },
  64477. borderRadius: 15,
  64478. renderOrder:10,
  64479. useDepth:true,
  64480. clipDistance: 30, maxClipFactor:0.3, occlusionDistance:3,
  64481. };
  64482. const labelProp2 = {
  64483. //sizeInfo: {minSize : 200 , maxSize : 250, nearBound : 0.8, farBound : 10},
  64484. backgroundColor:{r: 255, g: 255, b: 255, a: 0 },
  64485. textColor:{r:255 , g: 255, b: 255, a: 1 },
  64486. textBorderColor:{r:30 , g:30, b: 30, a: 1 },
  64487. textBorderThick:3,
  64488. dontFixOrient:true,
  64489. renderOrder:10,
  64490. fontsize:30,
  64491. };
  64492. let markerTex;
  64493. //显示全景图时marker没有被遮挡,如果需要,要换成depthBasicMaterial 或者直接把skybox的深度修改(拿到深度贴图后更如此)
  64494. let planeGeo$1 = new PlaneBufferGeometry(0.2,0.2);
  64495. let sg = new SphereGeometry(0.1, 8, 8);
  64496. let smHovered = new MeshBasicMaterial({/* side: THREE.BackSide, */color: 0xff0000});
  64497. let sm = new MeshBasicMaterial({/* side: THREE.BackSide */});
  64498. var rot90 = new Quaternion().setFromAxisAngle(new Vector3(0,0,1), Math.PI/2 ); //使用的是刚好适合全景图的,给cube贴图需要转90°
  64499. //var rot90 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0), -Math.PI/2 ); //4dkk->navvis
  64500. //var rot901 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,1,0), -Math.PI/2 ); //整张球幕图要旋转下
  64501. //rot90 = new THREE.Quaternion().multiplyQuaternions( rot901, rot90)
  64502. var old = null;
  64503. /*
  64504. 转成四维看看的axis:
  64505. var a = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), THREE.Math.degToRad(-90)) 因为四维的要绕y转90
  64506. 这里的quaternion.multiply(a);
  64507. 先乘再换顺序 w : q.w, x:q.x , y:-q.z, z:q.y
  64508. */
  64509. //暂时直接用4dkkconsole输出的数据
  64510. class Panorama extends EventDispatcher{
  64511. constructor(o, images360){//file, time, longitude, latitude, altitude, course, pitch, roll
  64512. super();
  64513. this.id = o.id; //唯一标识
  64514. this.images360 = images360;
  64515. this.visible = true; //for updateVisible
  64516. this.enabled = true;//是否可以走
  64517. this.addEventListener('isVisible',(e)=>{//是否显示该点的mesh(不显示也能走)
  64518. //console.log('pano isVisible', this.id, e.visible)
  64519. Potree.Utils.updateVisible(this.marker, 'panoVisi', e.visible);
  64520. Potree.settings.showPanoMesh && (this.mesh.visible = e.visible);
  64521. if(e.reason == 'screenshot' || e.visible){
  64522. this.label && (this.label.visible = e.visible);//截图时隐藏下
  64523. }
  64524. this.label2 && Potree.Utils.updateVisible(this.label2, 'panoVisi', e.visible);
  64525. });
  64526. /*
  64527. 漫游点可见性:旧
  64528. level reason 类型
  64529. 2(最高)buildingChange(不在此楼层) unvisible
  64530. 1 modeIsShowPanos(漫游模式) visible //不记得为什么加这个了,所以重写
  64531. 0 pointcloudVisi(隐藏了数据集) unvisible
  64532. */
  64533. /*
  64534. 漫游点可见性:新
  64535. level reason 类型
  64536. 2(最高)buildingChange(不在此楼层) unvisible
  64537. 1 ifShowMarker(marker显示开关) unvisible
  64538. 0 pointcloudVisi(隐藏了数据集) unvisible
  64539. */
  64540. this.panosData = o;
  64541. this.originPosition = new Vector3().copy(o.pose.translation);
  64542. this.originFloorPosition = new Vector3().copy(o.puck);
  64543. this.originID = parseInt(o.uuid);//id uuid "file_id":"00022"对应是原本的4dkk的id --来自vision.txt
  64544. this.pointcloud = viewer.scene.pointclouds[0];
  64545. this.pointcloud.panos.push(this);
  64546. //this.sid = this.pointcloud.sceneCode + '|' + this.originID //不会更改的标记
  64547. this.sid = this.originID; //不会更改的标记
  64548. //全景图和Cube的水平采样起始坐标相差90度
  64549. /* if(from4dkk){
  64550. var qua = o.dataset_orientation
  64551. var quaternion = new THREE.Quaternion().fromArray(qua)
  64552. quaternion = new THREE.Quaternion().multiplyQuaternions(quaternion, rot901);//整张球幕图要旋转下 因为在4dkk里转过,还原。如果是tiles的不用
  64553. this.quaternion = new THREE.Quaternion(quaternion.x, -quaternion.z, quaternion.y, quaternion.w) //转化坐标
  64554. }else{ */
  64555. this.quaternion = new Quaternion().copy(o.pose.rotation);
  64556. this.quaternion4dkk = math.convertVisionQuaternion(this.quaternion);//4dkk内使用的quaternion
  64557. this.quaternion2 = this.quaternion.clone();
  64558. //this.quaternion = new THREE.Quaternion().multiplyQuaternions(this.quaternion, rot90);//全景图和Cube的水平采样起始坐标相差90度,cubeTex转90度
  64559. this.rotation4dkk = new Euler().setFromQuaternion(this.quaternion4dkk);
  64560. //}
  64561. //this.quaternion1 = Potree.Utils.QuaternionFactory.fromArray(o.dataset_orientation)
  64562. //同quaternion
  64563. //let xy = this.transform.forward([this.longitude, this.latitude]);
  64564. //this.file = `https://4dkk.4dage.com/images/images${Potree.settings.number}/pan/high/${this.id}.jpg`
  64565. this.neighbours = [];
  64566. this.rotation = new Euler().setFromQuaternion(this.quaternion);
  64567. this.build();
  64568. this.setPosition(this.originPosition, this.originFloorPosition );//this.transformByPointcloud() //初始化位移
  64569. this.addEventListener('hoverOn', (e)=>{//from Map
  64570. if(!e.byMainView){
  64571. this.hoverOn(e);
  64572. }
  64573. });
  64574. this.addEventListener('hoverOff', (e)=>{
  64575. if(!e.byMainView){
  64576. this.hoverOff(e);
  64577. }
  64578. });
  64579. }
  64580. get noNeighbour(){//是否绝对到不到的孤立点
  64581. for(let i=0,j=this.images360.panos.length; i<j; i++){
  64582. if(this.images360.neighbourMap[this.id][i] !== false ){
  64583. return false
  64584. }
  64585. }
  64586. return true
  64587. //return this.neighbours.length == 0
  64588. }
  64589. setEnable(enable){//是否可以走
  64590. Potree.Utils.updateVisible(this, 'isEnabled', enable); //令所有marker不可见
  64591. this.enabled = enable;
  64592. //如果当前在全景模式且在这个点,需要切换显示吗? 目前用不到
  64593. }
  64594. waitForLoad(){
  64595. viewer.waitForLoad(this, ()=>{//发送loading
  64596. return this.depthTex && this.skyboxTex
  64597. });
  64598. }
  64599. loadTex(){
  64600. if(this.skyboxTex || this.texLoading)return
  64601. this.texLoading = true;
  64602. let src = `${Potree.settings.urls.prefix1}/images/${this.originID}.jpg`; //`server\test\SS-t-P1d6CwREny2\${this.id}.jpg` //`${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${this.pointcloud.sceneCode}/data/${this.pointcloud.sceneCode}/depthmap/${this.originID}.png`
  64603. //console.log('开始下载depthImg', this.id)
  64604. let startLoad = (src)=>{
  64605. let texture = texLoader$4.load( src, ()=>{
  64606. this.skyboxTex = texture;
  64607. this.dispatchEvent({type:'loadedTex', loaded:true});
  64608. this.depthTexLoading = false;
  64609. //viewer.dispatchEvent('content_changed')
  64610. },null,(e)=>{//error
  64611. console.error('loadTex失败, 数据集sceneCode'+ this.pointcloud.sceneCode, this.id );
  64612. this.dispatchEvent({type:'loadedTex', });
  64613. });
  64614. texture.wrapS = RepeatWrapping;
  64615. texture.flipY = false;
  64616. texture.magFilter = LinearFilter;
  64617. texture.minFilter = LinearFilter; //防止边缘竖线
  64618. texture.generateMipmaps = false;
  64619. };
  64620. Potree.getRealUrl(src, startLoad);
  64621. }
  64622. loadDepthImg(){
  64623. if(!this.pointcloud.hasDepthTex || this.depthTex || this.depthTexLoading)return
  64624. this.depthTexLoading = true;
  64625. let src = //Potree.settings.number == 'SS-t-7DUfWAUZ3V' ? `${Potree.scriptPath}/data/${Potree.settings.number}/depthMap/${this.originID}.png` :
  64626. //`${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${this.pointcloud.sceneCode}/data/${this.pointcloud.sceneCode}/depthmap/${this.originID}.png`
  64627. `${Potree.settings.urls.prefix1}/depthmap/${this.originID}.png`;
  64628. //console.log('开始下载depthImg', this.id)
  64629. let startLoad = (src)=>{
  64630. let texture = texLoader$4.load( src, ()=>{
  64631. this.depthTex = texture;
  64632. this.dispatchEvent({type:'loadedDepthImg', pano:this, loaded:true});
  64633. this.depthTexLoading = false;
  64634. this.images360.updateDepthTex(this);
  64635. //viewer.dispatchEvent('content_changed')
  64636. },null,(e)=>{//error
  64637. console.error('loadDepthImg失败, 数据集sceneCode'+ this.pointcloud.sceneCode, this.id );
  64638. this.pointcloud.hasDepthTex = false;
  64639. this.dispatchEvent({type:'loadedDepthImg', pano:this, });
  64640. });
  64641. texture.wrapS = RepeatWrapping;
  64642. texture.flipY = false;
  64643. texture.magFilter = LinearFilter;
  64644. texture.minFilter = LinearFilter;
  64645. texture.generateMipmaps = false;
  64646. };
  64647. Potree.getRealUrl(src, startLoad);
  64648. }
  64649. build(){
  64650. { // orientation
  64651. //add
  64652. //var quaternion = new THREE.Quaternion().multiplyQuaternions(this.quaternion, rot901);//改 为球目全
  64653. //quaternion.premultiply(rot90)
  64654. this.panoMatrix = new Matrix4().makeRotationFromQuaternion(this.quaternion);
  64655. //this.oriPanoMatrix = this.panoMatrix.clone()
  64656. //if(this.quaternion2)this.oriPanoMatrix2 = new THREE.Matrix4().makeRotationFromQuaternion(this.quaternion2)
  64657. //补:全景图下和原来的一样
  64658. this.panoMatrix2 = this.panoMatrix;
  64659. this.panoMatrix2Inverse = this.panoMatrix2.clone().invert();
  64660. }
  64661. let marker = new Mesh(planeGeo$1, this.getMarkerMat() );
  64662. marker.name = 'marker_'+this.id;
  64663. marker.up.set(0,0,1);
  64664. marker.lookAt(marker.up);
  64665. marker.scale.set(2,2,2);
  64666. this.addEventListener('changeMarkerTex',(e)=>{
  64667. marker.material.map = markerTex[e.name];
  64668. });
  64669. this.marker = marker;
  64670. this.images360.node.add(marker);
  64671. //Potree.settings.isTest && this.addLabel()
  64672. this.addLabel2();
  64673. marker.addEventListener('mouseover', this.hoverOn.bind(this));
  64674. marker.addEventListener('mouseleave', this.hoverOff.bind(this));
  64675. }
  64676. /* transformByPointcloud(){
  64677. let position = this.originPosition.clone().applyMatrix4(this.pointcloud.transformMatrix);//也可以用datasetPosTransform算
  64678. let floorPosition = this.originFloorPosition.clone().applyMatrix4(this.pointcloud.transformMatrix);
  64679. this.setPosition(position, floorPosition)
  64680. this.panoMatrix = new THREE.Matrix4().multiplyMatrices(this.pointcloud.rotateMatrix, this.oriPanoMatrix )
  64681. //this.panoMatrix2 = Potree.Utils.datasetRotTransform({fromDataset:true, pointcloud:this.pointcloud, matrix:this.oriPanoMatrix, getMatrix:true}) //和上一行结果一样
  64682. //quaternion也变下
  64683. if(this.oriPanoMatrix2){
  64684. this.panoMatrix2 = new THREE.Matrix4().multiplyMatrices(this.pointcloud.rotateMatrix, this.oriPanoMatrix2 )//供DepthImageSampler使用
  64685. this.panoMatrix2Inverse = this.panoMatrix2.clone().invert();
  64686. }
  64687. this.dispatchEvent('rePos')
  64688. } */
  64689. setPosition(position, floorPosition){
  64690. this.position = position;
  64691. this.floorPosition = floorPosition;
  64692. //this.mesh.position.copy(this.position)
  64693. this.marker.position.copy(this.floorPosition);
  64694. this.marker.position.z+=0.04;//会被点云遮住
  64695. if(this.label){
  64696. if(Potree.settings.editType == 'pano'){
  64697. this.label.position.copy(this.position);
  64698. }else {
  64699. this.label.position.copy(this.floorPosition);
  64700. }
  64701. this.label.position.z+=0.14;
  64702. this.label.update();
  64703. }
  64704. if(this.label2){
  64705. if(Potree.settings.editType == 'pano'){
  64706. this.label2.position.copy(this.position);
  64707. }else {
  64708. this.label2.position.copy(this.floorPosition);
  64709. }
  64710. this.label2.position.copy(this.marker.position);
  64711. this.label2.update();
  64712. }
  64713. }
  64714. getMarkerMat(){
  64715. if(!markerTex) {
  64716. markerTex = {
  64717. //default:texLoader.load( Potree.resourcePath+'/textures/marker.png' ),
  64718. ring:texLoader$4.load( Potree.resourcePath+'/textures/marker2.png' )
  64719. };
  64720. //markerTex.default.anisotropy = 4 // 各向异性过滤 .防止倾斜模糊
  64721. markerTex.ring.anisotropy = 4;
  64722. //有可能被点云遮住吗。
  64723. }
  64724. return new DepthBasicMaterial({opacity: markerOpacitys.default, side: DoubleSide , map:markerTex.ring/* .default */ ,transparent:true,
  64725. clipDistance: 2, occlusionDistance:1, //不能设置太短,因为过渡时深度不准确
  64726. useDepth: !!(Potree.settings.useDepthTex && this.pointcloud.hasDepthTex),
  64727. autoDepthTest:true
  64728. //改为DepthBasicMaterial是因为原Basic的材质在有深度图时过渡会先隐藏后出现。 注:没有深度图时全景模式的marker无法遮挡
  64729. })
  64730. }
  64731. hoverOn(e={}) {
  64732. //console.log("hoverOn " + this.id )
  64733. transitions.start(lerp.property(this.marker.material, "opacity", markerOpacitys.hovered,()=>{
  64734. viewer.dispatchEvent('content_changed');
  64735. }), this.marker.visible ? 250 : 0);
  64736. if(!e.byMap) this.dispatchEvent({type:'hoverOn', byMainView:true});
  64737. if(!e.byImages360) this.images360.dispatchEvent({type:'markerHover', hovered:true, pano:this});
  64738. }
  64739. hoverOff(e={}){
  64740. //console.log("hoverOff " + this.id )
  64741. transitions.start(lerp.property(this.marker.material, "opacity", markerOpacitys.default,()=>{
  64742. viewer.dispatchEvent('content_changed');
  64743. }), this.marker.visible ? 250 : 0);
  64744. if(!e.byMap) this.dispatchEvent({type:'hoverOff', byMainView:true});
  64745. if(!e.byImages360) this.images360.dispatchEvent({type:'markerHover', hovered:false, pano:this});
  64746. }
  64747. enter(){
  64748. this.entered = true;
  64749. viewer.dispatchEvent({type:PanoramaEvents.Enter, oldPano:old, newPano:this } );
  64750. old = this;
  64751. //console.log("enter pano "+ this.id)
  64752. }
  64753. exit(){
  64754. this.skyboxTex && this.skyboxTex.dispose();
  64755. this.depthTex && this.depthTex.dispose(); //贴图不使用后先dispose,下次到该点时会自动还原
  64756. this.entered = false; //add
  64757. viewer.dispatchEvent({type:PanoramaEvents.Exit, pano:this});
  64758. }
  64759. addLabel(){
  64760. this.removeTextLabel();
  64761. this.label = new TextSprite$2(Object.assign({},
  64762. labelProp, {text: this.id + "("+this.originID+")"}) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
  64763. );
  64764. this.images360.node.add(this.label);
  64765. this.floorPosition && this.label.position.copy(this.floorPosition);
  64766. }
  64767. addLabel2(){
  64768. if(this.label2)return
  64769. this.label2 = new TextSprite$2(Object.assign({},
  64770. labelProp2, {text: /* this.originID */ parseInt(this.id)+1 }) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
  64771. );
  64772. this.images360.node.add(this.label2);
  64773. this.floorPosition && this.label2.position.copy(this.floorPosition);
  64774. let s = 0.4;
  64775. this.label2.scale.set(s,s,s);
  64776. //Potree.Utils.updateVisible(this.label2, 'notDisplay', false)
  64777. Potree.Utils.updateVisible(this.label2, 'panoVisi', this.visible);
  64778. }
  64779. removeTextLabel(){
  64780. if(this.label){
  64781. this.label.parent.remove(this.label);
  64782. }
  64783. }
  64784. getCeilHeight(){//天花板高度值 (假设不存在depth为0的点,所有为0的要么是在盲区,要么是无穷远。)
  64785. if(this.ceilZ == void 0){
  64786. const depthTiming = Potree.timeCollect.depthSampler.median; //pc firefox达到4. chrome为0.01
  64787. //用三个间隔120度散开,和中心垂直线成一定夹角的三个向量去求 最高高度 (不求平均的原因:万一是0不好算)
  64788. let rotMat = new Matrix4().makeRotationX((Potree.config.depthTexUVyLimit+0.01)*Math.PI);// 角度不能小于天花板中空的半径
  64789. let dirs = [new Vector3(0,0,1).applyMatrix4(rotMat)];
  64790. if(depthTiming < 1){
  64791. let rotMat1 = new Matrix4().makeRotationZ(Math.PI*2 / 3);
  64792. dirs.push(dirs[0].clone().applyMatrix4(rotMat1));
  64793. }
  64794. if(depthTiming < 0.3){
  64795. let rotMat2 = new Matrix4().makeRotationZ(-Math.PI*2 / 3);
  64796. dirs.push(dirs[0].clone().applyMatrix4(rotMat2));
  64797. }
  64798. let zs = dirs.map(dir_=>{
  64799. let dir = dir_.clone().applyMatrix4(this.panoMatrix2); //pano不一定是垂直的, 需要把之前的dirInPano先转成真实的dir,防止超出角度限制
  64800. let intersect = viewer.images360.getIntersect(this, dir);
  64801. let z = intersect ? intersect.location.z : Infinity;/* this.position.z+skyHeight */ //没有intersect代表可能是天空
  64802. return z
  64803. });
  64804. zs.sort((a,b)=>{return b-a});//得最大值 (不用中位数的原因:在屋檐处,如果仅有一个intersect是天空,因到了室外所以也用天空高度)
  64805. this.ceilZ = zs[0];
  64806. let min = this.position.z + 1; // 防止意外太低
  64807. this.ceilZ = Math.max(min, this.ceilZ);
  64808. //console.log(this.id, 'ceilZ:', this.ceilZ )
  64809. }
  64810. return this.ceilZ
  64811. }
  64812. };
  64813. class DepthImageSampler extends EventDispatcher{
  64814. constructor(){
  64815. super();
  64816. var canvas = document.createElement("canvas");
  64817. this.canvas = canvas;
  64818. this.context = canvas.getContext("2d");
  64819. this.imgDatas = [];
  64820. /* document.getElementsByTagName('body')[0].appendChild(canvas);
  64821. canvas.style.position = 'fixed';
  64822. canvas.style.width = '1024px';
  64823. canvas.style.top = canvas.style.left = 0
  64824. canvas.style['z-index'] = 100
  64825. */
  64826. this.maxDataCount = browser.isMobile() ? 6 : 20; //手机会崩溃. 平均每张图为8M数据量(以200个点的园区为例,加载时间久一些后,总内存=700 + 每张图的8M * maxDataCount)
  64827. this.maxNeighCount = browser.isMobile() ? 3 : 14; //包含在maxDataCount内的nearPanos最大个数.至少比maxDataCount少3个,留出空位给最近更新的pano
  64828. this.nearPanos = [];
  64829. }
  64830. updateNearPanos(panos){
  64831. this.nearPanos = panos.slice(0,this.maxNeighCount);
  64832. }
  64833. changeImg(img, pano){
  64834. this.pano = pano;
  64835. let item = this.imgDatas.find(p=>p.pano == pano);
  64836. if(/* this.img == img || */item){
  64837. //最新的在末尾,所以换到末尾
  64838. let index = this.imgDatas.indexOf(item);
  64839. this.imgDatas.splice(index,1);
  64840. this.imgDatas.push(item);
  64841. //console.log('重复使用',item.pano.id)
  64842. return
  64843. }
  64844. viewer.addTimeMark('depthSampler','start');
  64845. this.canvas.width = img.width;
  64846. this.canvas.height = img.height;
  64847. this.context.drawImage(img, 0, 0);
  64848. let data = this.context.getImageData(0, 0, img.width , img.height ).data; //getImageData 1px时 : pc chrome 耗时0.01毫秒左右(排除第一次的50) , 但firefox: 4。但换贴图之后就多达5甚至几十
  64849. //console.log('changeImg',pano.id )
  64850. //this.img = img
  64851. if(this.imgDatas.length >= this.maxDataCount){
  64852. let old = this.imgDatas.find(e=>!this.nearPanos.includes(e.pano));
  64853. //console.log('推出',old.pano.id)
  64854. this.imgDatas.splice(this.imgDatas.indexOf(old), 1);//推出使用时间最早的一个非nearPano
  64855. }
  64856. this.imgDatas.push({pano, data});
  64857. this.dispatchEvent({type:'changeImg',pano});
  64858. viewer.addTimeMark('depthSampler','end'); //耗时chrome 25ms,firefox: 38ms, iphoneX:33ms
  64859. /* pano.depthData = {}
  64860. for(let h=0; h<img.height; h++){
  64861. for(let w=0; w<img.width; w++){
  64862. let blockIndex = img.width * h + w
  64863. let r = data.slice(blockIndex*4, (blockIndex+1)*4)
  64864. let depth = r[1] + r[0] / 256
  64865. if(depth>0) pano.depthData[h+'|'+w] = depth
  64866. }
  64867. } */
  64868. }
  64869. getDepth( UVx, UVy) {//根据图片像素获取深度值
  64870. var x = Math.round(UVx * (this.canvas.width - 1))
  64871. , y = Math.round(UVy * (this.canvas.height - 1));
  64872. if (!(x < 0 || y < 0 || x >= this.canvas.width || y >= this.canvas.height)) {
  64873. /* viewer.addTimeMark('depthSampler','start')
  64874. var r = this.context.getImageData(x, y, 1, 1).data; //pc chrome 耗时0.01毫秒左右(排除第一次的50) , 但firefox: 4。但换贴图之后就多达5甚至几十
  64875. viewer.addTimeMark('depthSampler','end')
  64876. //console.log('color', r, x,y)
  64877. return r[1] + r[0] / 256 */
  64878. let imgData = this.imgDatas.find(p=>p.pano == this.pano);
  64879. let blockIndex = this.canvas.width * y + x;
  64880. let color = imgData.data.slice(blockIndex*4, (blockIndex+1)*4);
  64881. return color[1] + color[0] / 256
  64882. }
  64883. }
  64884. sample( intersect, currentPano, onlyPos ) {//通过和skybox的intersect得到真实的intersect的位置
  64885. if(!intersect)return
  64886. let location = new Vector3;
  64887. let normal;
  64888. currentPano = currentPano || viewer.images360.currentPano;
  64889. //let markName
  64890. if(currentPano != this.currentPano){
  64891. if(!currentPano.depthTex/* || !currentPano.depthTex.image */) return //未加载
  64892. /* markName = 'depthSampleChangeTex'
  64893. viewer.addTimeMark(markName,'start') */
  64894. this.changeImg(currentPano.depthTex.image, currentPano);
  64895. this.currentPano = currentPano;
  64896. }/* else{
  64897. markName = 'depthSampleSame'
  64898. viewer.addTimeMark(markName,'start')
  64899. } */
  64900. let origin = currentPano.position;
  64901. let dir = intersect.dir || new Vector3().subVectors(intersect.point, origin).normalize();
  64902. //var uv = intersect.uv
  64903. //let dirInPano = math.getNormalDir(dir, currentPano)//转化为考虑漫游点旋转的方向
  64904. let dirInPano = dir.clone().applyMatrix4(currentPano.panoMatrix2Inverse).normalize(); //转化为考虑漫游点旋转的方向
  64905. let uv = math.getUVfromDir(dirInPano);//转化为uv
  64906. let distance = this.getDepth( uv.x, uv.y);
  64907. //viewer.addTimeMark(markName,'end')
  64908. if (!distance){
  64909. const margin = 0.1;
  64910. if(uv.y > 1-Potree.config.depthTexUVyLimit){//漫游点底部识别不到的区域,给一个地板高度
  64911. distance = (currentPano.floorPosition.z - origin.z - margin) / dir.z;
  64912. location.copy(dir).multiplyScalar(distance).add(origin);
  64913. let normal = new Vector3(0,0,1);
  64914. return {location, normal, distance}
  64915. }else if(uv.y < Potree.config.depthTexUVyLimit){
  64916. let ceilZ = currentPano.getCeilHeight();
  64917. if(ceilZ == Infinity)return !1
  64918. else {
  64919. distance = (ceilZ - origin.z - margin) / dir.z;
  64920. location.copy(dir).multiplyScalar(distance).add(origin);
  64921. let normal = new Vector3(0,0,-1);
  64922. return {location, normal, distance}
  64923. }
  64924. }
  64925. //console.log('无穷远')
  64926. return !1; //应该是天空或模型外 , 因为很少有漫游点的地方还拍不到地板
  64927. }
  64928. //console.log('distance', distance, dirInPano.clone().multiplyScalar(distance))
  64929. location.copy(dir).multiplyScalar(distance).add(origin);
  64930. if(!onlyPos){
  64931. var pL = this.getNearbyPoint(origin, uv, -1, 0)
  64932. , pR = this.getNearbyPoint(origin, uv, 1, 0)
  64933. , pB = this.getNearbyPoint(origin, uv, 0, -1)
  64934. , pT = this.getNearbyPoint(origin, uv, 0, 1);
  64935. normal = this.planeFit(dir,location, pL,pR,pB,pT );
  64936. }
  64937. /* if(normal.x != normal.x ){
  64938. console.log('NAN', normal)
  64939. var pL = this.getNearbyPoint(origin, uv, -1, 0)
  64940. , pR = this.getNearbyPoint(origin, uv, 1, 0)
  64941. , pB = this.getNearbyPoint(origin, uv, 0, -1)
  64942. , pT = this.getNearbyPoint(origin, uv, 0, 1);
  64943. } */
  64944. //console.log(location, normal, distance)
  64945. return {location, normal, distance}
  64946. }
  64947. getNearbyPoint( origin, uv, x, y) { //获取附近的若干像素距离的点
  64948. let uv2 = uv.clone();
  64949. uv2.x += x/(this.canvas.width-1);
  64950. uv2.x = this.clampUV(uv2.x);
  64951. uv2.y += y/(this.canvas.height-1);
  64952. uv2.y = this.clampUV(uv2.y);
  64953. /* if(uv2.x < 0 || uv2.y < 0 || uv2.x > 1 || uv2.y > 1){
  64954. console.log('will nan')
  64955. } */
  64956. let dir = math.getDirFromUV(uv2);//从uv获取到方向
  64957. dir.applyMatrix4(viewer.images360.currentPano.panoMatrix2);
  64958. let depth = this.getDepth(uv2.x, uv2.y);
  64959. /* if(Math.abs(depth - this.mainDepth) > 0.3){
  64960. console.log('Math.abs(depth - this.mainDepth) > 0.3')
  64961. } */
  64962. //let dir = new THREE.Vector3().subVectors(intersect.point, origin).normalize()
  64963. let position = new Vector3().copy(dir).multiplyScalar(depth).add(origin);
  64964. //console.log('getNearbyPoint', uv2, depth, dir, position )
  64965. return position
  64966. }
  64967. clampUV(v){
  64968. return (v + 1) % 1; // 使输出在 0-1
  64969. }
  64970. planeFit(dir, position, pL,pR,pB,pT ) {//求平均法线
  64971. let normal = new Vector3;
  64972. let plane = new Plane;
  64973. function addNormal(p1, p2) {//根据临接的四个点,分别求法线,然后法线相加能得到平均法线
  64974. if(!p1 || !p2)return
  64975. plane.setFromCoplanarPoints(position, p1, p2);
  64976. //console.log('normalSub', plane.normal)
  64977. normal.addScaledVector(plane.normal, dir.dot(plane.normal) < 0 ? 1 : -1);//根据面的朝向判断加还是减
  64978. }
  64979. addNormal(pL, pB);
  64980. addNormal(pL, pT);
  64981. addNormal(pR, pB);
  64982. addNormal(pR, pT);
  64983. if(0 !== normal.x || 0 !== normal.y || 0 !== normal.z){
  64984. normal.normalize();
  64985. //console.log(normal)
  64986. return normal
  64987. }
  64988. /* 四个面拼成一个菱形 */
  64989. }
  64990. }
  64991. let {PanoSizeClass,Vectors,GLCubeFaces: GLCubeFaces$1, PanoramaEvents: PanoramaEvents$1} = Potree.defines;
  64992. var rot90$1 = new Quaternion().setFromAxisAngle(new Vector3(0,0,1), Math.PI/2 ); //使用的是刚好适合全景图的,给cube贴图需要转90°
  64993. let raycaster = new Raycaster();
  64994. //let currentlyHovered = null;
  64995. let texLoader$5 = new TextureLoader();
  64996. let tileArr = [];
  64997. let previousView = {
  64998. controls: null,
  64999. position: null,
  65000. target: null,
  65001. };
  65002. const HighMapCubeWidth = 1;
  65003. const directionFactor = 400; //原先10,几乎只往距离近的走了;设置太大容易略过近处漫游点走向下坡,因为鼠标一般在地面,下坡的漫游点更有利
  65004. class Images360 extends EventDispatcher{
  65005. constructor(viewer ){
  65006. super();
  65007. this.viewer = viewer;
  65008. this.panos = [];
  65009. this.neighbourMap = {};
  65010. this.node = new Object3D();
  65011. this.node.name = 'ImagesNode';
  65012. this.cubePanos = [];
  65013. {
  65014. this.cube = new Mesh(new BoxBufferGeometry(1,1,1,1),new ModelTextureMaterial());
  65015. Potree.Utils.updateVisible(this.cube,'showSkybox', false );
  65016. this.cube.layers.set(Potree.config.renderLayers.skybox);
  65017. this.cube.name = 'skyboxCube';
  65018. viewer.scene.scene.add(this.cube);
  65019. }
  65020. if(Potree.settings.testCube){
  65021. this.cubeTest = this.cube.clone();
  65022. this.cubeTest.material = new MeshBasicMaterial({
  65023. wireframe:true,
  65024. color:'#FF3377',
  65025. transparent:true,
  65026. opacity:0.7,
  65027. depthWrite:false,
  65028. depthTest:false,
  65029. });
  65030. viewer.scene.scene.add(this.cubeTest);
  65031. this.cubeTest.visible = true;
  65032. }
  65033. this.flying_ = false;
  65034. this.currentPano = null;
  65035. this.mouseLastMoveTime = Date.now();
  65036. this.scrollZoomSpeed = 0.06;
  65037. this.zoomLevel = 1;
  65038. this.depthSampler = new DepthImageSampler();
  65039. viewer.fpControls.addEventListener('dollyStopCauseUnable',(e)=>{
  65040. if(/* e.hoverViewport != viewer.mainViewport || */!Potree.settings.zoom.enabled)return
  65041. if(e.scale != void 0){//触屏
  65042. this.zoomBy(e.scale, e.pointer);
  65043. }else {//滚轮
  65044. let zoom;
  65045. if(e.delta > 0){
  65046. zoom = 1 + this.scrollZoomSpeed;
  65047. }else {
  65048. zoom = 1 - this.scrollZoomSpeed;
  65049. }
  65050. e.delta != 0 && this.zoomBy(zoom);
  65051. }
  65052. });
  65053. let click = (e) => {//不用"mouseup" 是因为 mouseup有drag object时也会触发
  65054. if(e.clickElement ||
  65055. Potree.settings.unableNavigate || this.flying || !e.isTouch && e.button != MOUSE.LEFT || e.drag && e.drag.object //拖拽结束时不算
  65056. || Potree.settings.editType == 'pano' && viewer.modules.PanoEditor.activeViewName != 'mainView'
  65057. || Potree.settings.editType == 'merge' && !e.intersectPoint || viewer.inputHandler.hoveredElements[0] && viewer.inputHandler.hoveredElements[0].isModel && e.intersectPoint.distance > viewer.inputHandler.hoveredElements[0].distance
  65058. || e.hoverViewport != viewer.mainViewport //如数据集校准其他viewport
  65059. || viewer.mainViewport.camera.type == 'OrthographicCamera' //暂时不支持
  65060. ) return
  65061. if(!Potree.settings.dblToFocusPoint/* && this.currentPano */){//双击不会focus点云 或者 已经focusPano了
  65062. this.flyToPanoClosestToMouse();
  65063. }
  65064. };
  65065. viewer.addEventListener('global_click' , click);
  65066. viewer.addEventListener("global_mousemove", (e) => {
  65067. if(!Potree.settings.unableNavigate && Potree.settings.ifShowMarker && e.hoverViewport == viewer.mainViewport){//如果不显示marker,就在点击时再更新
  65068. this.updateClosestPano(e.intersect);
  65069. }
  65070. });
  65071. this.addEventListener('markerHover',(e)=>{
  65072. this.updateClosestPano(e.pano, e.hovered);
  65073. });
  65074. if(!Potree.settings.isOfficial){
  65075. this.domRoot = viewer.renderer.domElement.parentElement;
  65076. let elUnfocus = $("<input type='button' value='unfocus'></input>");
  65077. elUnfocus.css({
  65078. position : "absolute",
  65079. right : '25%',
  65080. bottom: '20px',
  65081. zIndex: "10000",
  65082. fontSize:'1em', color:"black",
  65083. display:'none',
  65084. background:'rgba(255,255,255,0.8)',
  65085. });
  65086. elUnfocus.on("click", () => this.unfocus());
  65087. this.elUnfocus = elUnfocus;
  65088. this.domRoot.appendChild(elUnfocus[0]);
  65089. if(Potree.settings.editType != 'merge'){
  65090. let elHide = $("<input type='button' value='隐藏点云'></input>");
  65091. elHide.css({
  65092. position : "absolute",
  65093. right : '40%',
  65094. bottom: '20px',
  65095. zIndex: "10000",
  65096. fontSize:'1em' ,color:"black",
  65097. width : '100px',
  65098. background:'rgba(255,255,255,0.8)',
  65099. });
  65100. this.domRoot.appendChild(elHide[0]);
  65101. elHide.on("click", (e) => {
  65102. let visi = Potree.Utils.getObjVisiByReason(viewer.scene.pointclouds[0], 'force');
  65103. viewer.scene.pointclouds.forEach(e=>{
  65104. Potree.Utils.updateVisible(e, 'force', !visi);
  65105. });
  65106. elHide.val(!visi ? "隐藏点云" : "显示点云");
  65107. });
  65108. }
  65109. let elDisplayModel = $("<input type='button' value='>>全景'></input>");
  65110. elDisplayModel.css({
  65111. position : "absolute",
  65112. right : '65%',
  65113. bottom: '20px',
  65114. zIndex: "10000",
  65115. fontSize:'1em',color:"black",
  65116. width : '100px',
  65117. background:'rgba(255,255,255,0.8)',
  65118. });
  65119. this.domRoot.appendChild(elDisplayModel[0]);
  65120. elDisplayModel.on("click", (e) => {
  65121. if(Potree.settings.displayMode == 'showPointCloud' && this.panos.length == 0)return
  65122. Potree.settings.displayMode = Potree.settings.displayMode == 'showPointCloud' ? 'showPanos' : 'showPointCloud';
  65123. });
  65124. this.elDisplayModel = elDisplayModel;
  65125. }
  65126. {//切换模式
  65127. let displayMode = '';
  65128. this.latestRequestMode = '';//因为可能延迟,所以记录下每次的请求模式,延迟后判断这个
  65129. Object.defineProperty(Potree.settings , "displayMode",{
  65130. get: function() {
  65131. return displayMode
  65132. },
  65133. set: (mode)=> {
  65134. this.latestRequestMode = mode;
  65135. console.warn('Request setMode: ' + mode);
  65136. let config2;
  65137. let config = Potree.config.displayMode[mode];
  65138. if(this.isAtPano() && !this.latestToPano){
  65139. config2 = config.atPano;
  65140. }else {
  65141. config2 = config.transition;
  65142. }
  65143. let changeTileDownload = ()=>{
  65144. if(config2.showSkybox || config2.showPoint && config2.pointUsePanoTex){
  65145. //this.tileDownloader.start()
  65146. this.currentPano && this.currentPano.enter();
  65147. }else {
  65148. //this.tileDownloader.stop()
  65149. this.currentPano && this.currentPano.exit();
  65150. }
  65151. };
  65152. if(mode != displayMode){
  65153. this.dispatchEvent({type:'beginChangeMode',mode});
  65154. if(mode == 'showPanos' && viewer.mainViewport.camera.type == 'OrthographicCamera')return //等待切换
  65155. let camera = viewer.scene.getActiveCamera();
  65156. if(mode == 'showPanos' && viewer.mainViewport.view.isFlying()){//飞完才能切换全景
  65157. let f = ()=>{
  65158. if(this.latestRequestMode == mode){//如果ui还是停在这个模式的话
  65159. Potree.settings.displayMode = mode;
  65160. }
  65161. viewer.mainViewport.view.removeEventListener('flyingDone', f);
  65162. };
  65163. viewer.mainViewport.view.addEventListener('flyingDone', f); //once
  65164. return
  65165. }
  65166. if(this.isAtPano() && !this.latestToPano){
  65167. config2 = config.atPano;
  65168. }else {
  65169. config2 = config.transition;
  65170. if(mode == 'showPanos'){//自动飞入一个pano
  65171. //要改成飞进最近的。。。
  65172. if(this.panos.length == 0)return
  65173. //this.modeChanging = true //主要是因为到全景图不会立刻成功
  65174. let wait = (e)=>{
  65175. this.removeEventListener('flyToPanoDone',wait);
  65176. setTimeout(()=>{
  65177. if(this.latestRequestMode == mode ){
  65178. Potree.settings.displayMode = mode;
  65179. }
  65180. },e.makeIt ? 1 : 50);
  65181. };
  65182. this.addEventListener('flyToPanoDone',wait); //等待飞行完毕。flyToPano的callback可能不执行所以换这个。但也可能被cancel
  65183. this.flyToPano({
  65184. pano: this.findNearestPano(),
  65185. });
  65186. return;
  65187. }else {
  65188. }
  65189. }
  65190. changeTileDownload();
  65191. if(config2.showSkybox || config2.pointUsePanoTex){
  65192. let wait = (e)=> {
  65193. viewer.ifAllLoaded();
  65194. //if(e.pano && e.pano != this.currentPano)return//loadedDepthImg
  65195. setTimeout( ()=>{
  65196. if(this.latestRequestMode == mode ){
  65197. Potree.settings.displayMode = mode;
  65198. }
  65199. },1);
  65200. };
  65201. /*
  65202. //this.updateDepthTex()
  65203. if(this.checkAndWaitForPanoLoad(this.currentPano, this.basePanoSize, wait)){
  65204. return
  65205. } */
  65206. if(!this.currentPano.skyboxTex){
  65207. this.currentPano.waitForLoad();
  65208. this.currentPano.addEventListener('loadedTex', wait, {once:true});
  65209. return this.currentPano.loadTex()
  65210. }
  65211. }
  65212. viewer.scene.pointclouds.forEach(e=>{
  65213. Potree.Utils.updateVisible(e, 'displayMode', config2.showPoint, 2 );
  65214. });
  65215. if(config2.pointUsePanoTex){
  65216. viewer.scene.pointclouds.forEach(e=>{
  65217. e.material.setProjectedPanos(this.currentPano,this.currentPano, 1);
  65218. });
  65219. }else {
  65220. viewer.scene.pointclouds.forEach(e=>{
  65221. e.material.stopProjectedPanos();
  65222. });
  65223. }
  65224. Potree.Utils.updateVisible(this.cube,'showSkybox',config2.showSkybox );// this.cube.visible = config2.showSkybox
  65225. //this.cube.visible = config.atPano.showSkybox
  65226. if(this.cube.visible){
  65227. //this.cube.material.setProjectedPanos(this.currentPano, this.currentPano, 1)
  65228. this.setProjectedPanos({
  65229. progress:1,
  65230. ifSkybox: true,
  65231. ifPointcloud : false,
  65232. easeInOutRatio : 0,
  65233. pano0:this.currentPano,
  65234. pano1:this.currentPano
  65235. });
  65236. }else {
  65237. this.smoothZoomTo(1);
  65238. }
  65239. /* viewer.dispatchEvent({
  65240. type: "enableChangePos",
  65241. canLeavePano : config.canLeavePano ,
  65242. viewport:
  65243. }) */
  65244. //viewer.mainViewport.unableChangePos = !config.canLeavePano
  65245. displayMode = mode;
  65246. if(mode == 'showPanos'){
  65247. camera.far = viewer.farWhenShowPano; //修改far
  65248. Potree.settings.pointDensity = 'panorama';
  65249. if(Potree.config.displayMode.showPanos.transition.pointUsePanoTex){
  65250. viewer.scene.pointclouds.forEach(e=>{
  65251. e.material.pointSizeType = 'FIXED';
  65252. });
  65253. }
  65254. this.updateCube(this.currentPano);
  65255. }else {
  65256. if(camera.limitFar) camera.far = Potree.settings.cameraFar;//修改far
  65257. Potree.settings.pointDensity = Potree.settings.UserPointDensity;
  65258. //Potree.sdk && Potree.sdk.scene.changePointOpacity()
  65259. if(Potree.config.displayMode.showPanos.transition.pointUsePanoTex){
  65260. viewer.scene.pointclouds.forEach(e=>{
  65261. e.material.pointSizeType = Potree.config.material.pointSizeType;
  65262. });
  65263. }
  65264. }
  65265. camera.updateProjectionMatrix();
  65266. if(this.elDisplayModel){
  65267. this.elDisplayModel.val( mode == 'showPointCloud' ? ">>全景" : '>>点云');
  65268. }
  65269. /* this.panos.forEach(e=>{
  65270. Potree.Utils.updateVisible(e, 'modeIsShowPanos', mode == 'showPanos', 1, mode == 'showPanos' ? 'add':'cancel') //
  65271. }) */
  65272. this.dispatchEvent({type:'endChangeMode',mode});
  65273. console.log('setModeSuccess: ' + mode);
  65274. }else {
  65275. changeTileDownload();
  65276. //this.dispatchEvent({type:'endChangeMode',mode})
  65277. }
  65278. }
  65279. });
  65280. Potree.settings.displayMode = 'showPointCloud';
  65281. }// 切换模式 end
  65282. {//
  65283. let currentPano = null;
  65284. Object.defineProperty(this , "currentPano",{
  65285. get: function() {
  65286. return currentPano
  65287. },
  65288. set: function(e) {
  65289. if(e != currentPano){
  65290. //console.log('set currentPano ', e.id)
  65291. currentPano && currentPano.exit();
  65292. e && e.enter();
  65293. currentPano = e;
  65294. }
  65295. }
  65296. });
  65297. }
  65298. {//是否显示marker
  65299. let ifShowMarker = true;
  65300. Object.defineProperty(Potree.settings, "ifShowMarker",{
  65301. get: function() {
  65302. return ifShowMarker
  65303. },
  65304. set: (show)=>{
  65305. show = !!show;
  65306. if(show != ifShowMarker){
  65307. this.panos.forEach(pano=>{
  65308. Potree.Utils.updateVisible(pano, 'ifShowMarker', show, 1 );
  65309. });
  65310. //this.emit('markersDisplayChange', show)
  65311. ifShowMarker = show;
  65312. viewer.dispatchEvent('showMarkerChanged');
  65313. viewer.dispatchEvent('content_changed');
  65314. }
  65315. }
  65316. });
  65317. }
  65318. viewer.addEventListener("update", () => {
  65319. this.update(viewer);
  65320. });
  65321. //viewer.inputHandler.addInputListener(this);
  65322. var keys = {
  65323. FORWARD: ['W'.charCodeAt(0), 38],
  65324. BACKWARD: ['S'.charCodeAt(0), 40],
  65325. LEFT: ['A'.charCodeAt(0), 37],
  65326. RIGHT: ['D'.charCodeAt(0), 39],
  65327. };
  65328. viewer.inputHandler.addEventListener('keydown',(e)=>{
  65329. if(Potree.settings.displayMode == 'showPanos'){
  65330. for(let i in keys){
  65331. if(keys[i].some(a => a == e.keyCode)){
  65332. switch(i){
  65333. case 'FORWARD':
  65334. this.flyLocalDirection(Vectors.FORWARD.clone());
  65335. break;
  65336. case 'BACKWARD':
  65337. this.flyLocalDirection(Vectors.BACK.clone());
  65338. break;
  65339. case 'LEFT':
  65340. this.flyLocalDirection(Vectors.LEFT.clone());
  65341. break;
  65342. case 'RIGHT':
  65343. this.flyLocalDirection(Vectors.RIGHT.clone());
  65344. break;
  65345. }
  65346. break;
  65347. }
  65348. }
  65349. }
  65350. });
  65351. };
  65352. updateDepthTex(pano){
  65353. if(this.currentPano != pano || !pano.depthTex)return
  65354. //this.depthSampler.changeImg(pano.depthTex.image); //pick sampler要飞到了才能切换图,而skybox贴图是随着全景图切换而切换的
  65355. this.cube.material.updateDepthTex(pano); //确保一下
  65356. }
  65357. findNearestPano(pos){
  65358. pos = pos ? new Vector3().copy(pos) : this.position;
  65359. let result = Common$1.sortByScore(this.panos,[Images360.filters.isEnabled()],[e=>-e.position.distanceTo(pos)]);
  65360. let pano = result[0] && result[0].item;
  65361. return pano
  65362. }
  65363. /* set flying(v){//正在飞向pano
  65364. this.flying_ = !!v
  65365. //console.log('this.flying_ ', !!v )
  65366. //this.emit('flying', this.flying_)
  65367. let config = Potree.config.displayMode[Potree.settings.displayMode]
  65368. viewer.mainViewport.unableChangePos = !config.canLeavePano || !!v
  65369. }
  65370. get flying(){
  65371. return this.flying_
  65372. } */
  65373. flyLocalDirection(dir) {
  65374. var direction = this.getDirection(dir),
  65375. option1 = 1 === dir.y ? .4 : .75,
  65376. option2 = 1 === Math.abs(dir.x);
  65377. return this.flyDirection(direction, option1, option2, true)
  65378. }
  65379. getDirection(e) {
  65380. if(!e){
  65381. return viewer.scene.view.direction
  65382. }else {
  65383. return e = e ? e : (new Vector3).copy(Vectors.FORWARD),
  65384. e.applyQuaternion(viewer.mainViewport.camera.quaternion)
  65385. }
  65386. }
  65387. get position(){
  65388. return this.viewer.scene.view.position.clone()
  65389. }
  65390. isAtPano(precision){//是否在某个漫游点上
  65391. if(precision){
  65392. return this.currentPano && math.closeTo(viewer.scene.view.position, this.currentPano.position, precision)
  65393. }
  65394. return this.currentPano && viewer.scene.view.position.equals(this.currentPano.position)
  65395. }
  65396. updateProjectedPanos(){//更新材质贴图
  65397. //console.warn('updateProjectedPanos')
  65398. this.projectedPano0 && this.projectedPano1 && this.setProjectedPanos({pano0:this.projectedPano0, pano1:this.projectedPano1});
  65399. }
  65400. setProjectedPanos(o={}){//设置cube和点云的材质贴图
  65401. this.cube.material.setProjectedPanos(o.pano0, o.pano1, o.progress);
  65402. if(o.ifPointcloud){
  65403. viewer.scene.pointclouds.forEach(e=>{
  65404. e.material.setProjectedPanos(o.pano0, o.pano1, o.progress, o.easeInOutRatio);
  65405. });
  65406. }
  65407. //console.warn('setProjectedPanos ', o.pano0.id , o.pano1.id)
  65408. this.projectedPano0 = o.pano0;
  65409. this.projectedPano1 = o.pano1;
  65410. }
  65411. cancelFlyToPano(toPano){//取消当前已有的飞行准备,前提是相机还未移动
  65412. if(/* viewer.mainViewport.view.isFlying() || */toPano && this.latestToPano != toPano)return
  65413. //Potree.Log('cancelFlyToPano', this.latestToPano && this.latestToPano.pano.id)
  65414. this.nextPano = null;
  65415. this.latestToPano = null;
  65416. }
  65417. flyToPano(toPano) { //飞向漫游点
  65418. if(!toPano)return
  65419. if(toPano instanceof Panorama){
  65420. toPano = {pano: toPano};
  65421. }
  65422. let done = (makeIt, disturb)=>{
  65423. //console.log('flyToPano done ', toPano.pano.id, makeIt, disturb )
  65424. if(makeIt || disturb) { // disturb已经开始飞行但中途取消
  65425. toPano.callback && toPano.callback(makeIt);
  65426. //this.flying = false
  65427. this.cancelFlyToPano(toPano);
  65428. this.updateClosestPano(this.closestPano,false); //飞行结束后取消点击漫游点时得到的closestPano
  65429. }else {
  65430. }
  65431. this.dispatchEvent({type:'flyToPanoDone', makeIt});
  65432. toPano.deferred && toPano.deferred.resolve(makeIt); //测量线截图时发现,resolve需要写在flying=false 后才行。
  65433. };
  65434. if(!toPano.pano.enabled)return done(false,true);
  65435. //Potree.Log('hope flyToPano: '+toPano.pano.id )
  65436. //如果旧的toPano只是旋转镜头,就直接取消旧的
  65437. if(this.latestToPano && this.latestToPano != toPano && (//还在飞
  65438. this.latestToPano.pano != this.currentPano || !this.isAtPano())){//如果旧的toPano只在pano旋转镜头,就直接取消旧的,继续执行
  65439. return done(false)
  65440. }
  65441. if(this.currentPano == toPano.pano && this.isAtPano() && !toPano.target && !toPano.quaternion ){
  65442. //已在该pano
  65443. this.dispatchEvent({type:'flyToPano', toPano});
  65444. return done(true);
  65445. }
  65446. //Potree.Log('flyToPano: '+toPano.pano.id, this.latestToPano && this.latestToPano.pano.id )
  65447. let target = toPano.target;
  65448. let config = Potree.config.displayMode[Potree.settings.displayMode];
  65449. let pointcloudVisi = config.atPano.showPoint; //viewer.scene.pointclouds[0].visible
  65450. let pano = toPano.pano;
  65451. let dis = pano.position.distanceTo(this.position);
  65452. this.nextPano = pano;
  65453. this.latestToPano = toPano;
  65454. //this.flying = true //防止新的请求
  65455. //Potree.Log('flyToPano:'+pano.id + ' , duration:'+toPano.duration, null, 12)
  65456. {//不飞的话是否不要执行这段?
  65457. let wait = ( )=> {
  65458. viewer.ifAllLoaded();
  65459. if( this.latestToPano && pano != this.latestToPano.pano)return//loadedDepthImg
  65460. if(this.latestToPano != toPano)return /* Potree.Log('已经取消') *///如果取消了
  65461. setTimeout(()=>{
  65462. if(this.latestToPano != toPano)return
  65463. this.flyToPano(toPano);
  65464. },1);
  65465. };
  65466. if(!pano.depthTex && pano.pointcloud.hasDepthTex){ //点云模式也要加载depthTex,因获取neighbour需要用到
  65467. //console.log('等待加载depthtex')
  65468. pano.addEventListener('loadedDepthImg', wait, {once:true});
  65469. pano.waitForLoad();
  65470. return pano.loadDepthImg()
  65471. }
  65472. if(config.atPano.showSkybox || config.atPano.pointUsePanoTex){
  65473. let a = this.updateCube(this.currentPano, toPano.pano);
  65474. if(a == 'useBound'){
  65475. toPano.useBound = true;
  65476. }
  65477. if(!pano.skyboxTex){
  65478. pano.waitForLoad();
  65479. pano.addEventListener('loadedTex', wait, {once:true});
  65480. return pano.loadTex()
  65481. }
  65482. /* if(this.checkAndWaitForPanoLoad(pano, toPano.basePanoSize || this.basePanoSize, wait )){
  65483. return
  65484. } */
  65485. }
  65486. }
  65487. Potree.Utils.updateVisible(this.cube,'showSkybox', config.atPano.showSkybox ); // this.cube.visible = config.atPano.showSkybox
  65488. //console.log('开始飞1')
  65489. if(config.transition.showPoint){
  65490. viewer.scene.pointclouds.forEach(e=>{
  65491. Potree.Utils.updateVisible(e, 'displayMode', true);
  65492. });
  65493. }
  65494. if(config.transition.showSkybox || config.transition.pointUsePanoTex){
  65495. this.setProjectedPanos({
  65496. progress:0,
  65497. ifSkybox: this.cube.visible,
  65498. ifPointcloud : config.transition.pointUsePanoTex,
  65499. easeInOutRatio : pointcloudVisi ? 0.3 : 0,
  65500. pano0:this.currentPano,
  65501. pano1:pano
  65502. });
  65503. }
  65504. const endPosition = pano.position.clone();
  65505. let T = Potree.config.transitionsTime;
  65506. let maxTime = this.isAtPano() ? T.panoToPanoMax : T.flyIn;
  65507. let duration = toPano.duration == void 0 ? (T.flyMinTime+Math.min(T.flytimeDistanceMultiplier * dis, maxTime)) : toPano.duration;
  65508. if(toPano.useBound){
  65509. duration = Math.min(1500, duration);
  65510. toPano.easeName = 'easeInOutQuad';
  65511. }else {
  65512. if(endPosition.equals(this.position))toPano.easeName = 'easeOutSine';
  65513. }
  65514. {
  65515. toPano.easeName = toPano.easeName || 'linearTween';
  65516. toPano.duration = duration;
  65517. this.beforeFlyToPano(toPano);
  65518. }
  65519. let onUpdate = (progress)=>{
  65520. this.cube.material.uniforms.progress.value = progress;
  65521. viewer.scene.pointclouds.forEach(e=>{
  65522. e.material.uniforms.progress.value = progress;
  65523. });
  65524. };
  65525. let fly = ()=>{
  65526. let startProgress = toPano.progress = toPano.progress || 0;
  65527. let loadNextProgress = MathUtils$1.clamp(1 - 2.5 / dis, 0.3, 0.8);
  65528. //console.log(loadNextProgress, (1-loadNextProgress) * dis )
  65529. this.dispatchEvent({type:'flyToPano', toPano});
  65530. viewer.scene.view.setView({position:endPosition, target, quaternion:toPano.quaternion , duration:toPano.duration,
  65531. onUpdate:(progress_, delta)=>{
  65532. let progress = startProgress + progress_ * (1 - startProgress);
  65533. let currentSpeed;
  65534. if (progress_ != 1 && progress_ != 0) { // 1的时候不准,往往偏小, 0的时候速度为0,也不记录
  65535. currentSpeed = ((progress - toPano.progress) * dis) / delta; //记录下当前速度,当变为匀速时可以过渡到flySpeed
  65536. } else {
  65537. currentSpeed = toPano.currentSpeed || 0;
  65538. }
  65539. toPano.currentSpeed = currentSpeed;
  65540. toPano.progress = progress;
  65541. //console.log('progress_', progress_, 'delta',delta , 'progress', progress/*, 'currentSpeed', currentSpeed, */ )
  65542. if (progress > loadNextProgress && toPano.easeName == 'linearTween' && currentSpeed){// 减速. 如果仅旋转就不停止
  65543. //console.log('减速', currentSpeed)
  65544. toPano.easeName = 'easeOutSine';
  65545. let restDis = (1 - progress) * dis;
  65546. toPano.duration = (Math.PI / 2 * restDis) / currentSpeed; // 这样能保证初始速度为currentSpeed
  65547. viewer.scene.view.cancelFlying('all',false); //为了防止执行cancelFun先主动cancel
  65548. toPano.flyCount = 2;
  65549. fly(toPano);
  65550. }
  65551. onUpdate(progress);
  65552. },
  65553. callback:()=>{
  65554. if(!config.atPano.pointUsePanoTex){
  65555. viewer.scene.pointclouds.forEach(e=>{
  65556. e.material.stopProjectedPanos();
  65557. });
  65558. }
  65559. this.currentPano = pano;
  65560. this.nextPano = null;
  65561. if(Potree.settings.displayMode == 'showPanos'){
  65562. viewer.scene.pointclouds.forEach(e=>{
  65563. Potree.Utils.updateVisible(e, 'displayMode',pointcloudVisi);
  65564. });
  65565. }
  65566. done(true);
  65567. this.updateDepthTex(this.currentPano);
  65568. this.updateProjectedPanos();//dispose
  65569. },
  65570. cancelFun:()=>{ done(false, true); },
  65571. Easing:toPano.easeName,
  65572. ignoreFirstFrame : toPano.flyCount != 2 //变换transition时不停一帧
  65573. });
  65574. };
  65575. if(Potree.settings.displayMode == 'showPanos'){
  65576. setTimeout(fly, 40); //更新geo后缓冲
  65577. }else {
  65578. fly();
  65579. }
  65580. //console.log('flyToPano:', toPano.pano.id)
  65581. }
  65582. beforeFlyToPano(toPano){
  65583. if(this.currentPano != toPano.pano) {
  65584. this.smoothZoomTo(toPano.zoomLevel || 1, toPano.duration / 2);
  65585. }
  65586. }
  65587. isNeighbour(pano0, pano1, dontCompute, onlyUseTex, computeDirFirst){//是否之间没有遮挡(在加载visibles之前,自己算) 最好pano0是currentPano
  65588. if(!pano0 || !pano1 )return
  65589. let margin = 0.1;
  65590. let map0 = this.neighbourMap[pano0.id]; //主
  65591. let map1 = this.neighbourMap[pano1.id]; //副
  65592. //三个方向 : position0到position1, position0到floorPosition1, position1到floorPosition0。 只要有一个满足ifNeighbour就为true。 不过为了不使sampler总换图,先只考虑从主pano到副pano的方向
  65593. //0能看到1不代表1能看到0; 但只要有一方能完全看到另一方,无论是position还是floorPosition都算是neighbor
  65594. //也正因此,全部计算完两两之间的neighbour后,neighbourMap也看起来有缺的样子,必须得通过isNeighbour函数来判断是否是邻居
  65595. let ifNeighbour;
  65596. if(map0[pano1.id] != void 0){
  65597. ifNeighbour = map0[pano1.id];
  65598. }
  65599. if(!ifNeighbour && map1[pano0.id] != void 0){
  65600. ifNeighbour = map1[pano0.id];
  65601. }
  65602. if(dontCompute) return ifNeighbour
  65603. let getNeighbour = (mainPano, subPano, jumpStep1, simpleJudge)=>{
  65604. //暂时只判断到pano,不判断到marker的方向
  65605. let dirPoints = [];
  65606. if(!jumpStep1){//跳过此步骤,因为之前算过不成功(虽然用另一个漫游点算的可能拍摄时间不同所以有概率不一样,如人走动)
  65607. dirPoints.push([subPano.position, mainPano.position]);
  65608. }
  65609. if(!simpleJudge){
  65610. dirPoints.push([subPano.floorPosition.clone().add(new Vector3(0,0,0.1)), mainPano.position]);
  65611. }
  65612. for(let i=0; i<dirPoints.length; i++){
  65613. let dir = new Vector3().subVectors(dirPoints[i][0], dirPoints[i][1]).normalize();
  65614. let intersectPoint = viewer.images360.depthSampler.sample({dir}, mainPano, true);
  65615. if(!intersectPoint || intersectPoint.distance+margin > pano0.position.distanceTo(pano1.position)){
  65616. return true
  65617. }
  65618. }
  65619. };
  65620. if( map0[pano1.id] == void 0 && !ifNeighbour ) {//主方向为空且不为邻居
  65621. let simpleJudge = pano0.position.distanceToSquared(pano1.position) > 300; //在远处去掉对floorPosition的判断
  65622. if(pano0.depthTex || pano1.depthTex){
  65623. if(map0[pano1.id] == void 0 && pano0.depthTex){
  65624. let is = getNeighbour(pano0, pano1, null, simpleJudge);
  65625. if(is){
  65626. ifNeighbour = true;
  65627. }else if(simpleJudge){
  65628. ifNeighbour = false;
  65629. }
  65630. map0[pano1.id] = !!is;
  65631. }
  65632. if( ifNeighbour == void 0 && /* map1[pano0.id] == void 0 && */ pano1.depthTex){ //若正向为false,反向暂且不算,等到pano0为主时再算
  65633. let is = getNeighbour(pano1, pano0, !ifNeighbour, simpleJudge);
  65634. if(is){
  65635. ifNeighbour = true;
  65636. }else if(simpleJudge){
  65637. ifNeighbour = false;
  65638. }
  65639. map1[pano0.id] = !!is;
  65640. }
  65641. ifNeighbour = !!ifNeighbour;
  65642. //console.log('isNeighbour', pano0, pano1, ifNeighbour)
  65643. /* if(ifNeighbour){ //需要标记成全部true吗,不标记也能get到,但标记了更直观,不标记保留信息更多
  65644. map0[pano1.id] = map1[pano0.id] = true
  65645. } */
  65646. }else if(!onlyUseTex){//使用点云判断(有深度贴图时不会执行到这)
  65647. let inDirection = ()=>{
  65648. let dir = new Vector3().subVectors(pano1.position,pano0.position).normalize();
  65649. let dis = pano1.position.distanceTo(pano0.position);
  65650. let hfov = cameraLight.getHFOVForCamera(viewer.mainViewport.camera , true );
  65651. let max = Math.cos(MathUtils$1.degToRad(10));
  65652. let min = Math.cos(MathUtils$1.degToRad(80));
  65653. if(this.getDirection().dot(dir) > MathUtils$1.clamp(Math.cos(hfov/2 ) * dis / 10, min, max )){//距离越远要求和视线角度越接近
  65654. return true
  65655. }
  65656. };
  65657. if(computeDirFirst){//先计算方向,防止重复计算ifBlockedByIntersect
  65658. if(inDirection()){
  65659. ifNeighbour = !viewer.inputHandler.ifBlockedByIntersect({pos3d:pano1.position, margin, cameraPos:pano0.position});
  65660. }
  65661. }else {
  65662. ifNeighbour = !viewer.inputHandler.ifBlockedByIntersect({pos3d:pano1.position, margin, cameraPos:pano0.position});
  65663. if(ifNeighbour && !inDirection()){
  65664. ifNeighbour = undefined; //不确定
  65665. }
  65666. }
  65667. //}
  65668. map0[pano1.id] = map1[pano0.id] = ifNeighbour ? 'byCloud' : ifNeighbour;//写简单点
  65669. }
  65670. }
  65671. if(ifNeighbour){
  65672. pano0.neighbours.includes(pano1) || pano0.neighbours.push(pano1);
  65673. pano1.neighbours.includes(pano0) || pano1.neighbours.push(pano0);
  65674. }
  65675. return ifNeighbour
  65676. }
  65677. bump(direction) {//撞墙弹回效果
  65678. if (!this.bumping && !this.latestToPano) {
  65679. let distance = Potree.settings.displayMode == 'showPanos' ? 0.3 : 0.2;//感觉点云模式比全景模式更明显,所以降低
  65680. let currentPos = this.position.clone();
  65681. let endPosition = new Vector3().addVectors(this.position, direction.clone().multiplyScalar(distance));
  65682. let duration = 150;
  65683. viewer.scene.view.setView({position:endPosition, duration,
  65684. callback:()=>{
  65685. viewer.scene.view.setView({position:currentPos, duration: duration*5,
  65686. callback: ()=>{
  65687. this.bumping = false;
  65688. //this.dispatchEvent('cameraMoveDone')
  65689. },
  65690. Easing:'easeInOutSine',
  65691. cancelFun:()=>{this.bumping = false;}
  65692. });
  65693. this.bumping = true;
  65694. },
  65695. cancelFun:()=>{this.bumping = false;},
  65696. Easing:'easeInOutSine'
  65697. });
  65698. this.bumping = true;
  65699. }
  65700. //备注:将4dkk中的‘前后方向变化fov、左右方向移动镜头’ 都改为移动镜头。 因为这里无法判断左右离壁距离。
  65701. }
  65702. flyToPanoClosestToMouse() {
  65703. if(!Potree.settings.ifShowMarker){//不显示marker的时候mousemove没更新鼠标最近点所以更新
  65704. this.updateClosestPano(viewer.inputHandler.intersect);
  65705. }
  65706. //console.log('flyToPanoClosestToMouse',this.closestPano)
  65707. if (this.closestPano) {
  65708. let pano = this.closestPano;
  65709. return this.flyToPano({
  65710. pano, easeName: this.isAtPano() ? 'linearTween' : 'easeInOutQuad'
  65711. });
  65712. }
  65713. var direction = this.viewer.inputHandler.getMouseDirection().direction;
  65714. this.flyDirection(direction);
  65715. }
  65716. flyDirection(direction, option1, option2, byKey) {
  65717. if(viewer.mainViewport.view.isFlying()){// closestPanoInDirection函数耗时长,飞行时运行会卡顿(如果以后加无缝过渡再说)
  65718. return
  65719. }
  65720. var deferred = $.Deferred();
  65721. //this.history.invalidate();
  65722. var panoSet = this.closestPanoInDirection(direction, option1, option2, byKey);
  65723. if (panoSet) {
  65724. this.flyToPano({
  65725. pano: panoSet,
  65726. callback: deferred.resolve.bind(deferred, !0)
  65727. } );
  65728. } else {
  65729. this.bump(direction);
  65730. deferred.resolve(!1);
  65731. }
  65732. return deferred.promise();
  65733. }
  65734. closestPanoInDirection(direction, option1, option2, byKey) {
  65735. return this.rankedPanoInDirection(0, direction, option1, option2, byKey)
  65736. }
  65737. rankedPanoInDirection(t, direction, option1, option2, byKey){
  65738. //此direction为mouseDirection,是否需要加上相机角度的权重
  65739. //let startTime = Date.now()
  65740. var panoSet = {
  65741. pano: null,
  65742. candidates: [] //缓存顺序--如果需要打印的话
  65743. };
  65744. t || (t = 0);
  65745. option1 = void 0 !== option1 ? option1 : .75;
  65746. var o = option2 ? "angle" : "direction";
  65747. let disSquareMap = new Map();
  65748. this.panos.forEach(pano=>{
  65749. let dis2 = pano.position.distanceToSquared(this.position); //距离目标点
  65750. disSquareMap.set(pano, dis2);
  65751. });
  65752. let changeTexCount = 0, maxWaitDur = 300;
  65753. var request = [//必要条件
  65754. Images360.filters.not(this.currentPano),
  65755. Images360.filters.isEnabled(),
  65756. Images360.filters.inFloorDirection( this.position, direction, option1 ), //原先用inPanoDirection,但容易穿楼层,当mouse较低或较高
  65757. Images360.filters.inPanoDirection( this.position, this.getDirection(), option1/* , true */), //垂直方向上再稍微限制一下, 要接近视线方向,避免点击前方时因无路而到下一楼。但不能太高,否则楼梯上稍微朝下点击都到不了上方。之所以使用视线方向是因为镜头方向比鼠标方向目的性更强。
  65758. (pano)=>{
  65759. let isNeighbour = this.isNeighbour(this.currentPano, pano, false, true); // 注: 不会再changeTex了
  65760. if(isNeighbour || pano.noNeighbour && disSquareMap.get(pano) < 200){//在靠近孤立点时可以通行。但是不好把握这个距离,太远的话很多地方都会不小心到孤立点,太近的话可能永远到不了。
  65761. return true
  65762. }
  65763. },
  65764. ];
  65765. var list = [//决胜项目
  65766. (pano)=>{
  65767. return -disSquareMap.get(pano)
  65768. },
  65769. Images360.scoreFunctions[o]( this.position, direction, true),
  65770. (pano)=>{
  65771. let neighbour = this.isNeighbour(this.currentPano, pano, true, true); //不计算的
  65772. return neighbour ? directionFactor : 0;
  65773. } ,
  65774. ];
  65775. if(!byKey && viewer.inputHandler.intersect && this.currentPano ){//方便上下楼, 考虑panos之间的角度差
  65776. let pos1 = this.currentPano.floorPosition;
  65777. let vec1 = new Vector3().subVectors(viewer.inputHandler.intersect.location, pos1 ).normalize();//应该只有atPano时才会执行到这吧?
  65778. list.push( function(pano) {
  65779. var pos2 = pano.floorPosition;
  65780. var vec2 = pos2.clone().sub(pos1).normalize();
  65781. return vec2.dot(vec1) * directionFactor * 4
  65782. });
  65783. }
  65784. this.findRankedByScore(t,request,list,panoSet);
  65785. //console.log( 'costTime:',Date.now() - startTime)
  65786. return panoSet.pano;
  65787. }
  65788. findRankedByScore(e, t, i, n) {
  65789. n && (n.candidates = null, //candidates 缓存顺序--如果需要打印的话
  65790. n.pano = null),
  65791. e || (e = 0);
  65792. var r = Common$1.sortByScore(this.panos, t, i);
  65793. //console.log('findRankedByScore', r && r.map(u=>u.item.id + '| ' + math.toPrecision(u.score,4) + " | " + math.toPrecision(u.scores,4)))
  65794. return !r || 0 === r.length || e >= r.length ? null : (n && (n.candidates = r,
  65795. n.pano = r[e].item),
  65796. r[e].item)
  65797. }
  65798. updateClosestPano(intersect, state) {//hover到的pano 大多数时候是null
  65799. var pano;
  65800. if(intersect instanceof Panorama){ //漫游模式
  65801. pano = state ? intersect : null;
  65802. }else {
  65803. if(this.isAtPano() || this.bumping){
  65804. return
  65805. }else {
  65806. var filterFuncs = [];
  65807. intersect = intersect && intersect.location;
  65808. if(!intersect)return
  65809. let sortFuncs = Potree.settings.editType != 'pano'? [Images360.sortFunctions.floorDisSquaredToPoint(intersect)] : [Images360.sortFunctions.disSquaredToPoint(intersect)];
  65810. pano = Common$1.find(this.panos, filterFuncs, sortFuncs);
  65811. }
  65812. }
  65813. if (pano != this.closestPano) {
  65814. pano && (this.isPanoHover = !0);
  65815. this.closestPanoChanging(this.closestPano, pano); // 高亮marker
  65816. //console.log('closestPano '+ (pano ? pano.id : 'null' ))
  65817. this.closestPano = pano;
  65818. } else {
  65819. this.isPanoHover = !1;
  65820. }
  65821. }
  65822. closestPanoChanging(oldPano, newPano){
  65823. if(!Potree.settings.ifShowMarker)return
  65824. oldPano && oldPano.hoverOff({byImages360:true});
  65825. newPano && newPano.hoverOn({byImages360:true});
  65826. }
  65827. /*
  65828. getTileDirection(){//根据不同dataset的来存储
  65829. var vectorForward = viewer.scene.view.direction.clone()
  65830. var vectorForwards = viewer.scene.pointclouds.map(e=>{
  65831. var inv = new THREE.Matrix4().copy(e.rotateMatrix).invert()//乘上dataset的旋转的反转
  65832. var direction = vectorForward.clone().applyMatrix4(inv)
  65833. return {
  65834. datasetId: e.dataset_id,
  65835. direction: math.convertVector.ZupToYup(direction)
  65836. }
  65837. })
  65838. //return vectorForwards[0].direction
  65839. return {
  65840. datasetsLocal: vectorForwards,
  65841. vectorForward
  65842. }
  65843. }
  65844. */
  65845. fitPanoTowardPoint(o){ //寻找最适合的点位
  65846. var point = o.point, //相机最佳位置
  65847. target = o.target || o.point, //实际要看的位置
  65848. require = o.require || [],
  65849. rank = o.rank || [],
  65850. force = o.force,
  65851. getAll = o.getAll,
  65852. bestDistance = o.bestDistance || 0,
  65853. sameFloor = o.sameFloor,
  65854. maxDis = o.maxDis,
  65855. dir = o.dir;
  65856. let camera = viewer.scene.getActiveCamera();
  65857. if(target && !dir){
  65858. dir = new Vector3().subVectors(target,point).normalize();
  65859. }
  65860. let atFloor = sameFloor && viewer.modules.SiteModel.pointInWhichEntity(point, 'floor');
  65861. //if(o.floor)require.push(Panorama.filters.atFloor(o.floor))
  65862. let checkIntersect = o.checkIntersect;
  65863. let base = Math.max(300, viewer.bound.boundSize.length()*3);
  65864. if(o.boundSphere){//只接受boundSphere
  65865. let aspect = 1;//size.x / size.y
  65866. let dis;
  65867. if(camera.aspect > aspect){//视野更宽则用bound的纵向来决定
  65868. dis = /* size.y */o.boundSphere.radius/* / 2 *// MathUtils.degToRad(camera.fov / 2);
  65869. }else {
  65870. let hfov = cameraLight.getHFOVForCamera(camera , true );
  65871. dis = /* size.x */ o.boundSphere.radius /* / 2 */ / (hfov / 2);
  65872. }
  65873. bestDistance = dis;//*0.8
  65874. }
  65875. let disSquareMap = new Map();
  65876. let bestDisSquared = bestDistance * bestDistance;
  65877. let maxDisSquared = maxDis && (maxDis * maxDis);
  65878. this.panos.forEach(pano=>{
  65879. let dis2 = pano.position.distanceToSquared(target); //距离目标点
  65880. disSquareMap.set(pano, dis2);
  65881. });
  65882. let panos = this.panos.sort((p1,p2)=>{return disSquareMap.get(p1)-disSquareMap.get(p2)});
  65883. if(maxDisSquared){//热点超过最大距离不可见的
  65884. let panos2 = [], pano, i=0;
  65885. while(pano = panos[i], disSquareMap.get(pano) < maxDisSquared){
  65886. panos2.push(pano);
  65887. i++;
  65888. }
  65889. if(panos2.length == 0)return {pano, msg:'tooFar'} //全部都大于maxDis, 就返回最近的
  65890. panos = panos2;
  65891. }
  65892. rank.push((pano)=>{
  65893. let dis1 = Math.abs(pano.position.distanceToSquared(point) - bestDisSquared); //距离最佳位置
  65894. disSquareMap.set(pano, dis1);
  65895. if(!target){
  65896. return -dis1
  65897. }else {
  65898. let dis2 = disSquareMap.get(pano);
  65899. let vec2 = new Vector3().subVectors(target,pano.position).normalize();
  65900. let cos = dir.dot(vec2);
  65901. //let result = (- dis1 - Math.pow(dis2 , 1.5)) / (cos + 2) // cos+2是为了调整到1-3,
  65902. let result = (dis1 + dis2*0.3) * ( -1 + cos*0.9 ); //尽量贴近最佳位置的角度, 或贴近相机原来的角度 。尽量靠近最佳观测点,并且优先选择靠近目标点的位置.(注意cos的乘数不能太接近1,否则容易只考虑角度)
  65903. //Potree.Log(pano.id, dis1, dis2, cos, result,{font:{toFixed:2,fontSize:10}})
  65904. return result
  65905. }
  65906. //注:热点最好加上法线信息,这样可以多加一个限制,尽量顺着热点像展示的方向。
  65907. },
  65908. (pano)=>{
  65909. let score = 0;
  65910. if(pano.depthTex && checkIntersect){
  65911. let intersect = !!viewer.ifPointBlockedByIntersect(target, pano.id, true); //viewer.inputHandler.ifBlockedByIntersect({pos3d:target, margin:0.1, cameraPos:pano})
  65912. if(intersect){
  65913. score = 0;
  65914. }else {
  65915. score = base * 2;
  65916. }
  65917. }else {
  65918. score = base * 1.5; //没加载好的话,不管了 , 几乎当做无遮挡,否则容易到不了最近点
  65919. }
  65920. return score
  65921. }
  65922. );
  65923. var g = Common$1.sortByScore(panos, require, rank);
  65924. //console.log(g)
  65925. /* let result1 = g && g.slice(0, 10)
  65926. if(result1){
  65927. g = Common.sortByScore(result1, [], [(e)=>{//避免遮挡
  65928. let pano = e.item;
  65929. let score = 0, log = ''
  65930. if(atFloor && atFloor.panos.includes(pano)){//如果不在任何一楼呢?
  65931. score += 600, log+='atFloor'
  65932. }
  65933. return {score, log}
  65934. }]);
  65935. if(g){
  65936. g.forEach(e=>{e.item = e.item.item})
  65937. }
  65938. console.log(g)
  65939. } */
  65940. let pano = g && g.length > 0 && g[0].item;
  65941. if(pano && checkIntersect){
  65942. let intersect = !!viewer.ifPointBlockedByIntersect(target, pano.id, true);
  65943. if(intersect){
  65944. return {pano, msg : 'sheltered'}
  65945. }
  65946. }
  65947. //if(getAll)return g;
  65948. return pano
  65949. //注:深度图有的位置会不准确,以至于会算出错误的遮挡、选择错误的pano,解决办法只能是移动下热点到更好的位置
  65950. }
  65951. //---------------scroll zoom ------------------------------------------
  65952. /* zoomIn = function() { //放大
  65953. this.zoomBy(1 + this.zoomSpeed);
  65954. }
  65955. zoomOut = function() {//缩小
  65956. this.zoomBy(1 - this.zoomSpeed);
  65957. } */
  65958. zoomBy(e, pointer) {//以倍数
  65959. this.zoomTo(this.zoomLevel * e, pointer);
  65960. }
  65961. zoomTo(zoomLevel, pointer) {//缩放到某绝对zoomLevel
  65962. let zoom = Potree.settings.zoom;
  65963. if (zoom.enabled) {
  65964. zoomLevel = MathUtils$1.clamp(zoomLevel, zoom.min, zoom.max);
  65965. //console.log(zoomLevel)
  65966. if(zoomLevel == this.zoomLevel) return;
  65967. /* if (zoomLevel > this.zoomLevel) {
  65968. this.emit(ZoomEvents.ZoomIn);
  65969. zoomLevel === settings.zoom.max && this.emit(ZoomEvents.ZoomMax);
  65970. } else if (zoomLevel < this.zoomLevel) {
  65971. this.emit(ZoomEvents.ZoomOut);
  65972. zoomLevel === settings.zoom.min && this.emit(ZoomEvents.ZoomMin);
  65973. } */
  65974. this.zoomLevel = zoomLevel;
  65975. //定点缩放:使当前鼠标所在的位置缩放后不变
  65976. let view = viewer.scene.view;
  65977. let originDir = viewer.scene.view.direction;
  65978. let oldPointerDir = viewer.inputHandler.getMouseDirection(pointer).direction;
  65979. viewer.setFOV(Potree.config.view.fov * (1 / this.zoomLevel));
  65980. let newPointerDir = viewer.inputHandler.getMouseDirection(pointer).direction;
  65981. view.direction = oldPointerDir; //获取一下鼠标所在位置的yaw 和 pitch
  65982. let oldPitch = view.pitch, oldYaw = view.yaw;
  65983. view.direction = newPointerDir;
  65984. let newPitch = view.pitch, newYaw = view.yaw;
  65985. view.direction = originDir; //还原
  65986. viewer.scene.view.pitch -= newPitch - oldPitch;
  65987. viewer.scene.view.yaw -= newYaw - oldYaw;
  65988. }
  65989. }
  65990. zoomFovTo( fov ) { //通过fov来算zoomLevel
  65991. let zoomLevel = Potree.config.view.fov /* this.baseFov */ / fov;
  65992. this.zoomTo( zoomLevel );
  65993. }
  65994. smoothZoomTo(aimLevel, dur=0) {
  65995. var currentLevel = this.zoomLevel;
  65996. if(currentLevel == aimLevel)return;
  65997. var fun = (progress)=>{
  65998. //progress > 1 && (progress = 1)
  65999. let level = currentLevel * (1 - progress) + aimLevel * progress;
  66000. this.zoomTo(level, !0);
  66001. };
  66002. transitions.start(fun, dur, null, null, 0 , easing['easeInOutQuad'] );
  66003. }
  66004. getIntersect(pano, dir, origin){
  66005. if(pano && pano.pointcloud.hasDepthTex ){
  66006. return this.depthSampler.sample( {dir }, pano, true )
  66007. }else {
  66008. origin = origin || pano.position;
  66009. return viewer.inputHandler.getIntersect(viewer.inputHandler.hoverViewport, true, null, null, true, {
  66010. point: origin.clone().add(dir),
  66011. cameraPos: origin
  66012. })
  66013. }
  66014. }
  66015. addPanoData(data={} ){//加载漫游点
  66016. data = data.sweepLocations;
  66017. if(!data || data.length == 0)return console.error( '没有漫游点')
  66018. data.forEach((info)=>{
  66019. //if(Potree.fileServer){
  66020. info.id = this.panos.length; //把info的id的一长串数字改简单点
  66021. //}
  66022. let pano = new Panorama( info, this );
  66023. pano.addEventListener('dispose',(e)=>{
  66024. if(this.closestPano == pano) this.closestPano = null;
  66025. });
  66026. this.panos.push(pano);
  66027. });
  66028. }
  66029. loadDone(){
  66030. Potree.Utils.setObjectLayers(this.node, 'sceneObjects');
  66031. this.panos.forEach(e=>{
  66032. this.neighbourMap[e.id] = {};
  66033. e.label && Potree.Utils.setObjectLayers(e.label, 'bothMapAndScene');
  66034. });
  66035. {
  66036. let minSize = new Vector3(1,1,1);
  66037. this.bound = math.getBoundByPoints(this.panos.map(e=>e.position), minSize);
  66038. viewer.scene.pointclouds.forEach(pointcloud=>pointcloud.getPanosBound());
  66039. }
  66040. if(viewer.scene.pointclouds.some(e=>e.panos.length == 0)){
  66041. //console.warn('存在数据集没有pano');
  66042. viewer.hasNoPanoDataset = true;
  66043. }
  66044. }
  66045. getPano(value, typeName='id'){ //默认找的是id,也可以是sid、uuid
  66046. return this.panos.find(p=>p[typeName] == value)
  66047. }
  66048. update(){
  66049. if(!this.currentPano)return
  66050. Potree.Common.intervalTool.isWaiting('filterDepthTex', ()=>{
  66051. var s = [Images360.filters.not(this.currentPano )],
  66052. l = [Images360.scoreFunctions.distanceSquared(this.currentPano ), Images360.scoreFunctions.direction(this.position, this.getDirection())];
  66053. this.nearPanos = Common$1.sortByScore(this.panos, s, l).map(e=>e.item);
  66054. //下载深度图
  66055. let depTexDlCount = browser.isMobile() ? 1 : 2;
  66056. let loadingCount = this.nearPanos.filter(p=>p.depthTexLoading).length;
  66057. if(loadingCount<depTexDlCount){
  66058. this.nearPanos.filter(p=>!p.depthTex).slice(0, depTexDlCount-loadingCount).forEach(p=>p.loadDepthImg());
  66059. }
  66060. }, 77);
  66061. this.getNeighbours(this.nearPanos);
  66062. }
  66063. };
  66064. Images360.prototype.getNeighbours = function(){ //逐渐自动获取neighbours。 200个点差不多在半分钟内算完
  66065. let lastIndex; //标记上次查询到哪,防止重新sortByScore
  66066. return function(nearPanos){
  66067. if(!this.currentPano || viewer.mainViewport.view.isFlying() || viewer.lastFrameChanged || viewer.inputHandler.drag /* interacted */){ //拖拽时不更新,否则移动端卡
  66068. return lastIndex = 0;
  66069. }
  66070. if(!nearPanos)return;
  66071. //let startTime = Date.now()
  66072. let panos = [this.currentPano, ...nearPanos ];
  66073. this.depthSampler.updateNearPanos(panos);
  66074. let maxWaitDur = browser.isMobile() ? 40 : 60;
  66075. let changeCount = 0, getCount = 0;
  66076. let changeTexCount = ()=>{
  66077. changeCount ++;
  66078. };
  66079. let median = Math.max(10, Potree.timeCollect.depthSampler.median);
  66080. let ifOverTime = ()=>{
  66081. let is = changeCount * median + getCount * 0.01 > maxWaitDur;//不换贴图也要一丢丢计算时间
  66082. /* if(is){
  66083. console.log(1)
  66084. } */
  66085. return is
  66086. };
  66087. this.depthSampler.addEventListener('changeImg', changeTexCount);
  66088. outer: for(let i=lastIndex,j=panos.length; i<j; i++){
  66089. let pano = panos[i];
  66090. let others = panos.slice(i+1, j);
  66091. lastIndex = i;
  66092. var g = Common$1.sortByScore(others, [ ], [
  66093. Images360.scoreFunctions.distanceSquared(pano.position)
  66094. ]);
  66095. for(let a=0, b=g.length; a<b; a++){
  66096. let item = g[a];
  66097. if(this.isNeighbour(pano, item.item, true) != void 0) continue
  66098. let byCloud = !pano.pointcloud.hasDepthTex;
  66099. let result = this.isNeighbour(pano, item.item, false, !byCloud, true);//计算
  66100. if(result != void 0){//计算了
  66101. //console.log('提前计算neighbor', pano.id, item.item.id)
  66102. this.dispatchEvent({type:'getNeighbourAuto', panos:[pano,item.item]});
  66103. if(byCloud){ //只计算一次
  66104. //console.log('提前计算neighbor byCloud', result, pano.id, item.item.id)
  66105. break outer;
  66106. }
  66107. getCount ++;
  66108. if(ifOverTime()){
  66109. break outer
  66110. }
  66111. }
  66112. }
  66113. lastIndex = i+1; //这轮结束
  66114. }
  66115. this.depthSampler.removeEventListener('changeImg', changeTexCount);
  66116. /* let costTime = Date.now() - startTime
  66117. costTime > maxWaitDur && console.log( 'costTime:',costTime) */
  66118. }
  66119. }();
  66120. Images360.filters = {
  66121. inPanoDirection : function(pos, dir, i, log) { //pano在mouse的方向上
  66122. return function(pano) {
  66123. var r = pano.floorPosition.clone().sub(pos).normalize();
  66124. var o = pano.position.clone().sub(pos).normalize();
  66125. log && console.log('dire',pano.id, r.dot(dir), o.dot(dir) );
  66126. return r.dot(dir) > i || o.dot(dir) > i
  66127. }
  66128. },
  66129. inFloorDirection: function(pos, dir, min, log) { //pano在mouse的水平方向上
  66130. return function(pano) {
  66131. var vec = new Vector2().subVectors(pano.floorPosition, pos).normalize();
  66132. var dir_ = new Vector2().copy(dir).normalize();
  66133. log && console.log('dire', pano.id, vec.dot(dir_) );
  66134. return vec.dot(dir_) > min
  66135. /* var i = pano.floorPosition.clone().sub(pos).setZ(0).normalize();//改成在xz方向上,否则点击墙面不会移动
  66136. return i.dot(dir.clone().setZ(0)) > min */
  66137. }
  66138. },
  66139. isNotBehindNormal: function(e, t) {
  66140. var i = new Vector3;
  66141. return t = t.clone(),
  66142. function(n) {
  66143. var r = i.copy(n.position).sub(e).normalize();
  66144. return r.dot(t) > 0
  66145. }
  66146. },
  66147. isCloseEnoughTo: function(e, t) {
  66148. return function(i) {//因为marker可能比地面高,所以识别范围要比marker看起来更近一些。(因为投影到地板的位置比marker更近)
  66149. return e.distanceTo(i.floorPosition) < t //许钟文
  66150. }
  66151. },
  66152. not: function(e) {
  66153. return function(t) {
  66154. return t !== e
  66155. }
  66156. } ,
  66157. isEnabled:function() {
  66158. return function(t) {
  66159. return t.enabled
  66160. }
  66161. },
  66162. isVisible:function() {
  66163. return function(t) {
  66164. return t.visible
  66165. }
  66166. }
  66167. };
  66168. Images360.scoreFunctions = {
  66169. direction: function(curPos, dir, ifLog) {
  66170. return function(pano) {
  66171. var pos1 = /* pano.floorPosition */ pano.position; //旧:改为权重放在marker上,这样对有斜坡的更准确,如上楼, 但这样近距离的pano角度就会向下了,以致于走不到
  66172. var n = pos1.clone().sub(curPos).normalize();
  66173. //ifLog && console.log('direction', pano.id, n.dot(dir) * directionFactor )
  66174. return n.dot(dir) * directionFactor
  66175. }
  66176. },
  66177. distance: function(pos1, r=1, ifLog) {
  66178. if(pos1.position)pos1 = pos1.position;
  66179. return function(pano) {//许钟文 改
  66180. var pos2 = pano.position.clone();
  66181. //ifLog && console.log('distance', pano.id, pos1.distance(pos2) * -1 )
  66182. return pos1.distanceTo(pos2) * -1 * r;
  66183. }
  66184. },
  66185. distanceSquared: function(pos1, r=1 ) {
  66186. if(pos1.position)pos1 = pos1.position;
  66187. return function(pano) {//许钟文 改
  66188. var pos2 = pano.position.clone();
  66189. return pos1.distanceToSquared(pos2) * -1 * r;
  66190. }
  66191. },
  66192. angle: function(e, t) {
  66193. return function(i) {
  66194. var n = i.position.clone().sub(e).normalize();
  66195. return n.angleTo(t) * Potree.config.navigation.angleFactor
  66196. }
  66197. },
  66198. };
  66199. Images360.sortFunctions = {//排序函数,涉及到两个item相减
  66200. floorDisSquaredToPoint: function(e) {
  66201. return function(t, i) {
  66202. return t.floorPosition.distanceToSquared(e) - i.floorPosition.distanceToSquared(e)
  66203. }
  66204. },
  66205. disSquaredToPoint: function(e) {
  66206. return function(t, i) {
  66207. return t.position.distanceToSquared(e) - i.position.distanceToSquared(e)
  66208. }
  66209. },
  66210. };
  66211. Images360.prototype.updateCube = (function(){//增加细分的版本,且垂直方向上取中位数 侧边多条
  66212. const minDis = 0.2; //pano和墙距离不能小于相机的near
  66213. const height = 1; //准确计算的话要分别计算两个pano的地面、天花板之间的俯仰角,和pano之间的还不一样。这里统一假设一个比较小的高度,因高度越大 maxSinAlpha 越大
  66214. let minTanBeta = minDis / height; /* (pano0.position.z - pano0.floorPosition.z) */
  66215. let minBeta = Math.atan(minTanBeta);
  66216. const maxSinAlpha = Math.cos(minBeta); // 注:beta = Math/2 - alpha
  66217. const skyHeight = 50;
  66218. return function(pano0, pano1){
  66219. if(Potree.settings.displayMode != 'showPanos' || pano0 == pano1
  66220. || this.cubePanos.includes(pano0) && this.cubePanos.includes(pano1)
  66221. ) return
  66222. this.cubePanos = [pano0, pano1];
  66223. viewer.addTimeMark('updateCube','start');
  66224. //console.log('updateCube',pano0.id, pano1&&pano1.id)
  66225. let useBound = (bound, size)=>{
  66226. size = size || bound.getSize(new Vector3);
  66227. let center = bound.getCenter(new Vector3);
  66228. size.max(new Vector3(HighMapCubeWidth,HighMapCubeWidth,HighMapCubeWidth));
  66229. this.cube.geometry = new BoxBufferGeometry(1,1,1,1);
  66230. this.cube.scale.copy(size);
  66231. this.cube.position.copy(center);
  66232. if(Potree.settings.testCube){
  66233. this.cubeTest.geometry = this.cube.geometry;
  66234. this.cubeTest.scale.copy(size);
  66235. this.cubeTest.position.copy(center);
  66236. }
  66237. return 'useBound'
  66238. };
  66239. let getPanoBound = (pano)=>{//因漫游点可能在点云外部,如室外平地,所以需要union进漫游点
  66240. let panoBound = new Box3;
  66241. panoBound.expandByPoint(pano.position);
  66242. panoBound.expandByVector(new Vector3(10,10,10));//give pano a margin
  66243. return pano.pointcloud.bound.clone().union(panoBound)
  66244. };
  66245. this.cube.geometry.dispose();
  66246. if(pano1){//过渡
  66247. let dontAddSides;
  66248. let dis = pano0.position.distanceTo(pano1.position);
  66249. let sinAlpha = Math.abs(pano0.position.z - pano1.position.z) / dis; //俯仰角的sin,随角度增大而增大 0-1
  66250. let score = (1+sinAlpha*20) * dis; //score越大创建的mesh越不适合
  66251. let isNeighbour = this.isNeighbour(pano0, pano1);
  66252. //console.log(pano0.id, pano1.id, maxSinAlpha.toFixed(2), sinAlpha.toFixed(2), score.toFixed(2), isNeighbour)
  66253. //let depthTiming = Potree.timeCollect.depthSampler.median //pc firefox达到4. chrome为0.01
  66254. if(sinAlpha>maxSinAlpha || !pano0.pointcloud.hasDepthTex || !pano1.pointcloud.hasDepthTex || (isNeighbour ? score > 100 : score > 50 ) ){
  66255. let bound = getPanoBound(pano0).union(getPanoBound(pano1));
  66256. let size = bound.getSize(new Vector3);
  66257. let max = Math.max(size.x, size.y, size.z);
  66258. size.set(max,max,max); //距离太远的数据集,过渡会畸变。所以扩大skybox,且为立方体
  66259. return useBound(bound, size)
  66260. }else if(/* depthTiming > 1 || */ (isNeighbour ? score > 70 : score > 15)){
  66261. dontAddSides = true; //pano间有阻挡时得到的side点可能使通道变窄,所以去掉。
  66262. }
  66263. //俯仰角增大时可能不在同一楼层,算出来的mesh不太好,所以更倾向直接使用cube,或去除side。
  66264. let half; //6 : (browser.isMobile() ? 2 : 3) //自行输入 (点云计算的慢,还不准)
  66265. {
  66266. let min = 3,max = 6, minTime = 0, maxTime = 3;
  66267. /* half = math.linearClamp(depthTiming, minTime,maxTime, max,min)
  66268. half = Math.round(half) */
  66269. half = max;
  66270. }
  66271. let count1 = 2*half;//偶数个 每个pano向 外dir 个数
  66272. //奇数个的好处:在窄空间内能探测到最远距离,坏处是前方有尖角。偶数个的坏处就是可能检测距离太近。
  66273. //let panoIndex = 0
  66274. let getDir = (angle_, vec)=>{ //旋转获得水平向量
  66275. let rotMat = new Matrix4().makeRotationZ(angle_);
  66276. return vec.clone().applyMatrix4(rotMat)
  66277. };
  66278. let getFar = (dir, pano, origin, height)=>{//获取在这个方向上和墙体intersect的距离
  66279. //在垂直方向上分出多个方向,取一个最可能的接近真实的距离
  66280. let maxH = 40, minH = 2, minR = 0.5, maxR = 2;
  66281. height = height == void 0 ? (Math.min(skyHeight,pano.ceilZ) - pano.floorPosition.z) : height;
  66282. //let r = height (maxH - minH)* 0.14 // 高度越小,角度越小
  66283. //let r = minR + ( maxR - minR) * THREE.Math.clamp((height - minH) / (maxH - minH),0,1) //THREE.Math.smoothstep(currentDis, op.nearBound, op.farBound);
  66284. let r = math.linearClamp(height, minH,maxH, minR, maxR);
  66285. let getZ = (deg)=>{
  66286. deg *= r;
  66287. deg = MathUtils$1.clamp(deg, 1, 80);
  66288. return Math.tan(MathUtils$1.degToRad(deg))
  66289. };
  66290. let dirs_; //注意:角度太大会碰到天花板或地板,越远越容易碰到, 在地下停车场就会伸展不开。 户外时需要更多向上的方向,所以上方向多一个
  66291. /* if(depthTiming > 2) dirs_ = [35,0,-5]
  66292. else if(depthTiming > 0.5) dirs_ = [35,10,0,-5]
  66293. else */dirs_ = [35,20,7, 0,-5];
  66294. dirs_ = dirs_.map(deg=> dir.clone().setZ(getZ(deg)).normalize() );
  66295. let max = 50;
  66296. let count2 = dirs_.length;
  66297. let disArr = dirs_.map((dir_, i) =>{
  66298. let intersect = this.getIntersect(pano, dir_, origin);
  66299. let projectLen = intersect && intersect.distance ? dir_.dot(dir)*intersect.distance : max; //得到project在dir的长度
  66300. return projectLen //得水平距离
  66301. });
  66302. //console.log(pano ? pano.id : 'side','disArr', disArr.slice(0))
  66303. disArr.sort((a,b)=>{return b-a}); //从大到小
  66304. //console.log(pano ? pano.id : 'side','disArr', disArr)
  66305. let dis = disArr[Math.floor(count2/2-0.5)]; //对半、取前(中位数)
  66306. return dis
  66307. };
  66308. let sideCount = [0,0];
  66309. let addPos = (pano, vec )=>{//添加这个pano这一侧向外半圆的顶点
  66310. //添加pano位置对应的最高点最低点:
  66311. let minZ, maxZ;
  66312. minZ = pano.floorPosition.z;
  66313. maxZ = pano.getCeilHeight();
  66314. if(maxZ == Infinity) maxZ = skyHeight; //maxZ = Math.max(skyHeight, maxZ)
  66315. [maxZ, minZ ].forEach(z=>{
  66316. posArr.push(pano.position.clone().setZ(z));
  66317. });
  66318. //在画面上线条从左往右数
  66319. const angle = Math.PI/(count1-1);
  66320. const dirs = []; //平分这半边180度
  66321. for(let i=0;i<count1;i++){
  66322. dirs.push(getDir(Math.PI/2-i*angle, vec));//正的在左边
  66323. }
  66324. let dirs2 = dirs.map((dir)=>{
  66325. return {
  66326. dir,
  66327. dis: getFar(dir, pano)
  66328. }
  66329. });
  66330. //剔除那些突然间离相机很近的dir。有可能是拍摄的人、或者杆子、树
  66331. /* dirs2.forEach((e,i)=>{
  66332. console.log(i, e.dis)
  66333. let smallThanBefore = ()=>{
  66334. return dirs2[i-1].dis / e.dis > maxRatio
  66335. }
  66336. let smallThanAfter = ()=>{
  66337. return dirs2[i+1].dis / e.dis > maxRatio
  66338. }
  66339. if(i>0 && i<count1-1 && smallThanBefore() && smallThanAfter()){//比左右两边都小很多
  66340. e.disB = (dirs2[i-1].dis + dirs2[i+1].dis) / 2 //平均数
  66341. console.log('两者之间',i,e.disB)
  66342. }else if(i==count1-1 && smallThanBefore() ) {//比前者小很多
  66343. e.disB = dirs2[i-1].dis * 0.8
  66344. console.log('smallThanBefore', i, e.disB)
  66345. }else if(i==0 && smallThanAfter() ){//比后者小很多
  66346. e.disB = dirs2[i+1].dis * 0.8
  66347. console.log('smallThanAftere', i, e.disB)
  66348. }
  66349. }) */
  66350. const maxRatio1 = 3 , maxRatio2 = 8; //超过maxRatio1就要加入判断,而最终结果的设限其实是maxRatio2
  66351. const minWidth = 0.5;
  66352. let computeWidth = (start,end)=>{
  66353. start+=1; //不包含start和end
  66354. let count = end - start ;
  66355. let dis = 0;
  66356. for(let m=start;m<end;m++){//得平均数
  66357. dis += dirs2[m].dis;
  66358. }
  66359. dis /= count;
  66360. let angle = Math.PI / (count1-1) * count / 2;
  66361. let width = dis * Math.tan(angle); //得到block的半宽度
  66362. return width
  66363. };
  66364. let changeDis = (start,end )=>{ //不包含start
  66365. start+=1; //不包含start和end
  66366. for(let m=start;m<end;m++){
  66367. dirs2[m].disB = dirs2[end].dis * 0.8;
  66368. //console.log('changeDis', m, dirs2[m].disB)
  66369. }
  66370. };
  66371. let start = -1;
  66372. for(let i=0;i<count1;i++){//遍历时将左边dis比之小很多且宽度较小的改大
  66373. //console.log(i, dirs2[i].dis)
  66374. let j = i-1;
  66375. let ratios = 0;
  66376. while(j>start && dirs2[i].dis / dirs2[j].dis > maxRatio1){
  66377. ratios += dirs2[i].dis / dirs2[j].dis;
  66378. j--;
  66379. }
  66380. let count = i-j-1;
  66381. ratios /= count;
  66382. if(count > 0 && computeWidth(j,i)< minWidth * ratios / maxRatio2 ){ //怎么感觉好像改成了视觉宽度小于某个值即可,那直接用count好了?
  66383. changeDis(j,i);
  66384. start = i; //在此之前的修改过,之后不用再判断
  66385. }
  66386. /* if(count > 0 && (count == 1 || computeWidth(j,i)<minWidth)){//若只有一个不用判断宽度直接修改
  66387. changeDis(j,i)
  66388. start = i //在此之前的修改过,之后不用再判断
  66389. } */
  66390. }
  66391. dirs2.forEach((e, index)=>{
  66392. let dir = e.dir.clone().multiplyScalar(e.disB || e.dis);
  66393. [maxZ,minZ].forEach(z=>{
  66394. posArr.push(pano.position.clone().setZ(z).add(dir)); //获取到外墙点
  66395. });
  66396. });
  66397. };
  66398. let addSide = ()=>{//两个漫游点间两边各加一些侧线
  66399. //中点处的
  66400. let top0 = pano0.ceilZ == Infinity ? skyHeight : pano0.ceilZ;
  66401. let top1 = pano1.ceilZ == Infinity ? skyHeight : pano1.ceilZ;
  66402. let midMaxZ = (top0 + top1)/2;
  66403. let midMinZ = (pano0.floorPosition.z+pano1.floorPosition.z)/2;
  66404. let mid = new Vector3().addVectors(pano0.position, pano1.position).multiplyScalar(0.5);
  66405. if(!dontAddSides){
  66406. if( pano0.pointcloud.hasDepthTex && pano0.pointcloud.hasDepthTex){
  66407. let panos = [pano0,pano1];
  66408. let vecs = [vec.clone().negate(), vec];
  66409. let axis = [[-1,1],[1,-1]];
  66410. let dis2d = new Vector2().subVectors(pano0.position, pano1.position).length();//水平上的距离
  66411. let maxDis = 50, minDis = 0.5, minR = 0.2, maxR = 1.2;
  66412. //let r = maxR - ( maxR - minR) * THREE.Math.clamp((dis2d - minDis) / (maxDis - minDis),0,1) //dis2d越大,角度要越小 //THREE.Math.smoothstep(currentDis, op.nearBound, op.farBound);
  66413. let r = math.linearClamp(dis2d, minDis,maxDis, maxR, minR);
  66414. //console.log('dis2d',dis2d,'r',r)
  66415. let angles = (browser.isMobile ? [50] : [35,65]).map(deg=>{ //正的在左边 尽量能够平分中间这段墙体。 (角度为从中心向外)
  66416. let angle = MathUtils$1.clamp(deg * r, 5, 80);
  66417. //console.log('angle',angle)
  66418. return MathUtils$1.degToRad(angle)
  66419. });
  66420. axis.forEach((axis_, index0)=>{
  66421. let disToSides = [];
  66422. let accordingPano = index0 == 0 ? pano0 : pano1; //根据离该点在vec方向上的距离顺序来存顶点
  66423. panos.forEach((pano,index)=>{
  66424. let dirs = angles.map(angle=>getDir(axis_[index]*angle, vecs[index]));//一侧的若干角度
  66425. dirs.forEach((dir_,i)=>{
  66426. let dis1 = getFar(dir_, pano);
  66427. let disToPano2d = dis1 * Math.cos(angles[i]);
  66428. if(disToPano2d<dis2d){//超过的话都到另一半pano的半圆了,不计入
  66429. let disToSide = dis1 * Math.sin(angles[i]);
  66430. if(pano != accordingPano){
  66431. disToPano2d = dis2d - disToPano2d; //反一下
  66432. }
  66433. dir_.multiplyScalar( dis1 );
  66434. disToSides.push({disToSide,disToPano2d, pano, dir_});
  66435. }
  66436. });
  66437. });
  66438. if(disToSides.length){
  66439. //disToSides.sort((a,b)=>{return b-a});//从大到小
  66440. //由距离accordingPano的近到远:
  66441. disToSides.sort((a,b)=>{return a.disToPano2d-b.disToPano2d});
  66442. //console.log('disToSides', index0, disToSides)
  66443. if(disToSides.length == 1 && disToSides[0].disToSide < 0.5){
  66444. disToSides = []; //如果太近直接去除
  66445. }
  66446. disToSides.forEach(e=>{//求z
  66447. let ratio = e.disToPano2d / dis2d;
  66448. let r = accordingPano == pano0 ? (1-ratio) : ratio;
  66449. let sideMaxZ_ = top0 * r + top1 * (1-r);
  66450. let sideMinZ_ = pano0.floorPosition.z * r + pano1.floorPosition.z * (1-r);
  66451. [sideMaxZ_,sideMinZ_].forEach(z=>{
  66452. posArr.push(e.pano.position.clone().setZ(z).add(e.dir_)); //是直接使用最长dis的那个intersect点好还是mid
  66453. });
  66454. });
  66455. }
  66456. sideCount[index0] = disToSides.length; //记录侧边个数
  66457. });
  66458. }else {
  66459. //这段针对点云时,仅测试才会执行到
  66460. sideCount = [1,1];
  66461. let sideDirs = [getDir(Math.PI/2, vec), getDir(-Math.PI/2, vec)];
  66462. sideDirs.forEach((dir_ ,index)=>{
  66463. let dis = getFar(dir_, null, mid, midMaxZ-midMinZ); //直接从中点求两侧的距离
  66464. dir_.multiplyScalar( /* Math.max( */dis/* , sideDis[index]) */ );
  66465. [midMaxZ,midMinZ].forEach(z=>{
  66466. posArr.push(mid.clone().setZ(z).add(dir_));
  66467. });
  66468. });
  66469. }
  66470. }
  66471. //中心:
  66472. [midMaxZ,midMinZ].forEach(z=>{
  66473. posArr.push(mid.clone().setZ(z));
  66474. });
  66475. };
  66476. //positions存放顺序:pano的每边的 zMax和zMin 、count1个dir的点 ;侧边的点 ;连接处顶底的中点
  66477. let addFaces = ()=>{
  66478. let getPI = function(index, posType, panoIndex){//获取顶点序号
  66479. return 2 + (count1*2 + 2 ) * panoIndex + index*2 + (posType == 'top' ? 0 : 1)
  66480. };
  66481. let getSidePI = function(index, posType, panoIndex){//获取侧边顶点序号
  66482. if(panoIndex == 1) index += sideCount[0];
  66483. return getPI(index, posType, 2)-2
  66484. };
  66485. let getPanoPI = function(posType, panoIndex){//获取pano处对应的点序号
  66486. return getPI(-1, posType, panoIndex)
  66487. };
  66488. let topCenter = posArr.length-2; //最后添加的两个中心点
  66489. let btmCenter = posArr.length-1;
  66490. for(let i=0;i<2;i++){
  66491. for(let index=1; index<count1; index++){
  66492. //pano外侧半圆围墙
  66493. faceArr.push([getPI(index,'top',i), getPI(index-1,'btm',i), getPI(index-1,'top',i)],//加入一块四方面
  66494. [getPI(index,'top',i), getPI(index,'btm',i), getPI(index-1,'btm',i)]);
  66495. faceArr.push([getPI(index,'top',i), getPI(index-1,'top',i), getPanoPI('top',i)]);//天花板扇形
  66496. faceArr.push([getPI(index,'btm',i), getPI(index-1,'btm',i), getPanoPI('btm',i)]);//地板扇形
  66497. }
  66498. let j = (i + 1) % 2; //另一个pano
  66499. //侧边
  66500. for(let u=0; u<=sideCount[i]; u++){
  66501. //侧边每个四方的左上右上左下右下四个点
  66502. let pLT = u == 0 ? getPI(0,'top',i) : getSidePI(u-1, 'top',i);
  66503. let pRT = u == sideCount[i] ? getPI(count1-1,'top',j) : getSidePI(u, 'top',i);
  66504. let pLB = u == 0 ? getPI(0,'btm',i) : getSidePI(u-1, 'btm',i);
  66505. let pRB = u == sideCount[i] ? getPI(count1-1,'btm',j) : getSidePI(u, 'btm',i);
  66506. faceArr.push([pLT,pLB,pRB],[pLT,pRB,pRT]);//外侧四方面
  66507. faceArr.push([pLT,topCenter,pRT] ,[pLB,btmCenter,pRB] );//顶部和底部到整体中心的扇形(由于点的顺序是根据和两个pano的距离,因此到中心的夹角并没按顺序排列,所以可能会重叠)
  66508. if(i==0){//只需要算一次
  66509. //顶部和底部中心与两个pano边构成的三角形
  66510. if(u == 0){
  66511. faceArr.push([pLT,getPI(count1-1,'top',i),topCenter],
  66512. [pLB,getPI(count1-1,'btm',i),btmCenter],
  66513. );
  66514. }
  66515. //不能用else 因为当length==0时u==0也==sideCount[i],此时就是要两个面
  66516. if(u == sideCount[i]){
  66517. faceArr.push([pRT,getPI(0,'top',j),topCenter],
  66518. [pRB,getPI(0,'btm',j),btmCenter],
  66519. );
  66520. }
  66521. }
  66522. }
  66523. }
  66524. };
  66525. let posArr = [];
  66526. let faceArr = [];
  66527. //两点连线的水平向量
  66528. let vec = new Vector3().subVectors(pano0.position, pano1.position).setZ(0).normalize();
  66529. /* let sideDis0 = */addPos(pano0, vec);
  66530. /* let sideDis1 = */addPos(pano1, vec.clone().negate());
  66531. addSide();
  66532. addFaces();
  66533. //MeshDraw.updateGeometry(this.cube.geometry, posArr, faceArr)
  66534. let geo = MeshDraw.createGeometry(posArr, faceArr);
  66535. this.cube.geometry = geo;
  66536. this.cube.scale.set(1,1,1);
  66537. this.cube.position.set(0,0,0);
  66538. if(Potree.settings.testCube){
  66539. this.cubeTest.geometry = geo;
  66540. this.cubeTest.scale.set(1,1,1);
  66541. this.cubeTest.position.set(0,0,0);
  66542. }
  66543. }else {
  66544. useBound(getPanoBound(pano0));
  66545. }
  66546. viewer.addTimeMark('updateCube','end');
  66547. return true
  66548. /*
  66549. 关于卡顿:
  66550. 即使使用cube,若scale设置为只容纳两个pano,也会卡顿。但也是有的卡有的不卡。
  66551. 若按照原先的复杂geo,一般在平直的街道上行走流畅,经过拐弯或者复杂区域较卡。减小geo复杂度没有什么作用。
  66552. 注: 修改skybox,若不准的话,会遮住其他mesh,比如marker。尤其在没有深度贴图时。
  66553. 耗时: chrome: 20+ ,但是firefox:500+ 咋回事 ? iphonex safari: 40+
  66554. */
  66555. }
  66556. })();
  66557. /*
  66558. 检查贴图是否释放:
  66559. viewer.images360.panos.filter(e=>e.skyboxTex && e.skyboxTex._listeners && e.skyboxTex._listeners.dispose && e.skyboxTex._listeners.dispose.length)
  66560. */
  66561. // This is a generated file. Do not edit.
  66562. var Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/;
  66563. var ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/;
  66564. var ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/;
  66565. var unicode = {
  66566. Space_Separator: Space_Separator,
  66567. ID_Start: ID_Start,
  66568. ID_Continue: ID_Continue
  66569. };
  66570. var util = {
  66571. isSpaceSeparator (c) {
  66572. return typeof c === 'string' && unicode.Space_Separator.test(c)
  66573. },
  66574. isIdStartChar (c) {
  66575. return typeof c === 'string' && (
  66576. (c >= 'a' && c <= 'z') ||
  66577. (c >= 'A' && c <= 'Z') ||
  66578. (c === '$') || (c === '_') ||
  66579. unicode.ID_Start.test(c)
  66580. )
  66581. },
  66582. isIdContinueChar (c) {
  66583. return typeof c === 'string' && (
  66584. (c >= 'a' && c <= 'z') ||
  66585. (c >= 'A' && c <= 'Z') ||
  66586. (c >= '0' && c <= '9') ||
  66587. (c === '$') || (c === '_') ||
  66588. (c === '\u200C') || (c === '\u200D') ||
  66589. unicode.ID_Continue.test(c)
  66590. )
  66591. },
  66592. isDigit (c) {
  66593. return typeof c === 'string' && /[0-9]/.test(c)
  66594. },
  66595. isHexDigit (c) {
  66596. return typeof c === 'string' && /[0-9A-Fa-f]/.test(c)
  66597. },
  66598. };
  66599. let source;
  66600. let parseState;
  66601. let stack$1;
  66602. let pos;
  66603. let line;
  66604. let column;
  66605. let token;
  66606. let key;
  66607. let root;
  66608. var parse = function parse (text, reviver) {
  66609. source = String(text);
  66610. parseState = 'start';
  66611. stack$1 = [];
  66612. pos = 0;
  66613. line = 1;
  66614. column = 0;
  66615. token = undefined;
  66616. key = undefined;
  66617. root = undefined;
  66618. do {
  66619. token = lex();
  66620. // This code is unreachable.
  66621. // if (!parseStates[parseState]) {
  66622. // throw invalidParseState()
  66623. // }
  66624. parseStates[parseState]();
  66625. } while (token.type !== 'eof')
  66626. if (typeof reviver === 'function') {
  66627. return internalize({'': root}, '', reviver)
  66628. }
  66629. return root
  66630. };
  66631. function internalize (holder, name, reviver) {
  66632. const value = holder[name];
  66633. if (value != null && typeof value === 'object') {
  66634. for (const key in value) {
  66635. const replacement = internalize(value, key, reviver);
  66636. if (replacement === undefined) {
  66637. delete value[key];
  66638. } else {
  66639. value[key] = replacement;
  66640. }
  66641. }
  66642. }
  66643. return reviver.call(holder, name, value)
  66644. }
  66645. let lexState;
  66646. let buffer;
  66647. let doubleQuote;
  66648. let sign$1;
  66649. let c;
  66650. function lex () {
  66651. lexState = 'default';
  66652. buffer = '';
  66653. doubleQuote = false;
  66654. sign$1 = 1;
  66655. for (;;) {
  66656. c = peek();
  66657. // This code is unreachable.
  66658. // if (!lexStates[lexState]) {
  66659. // throw invalidLexState(lexState)
  66660. // }
  66661. const token = lexStates[lexState]();
  66662. if (token) {
  66663. return token
  66664. }
  66665. }
  66666. }
  66667. function peek () {
  66668. if (source[pos]) {
  66669. return String.fromCodePoint(source.codePointAt(pos))
  66670. }
  66671. }
  66672. function read () {
  66673. const c = peek();
  66674. if (c === '\n') {
  66675. line++;
  66676. column = 0;
  66677. } else if (c) {
  66678. column += c.length;
  66679. } else {
  66680. column++;
  66681. }
  66682. if (c) {
  66683. pos += c.length;
  66684. }
  66685. return c
  66686. }
  66687. const lexStates = {
  66688. default () {
  66689. switch (c) {
  66690. case '\t':
  66691. case '\v':
  66692. case '\f':
  66693. case ' ':
  66694. case '\u00A0':
  66695. case '\uFEFF':
  66696. case '\n':
  66697. case '\r':
  66698. case '\u2028':
  66699. case '\u2029':
  66700. read();
  66701. return
  66702. case '/':
  66703. read();
  66704. lexState = 'comment';
  66705. return
  66706. case undefined:
  66707. read();
  66708. return newToken('eof')
  66709. }
  66710. if (util.isSpaceSeparator(c)) {
  66711. read();
  66712. return
  66713. }
  66714. // This code is unreachable.
  66715. // if (!lexStates[parseState]) {
  66716. // throw invalidLexState(parseState)
  66717. // }
  66718. return lexStates[parseState]()
  66719. },
  66720. comment () {
  66721. switch (c) {
  66722. case '*':
  66723. read();
  66724. lexState = 'multiLineComment';
  66725. return
  66726. case '/':
  66727. read();
  66728. lexState = 'singleLineComment';
  66729. return
  66730. }
  66731. throw invalidChar(read())
  66732. },
  66733. multiLineComment () {
  66734. switch (c) {
  66735. case '*':
  66736. read();
  66737. lexState = 'multiLineCommentAsterisk';
  66738. return
  66739. case undefined:
  66740. throw invalidChar(read())
  66741. }
  66742. read();
  66743. },
  66744. multiLineCommentAsterisk () {
  66745. switch (c) {
  66746. case '*':
  66747. read();
  66748. return
  66749. case '/':
  66750. read();
  66751. lexState = 'default';
  66752. return
  66753. case undefined:
  66754. throw invalidChar(read())
  66755. }
  66756. read();
  66757. lexState = 'multiLineComment';
  66758. },
  66759. singleLineComment () {
  66760. switch (c) {
  66761. case '\n':
  66762. case '\r':
  66763. case '\u2028':
  66764. case '\u2029':
  66765. read();
  66766. lexState = 'default';
  66767. return
  66768. case undefined:
  66769. read();
  66770. return newToken('eof')
  66771. }
  66772. read();
  66773. },
  66774. value () {
  66775. switch (c) {
  66776. case '{':
  66777. case '[':
  66778. return newToken('punctuator', read())
  66779. case 'n':
  66780. read();
  66781. literal('ull');
  66782. return newToken('null', null)
  66783. case 't':
  66784. read();
  66785. literal('rue');
  66786. return newToken('boolean', true)
  66787. case 'f':
  66788. read();
  66789. literal('alse');
  66790. return newToken('boolean', false)
  66791. case '-':
  66792. case '+':
  66793. if (read() === '-') {
  66794. sign$1 = -1;
  66795. }
  66796. lexState = 'sign';
  66797. return
  66798. case '.':
  66799. buffer = read();
  66800. lexState = 'decimalPointLeading';
  66801. return
  66802. case '0':
  66803. buffer = read();
  66804. lexState = 'zero';
  66805. return
  66806. case '1':
  66807. case '2':
  66808. case '3':
  66809. case '4':
  66810. case '5':
  66811. case '6':
  66812. case '7':
  66813. case '8':
  66814. case '9':
  66815. buffer = read();
  66816. lexState = 'decimalInteger';
  66817. return
  66818. case 'I':
  66819. read();
  66820. literal('nfinity');
  66821. return newToken('numeric', Infinity)
  66822. case 'N':
  66823. read();
  66824. literal('aN');
  66825. return newToken('numeric', NaN)
  66826. case '"':
  66827. case "'":
  66828. doubleQuote = (read() === '"');
  66829. buffer = '';
  66830. lexState = 'string';
  66831. return
  66832. }
  66833. throw invalidChar(read())
  66834. },
  66835. identifierNameStartEscape () {
  66836. if (c !== 'u') {
  66837. throw invalidChar(read())
  66838. }
  66839. read();
  66840. const u = unicodeEscape();
  66841. switch (u) {
  66842. case '$':
  66843. case '_':
  66844. break
  66845. default:
  66846. if (!util.isIdStartChar(u)) {
  66847. throw invalidIdentifier()
  66848. }
  66849. break
  66850. }
  66851. buffer += u;
  66852. lexState = 'identifierName';
  66853. },
  66854. identifierName () {
  66855. switch (c) {
  66856. case '$':
  66857. case '_':
  66858. case '\u200C':
  66859. case '\u200D':
  66860. buffer += read();
  66861. return
  66862. case '\\':
  66863. read();
  66864. lexState = 'identifierNameEscape';
  66865. return
  66866. }
  66867. if (util.isIdContinueChar(c)) {
  66868. buffer += read();
  66869. return
  66870. }
  66871. return newToken('identifier', buffer)
  66872. },
  66873. identifierNameEscape () {
  66874. if (c !== 'u') {
  66875. throw invalidChar(read())
  66876. }
  66877. read();
  66878. const u = unicodeEscape();
  66879. switch (u) {
  66880. case '$':
  66881. case '_':
  66882. case '\u200C':
  66883. case '\u200D':
  66884. break
  66885. default:
  66886. if (!util.isIdContinueChar(u)) {
  66887. throw invalidIdentifier()
  66888. }
  66889. break
  66890. }
  66891. buffer += u;
  66892. lexState = 'identifierName';
  66893. },
  66894. sign () {
  66895. switch (c) {
  66896. case '.':
  66897. buffer = read();
  66898. lexState = 'decimalPointLeading';
  66899. return
  66900. case '0':
  66901. buffer = read();
  66902. lexState = 'zero';
  66903. return
  66904. case '1':
  66905. case '2':
  66906. case '3':
  66907. case '4':
  66908. case '5':
  66909. case '6':
  66910. case '7':
  66911. case '8':
  66912. case '9':
  66913. buffer = read();
  66914. lexState = 'decimalInteger';
  66915. return
  66916. case 'I':
  66917. read();
  66918. literal('nfinity');
  66919. return newToken('numeric', sign$1 * Infinity)
  66920. case 'N':
  66921. read();
  66922. literal('aN');
  66923. return newToken('numeric', NaN)
  66924. }
  66925. throw invalidChar(read())
  66926. },
  66927. zero () {
  66928. switch (c) {
  66929. case '.':
  66930. buffer += read();
  66931. lexState = 'decimalPoint';
  66932. return
  66933. case 'e':
  66934. case 'E':
  66935. buffer += read();
  66936. lexState = 'decimalExponent';
  66937. return
  66938. case 'x':
  66939. case 'X':
  66940. buffer += read();
  66941. lexState = 'hexadecimal';
  66942. return
  66943. }
  66944. return newToken('numeric', sign$1 * 0)
  66945. },
  66946. decimalInteger () {
  66947. switch (c) {
  66948. case '.':
  66949. buffer += read();
  66950. lexState = 'decimalPoint';
  66951. return
  66952. case 'e':
  66953. case 'E':
  66954. buffer += read();
  66955. lexState = 'decimalExponent';
  66956. return
  66957. }
  66958. if (util.isDigit(c)) {
  66959. buffer += read();
  66960. return
  66961. }
  66962. return newToken('numeric', sign$1 * Number(buffer))
  66963. },
  66964. decimalPointLeading () {
  66965. if (util.isDigit(c)) {
  66966. buffer += read();
  66967. lexState = 'decimalFraction';
  66968. return
  66969. }
  66970. throw invalidChar(read())
  66971. },
  66972. decimalPoint () {
  66973. switch (c) {
  66974. case 'e':
  66975. case 'E':
  66976. buffer += read();
  66977. lexState = 'decimalExponent';
  66978. return
  66979. }
  66980. if (util.isDigit(c)) {
  66981. buffer += read();
  66982. lexState = 'decimalFraction';
  66983. return
  66984. }
  66985. return newToken('numeric', sign$1 * Number(buffer))
  66986. },
  66987. decimalFraction () {
  66988. switch (c) {
  66989. case 'e':
  66990. case 'E':
  66991. buffer += read();
  66992. lexState = 'decimalExponent';
  66993. return
  66994. }
  66995. if (util.isDigit(c)) {
  66996. buffer += read();
  66997. return
  66998. }
  66999. return newToken('numeric', sign$1 * Number(buffer))
  67000. },
  67001. decimalExponent () {
  67002. switch (c) {
  67003. case '+':
  67004. case '-':
  67005. buffer += read();
  67006. lexState = 'decimalExponentSign';
  67007. return
  67008. }
  67009. if (util.isDigit(c)) {
  67010. buffer += read();
  67011. lexState = 'decimalExponentInteger';
  67012. return
  67013. }
  67014. throw invalidChar(read())
  67015. },
  67016. decimalExponentSign () {
  67017. if (util.isDigit(c)) {
  67018. buffer += read();
  67019. lexState = 'decimalExponentInteger';
  67020. return
  67021. }
  67022. throw invalidChar(read())
  67023. },
  67024. decimalExponentInteger () {
  67025. if (util.isDigit(c)) {
  67026. buffer += read();
  67027. return
  67028. }
  67029. return newToken('numeric', sign$1 * Number(buffer))
  67030. },
  67031. hexadecimal () {
  67032. if (util.isHexDigit(c)) {
  67033. buffer += read();
  67034. lexState = 'hexadecimalInteger';
  67035. return
  67036. }
  67037. throw invalidChar(read())
  67038. },
  67039. hexadecimalInteger () {
  67040. if (util.isHexDigit(c)) {
  67041. buffer += read();
  67042. return
  67043. }
  67044. return newToken('numeric', sign$1 * Number(buffer))
  67045. },
  67046. string () {
  67047. switch (c) {
  67048. case '\\':
  67049. read();
  67050. buffer += escape$1();
  67051. return
  67052. case '"':
  67053. if (doubleQuote) {
  67054. read();
  67055. return newToken('string', buffer)
  67056. }
  67057. buffer += read();
  67058. return
  67059. case "'":
  67060. if (!doubleQuote) {
  67061. read();
  67062. return newToken('string', buffer)
  67063. }
  67064. buffer += read();
  67065. return
  67066. case '\n':
  67067. case '\r':
  67068. throw invalidChar(read())
  67069. case '\u2028':
  67070. case '\u2029':
  67071. separatorChar(c);
  67072. break
  67073. case undefined:
  67074. throw invalidChar(read())
  67075. }
  67076. buffer += read();
  67077. },
  67078. start () {
  67079. switch (c) {
  67080. case '{':
  67081. case '[':
  67082. return newToken('punctuator', read())
  67083. // This code is unreachable since the default lexState handles eof.
  67084. // case undefined:
  67085. // return newToken('eof')
  67086. }
  67087. lexState = 'value';
  67088. },
  67089. beforePropertyName () {
  67090. switch (c) {
  67091. case '$':
  67092. case '_':
  67093. buffer = read();
  67094. lexState = 'identifierName';
  67095. return
  67096. case '\\':
  67097. read();
  67098. lexState = 'identifierNameStartEscape';
  67099. return
  67100. case '}':
  67101. return newToken('punctuator', read())
  67102. case '"':
  67103. case "'":
  67104. doubleQuote = (read() === '"');
  67105. lexState = 'string';
  67106. return
  67107. }
  67108. if (util.isIdStartChar(c)) {
  67109. buffer += read();
  67110. lexState = 'identifierName';
  67111. return
  67112. }
  67113. throw invalidChar(read())
  67114. },
  67115. afterPropertyName () {
  67116. if (c === ':') {
  67117. return newToken('punctuator', read())
  67118. }
  67119. throw invalidChar(read())
  67120. },
  67121. beforePropertyValue () {
  67122. lexState = 'value';
  67123. },
  67124. afterPropertyValue () {
  67125. switch (c) {
  67126. case ',':
  67127. case '}':
  67128. return newToken('punctuator', read())
  67129. }
  67130. throw invalidChar(read())
  67131. },
  67132. beforeArrayValue () {
  67133. if (c === ']') {
  67134. return newToken('punctuator', read())
  67135. }
  67136. lexState = 'value';
  67137. },
  67138. afterArrayValue () {
  67139. switch (c) {
  67140. case ',':
  67141. case ']':
  67142. return newToken('punctuator', read())
  67143. }
  67144. throw invalidChar(read())
  67145. },
  67146. end () {
  67147. // This code is unreachable since it's handled by the default lexState.
  67148. // if (c === undefined) {
  67149. // read()
  67150. // return newToken('eof')
  67151. // }
  67152. throw invalidChar(read())
  67153. },
  67154. };
  67155. function newToken (type, value) {
  67156. return {
  67157. type,
  67158. value,
  67159. line,
  67160. column,
  67161. }
  67162. }
  67163. function literal (s) {
  67164. for (const c of s) {
  67165. const p = peek();
  67166. if (p !== c) {
  67167. throw invalidChar(read())
  67168. }
  67169. read();
  67170. }
  67171. }
  67172. function escape$1 () {
  67173. const c = peek();
  67174. switch (c) {
  67175. case 'b':
  67176. read();
  67177. return '\b'
  67178. case 'f':
  67179. read();
  67180. return '\f'
  67181. case 'n':
  67182. read();
  67183. return '\n'
  67184. case 'r':
  67185. read();
  67186. return '\r'
  67187. case 't':
  67188. read();
  67189. return '\t'
  67190. case 'v':
  67191. read();
  67192. return '\v'
  67193. case '0':
  67194. read();
  67195. if (util.isDigit(peek())) {
  67196. throw invalidChar(read())
  67197. }
  67198. return '\0'
  67199. case 'x':
  67200. read();
  67201. return hexEscape()
  67202. case 'u':
  67203. read();
  67204. return unicodeEscape()
  67205. case '\n':
  67206. case '\u2028':
  67207. case '\u2029':
  67208. read();
  67209. return ''
  67210. case '\r':
  67211. read();
  67212. if (peek() === '\n') {
  67213. read();
  67214. }
  67215. return ''
  67216. case '1':
  67217. case '2':
  67218. case '3':
  67219. case '4':
  67220. case '5':
  67221. case '6':
  67222. case '7':
  67223. case '8':
  67224. case '9':
  67225. throw invalidChar(read())
  67226. case undefined:
  67227. throw invalidChar(read())
  67228. }
  67229. return read()
  67230. }
  67231. function hexEscape () {
  67232. let buffer = '';
  67233. let c = peek();
  67234. if (!util.isHexDigit(c)) {
  67235. throw invalidChar(read())
  67236. }
  67237. buffer += read();
  67238. c = peek();
  67239. if (!util.isHexDigit(c)) {
  67240. throw invalidChar(read())
  67241. }
  67242. buffer += read();
  67243. return String.fromCodePoint(parseInt(buffer, 16))
  67244. }
  67245. function unicodeEscape () {
  67246. let buffer = '';
  67247. let count = 4;
  67248. while (count-- > 0) {
  67249. const c = peek();
  67250. if (!util.isHexDigit(c)) {
  67251. throw invalidChar(read())
  67252. }
  67253. buffer += read();
  67254. }
  67255. return String.fromCodePoint(parseInt(buffer, 16))
  67256. }
  67257. const parseStates = {
  67258. start () {
  67259. if (token.type === 'eof') {
  67260. throw invalidEOF()
  67261. }
  67262. push();
  67263. },
  67264. beforePropertyName () {
  67265. switch (token.type) {
  67266. case 'identifier':
  67267. case 'string':
  67268. key = token.value;
  67269. parseState = 'afterPropertyName';
  67270. return
  67271. case 'punctuator':
  67272. // This code is unreachable since it's handled by the lexState.
  67273. // if (token.value !== '}') {
  67274. // throw invalidToken()
  67275. // }
  67276. pop();
  67277. return
  67278. case 'eof':
  67279. throw invalidEOF()
  67280. }
  67281. // This code is unreachable since it's handled by the lexState.
  67282. // throw invalidToken()
  67283. },
  67284. afterPropertyName () {
  67285. // This code is unreachable since it's handled by the lexState.
  67286. // if (token.type !== 'punctuator' || token.value !== ':') {
  67287. // throw invalidToken()
  67288. // }
  67289. if (token.type === 'eof') {
  67290. throw invalidEOF()
  67291. }
  67292. parseState = 'beforePropertyValue';
  67293. },
  67294. beforePropertyValue () {
  67295. if (token.type === 'eof') {
  67296. throw invalidEOF()
  67297. }
  67298. push();
  67299. },
  67300. beforeArrayValue () {
  67301. if (token.type === 'eof') {
  67302. throw invalidEOF()
  67303. }
  67304. if (token.type === 'punctuator' && token.value === ']') {
  67305. pop();
  67306. return
  67307. }
  67308. push();
  67309. },
  67310. afterPropertyValue () {
  67311. // This code is unreachable since it's handled by the lexState.
  67312. // if (token.type !== 'punctuator') {
  67313. // throw invalidToken()
  67314. // }
  67315. if (token.type === 'eof') {
  67316. throw invalidEOF()
  67317. }
  67318. switch (token.value) {
  67319. case ',':
  67320. parseState = 'beforePropertyName';
  67321. return
  67322. case '}':
  67323. pop();
  67324. }
  67325. // This code is unreachable since it's handled by the lexState.
  67326. // throw invalidToken()
  67327. },
  67328. afterArrayValue () {
  67329. // This code is unreachable since it's handled by the lexState.
  67330. // if (token.type !== 'punctuator') {
  67331. // throw invalidToken()
  67332. // }
  67333. if (token.type === 'eof') {
  67334. throw invalidEOF()
  67335. }
  67336. switch (token.value) {
  67337. case ',':
  67338. parseState = 'beforeArrayValue';
  67339. return
  67340. case ']':
  67341. pop();
  67342. }
  67343. // This code is unreachable since it's handled by the lexState.
  67344. // throw invalidToken()
  67345. },
  67346. end () {
  67347. // This code is unreachable since it's handled by the lexState.
  67348. // if (token.type !== 'eof') {
  67349. // throw invalidToken()
  67350. // }
  67351. },
  67352. };
  67353. function push () {
  67354. let value;
  67355. switch (token.type) {
  67356. case 'punctuator':
  67357. switch (token.value) {
  67358. case '{':
  67359. value = {};
  67360. break
  67361. case '[':
  67362. value = [];
  67363. break
  67364. }
  67365. break
  67366. case 'null':
  67367. case 'boolean':
  67368. case 'numeric':
  67369. case 'string':
  67370. value = token.value;
  67371. break
  67372. // This code is unreachable.
  67373. // default:
  67374. // throw invalidToken()
  67375. }
  67376. if (root === undefined) {
  67377. root = value;
  67378. } else {
  67379. const parent = stack$1[stack$1.length - 1];
  67380. if (Array.isArray(parent)) {
  67381. parent.push(value);
  67382. } else {
  67383. parent[key] = value;
  67384. }
  67385. }
  67386. if (value !== null && typeof value === 'object') {
  67387. stack$1.push(value);
  67388. if (Array.isArray(value)) {
  67389. parseState = 'beforeArrayValue';
  67390. } else {
  67391. parseState = 'beforePropertyName';
  67392. }
  67393. } else {
  67394. const current = stack$1[stack$1.length - 1];
  67395. if (current == null) {
  67396. parseState = 'end';
  67397. } else if (Array.isArray(current)) {
  67398. parseState = 'afterArrayValue';
  67399. } else {
  67400. parseState = 'afterPropertyValue';
  67401. }
  67402. }
  67403. }
  67404. function pop () {
  67405. stack$1.pop();
  67406. const current = stack$1[stack$1.length - 1];
  67407. if (current == null) {
  67408. parseState = 'end';
  67409. } else if (Array.isArray(current)) {
  67410. parseState = 'afterArrayValue';
  67411. } else {
  67412. parseState = 'afterPropertyValue';
  67413. }
  67414. }
  67415. // This code is unreachable.
  67416. // function invalidParseState () {
  67417. // return new Error(`JSON5: invalid parse state '${parseState}'`)
  67418. // }
  67419. // This code is unreachable.
  67420. // function invalidLexState (state) {
  67421. // return new Error(`JSON5: invalid lex state '${state}'`)
  67422. // }
  67423. function invalidChar (c) {
  67424. if (c === undefined) {
  67425. return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
  67426. }
  67427. return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
  67428. }
  67429. function invalidEOF () {
  67430. return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
  67431. }
  67432. // This code is unreachable.
  67433. // function invalidToken () {
  67434. // if (token.type === 'eof') {
  67435. // return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
  67436. // }
  67437. // const c = String.fromCodePoint(token.value.codePointAt(0))
  67438. // return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
  67439. // }
  67440. function invalidIdentifier () {
  67441. column -= 5;
  67442. return syntaxError(`JSON5: invalid identifier character at ${line}:${column}`)
  67443. }
  67444. function separatorChar (c) {
  67445. console.warn(`JSON5: '${formatChar(c)}' in strings is not valid ECMAScript; consider escaping`);
  67446. }
  67447. function formatChar (c) {
  67448. const replacements = {
  67449. "'": "\\'",
  67450. '"': '\\"',
  67451. '\\': '\\\\',
  67452. '\b': '\\b',
  67453. '\f': '\\f',
  67454. '\n': '\\n',
  67455. '\r': '\\r',
  67456. '\t': '\\t',
  67457. '\v': '\\v',
  67458. '\0': '\\0',
  67459. '\u2028': '\\u2028',
  67460. '\u2029': '\\u2029',
  67461. };
  67462. if (replacements[c]) {
  67463. return replacements[c]
  67464. }
  67465. if (c < ' ') {
  67466. const hexString = c.charCodeAt(0).toString(16);
  67467. return '\\x' + ('00' + hexString).substring(hexString.length)
  67468. }
  67469. return c
  67470. }
  67471. function syntaxError (message) {
  67472. const err = new SyntaxError(message);
  67473. err.lineNumber = line;
  67474. err.columnNumber = column;
  67475. return err
  67476. }
  67477. var stringify = function stringify (value, replacer, space) {
  67478. const stack = [];
  67479. let indent = '';
  67480. let propertyList;
  67481. let replacerFunc;
  67482. let gap = '';
  67483. let quote;
  67484. if (
  67485. replacer != null &&
  67486. typeof replacer === 'object' &&
  67487. !Array.isArray(replacer)
  67488. ) {
  67489. space = replacer.space;
  67490. quote = replacer.quote;
  67491. replacer = replacer.replacer;
  67492. }
  67493. if (typeof replacer === 'function') {
  67494. replacerFunc = replacer;
  67495. } else if (Array.isArray(replacer)) {
  67496. propertyList = [];
  67497. for (const v of replacer) {
  67498. let item;
  67499. if (typeof v === 'string') {
  67500. item = v;
  67501. } else if (
  67502. typeof v === 'number' ||
  67503. v instanceof String ||
  67504. v instanceof Number
  67505. ) {
  67506. item = String(v);
  67507. }
  67508. if (item !== undefined && propertyList.indexOf(item) < 0) {
  67509. propertyList.push(item);
  67510. }
  67511. }
  67512. }
  67513. if (space instanceof Number) {
  67514. space = Number(space);
  67515. } else if (space instanceof String) {
  67516. space = String(space);
  67517. }
  67518. if (typeof space === 'number') {
  67519. if (space > 0) {
  67520. space = Math.min(10, Math.floor(space));
  67521. gap = ' '.substr(0, space);
  67522. }
  67523. } else if (typeof space === 'string') {
  67524. gap = space.substr(0, 10);
  67525. }
  67526. return serializeProperty('', {'': value})
  67527. function serializeProperty (key, holder) {
  67528. let value = holder[key];
  67529. if (value != null) {
  67530. if (typeof value.toJSON5 === 'function') {
  67531. value = value.toJSON5(key);
  67532. } else if (typeof value.toJSON === 'function') {
  67533. value = value.toJSON(key);
  67534. }
  67535. }
  67536. if (replacerFunc) {
  67537. value = replacerFunc.call(holder, key, value);
  67538. }
  67539. if (value instanceof Number) {
  67540. value = Number(value);
  67541. } else if (value instanceof String) {
  67542. value = String(value);
  67543. } else if (value instanceof Boolean) {
  67544. value = value.valueOf();
  67545. }
  67546. switch (value) {
  67547. case null: return 'null'
  67548. case true: return 'true'
  67549. case false: return 'false'
  67550. }
  67551. if (typeof value === 'string') {
  67552. return quoteString(value, false)
  67553. }
  67554. if (typeof value === 'number') {
  67555. return String(value)
  67556. }
  67557. if (typeof value === 'object') {
  67558. return Array.isArray(value) ? serializeArray(value) : serializeObject(value)
  67559. }
  67560. return undefined
  67561. }
  67562. function quoteString (value) {
  67563. const quotes = {
  67564. "'": 0.1,
  67565. '"': 0.2,
  67566. };
  67567. const replacements = {
  67568. "'": "\\'",
  67569. '"': '\\"',
  67570. '\\': '\\\\',
  67571. '\b': '\\b',
  67572. '\f': '\\f',
  67573. '\n': '\\n',
  67574. '\r': '\\r',
  67575. '\t': '\\t',
  67576. '\v': '\\v',
  67577. '\0': '\\0',
  67578. '\u2028': '\\u2028',
  67579. '\u2029': '\\u2029',
  67580. };
  67581. let product = '';
  67582. for (let i = 0; i < value.length; i++) {
  67583. const c = value[i];
  67584. switch (c) {
  67585. case "'":
  67586. case '"':
  67587. quotes[c]++;
  67588. product += c;
  67589. continue
  67590. case '\0':
  67591. if (util.isDigit(value[i + 1])) {
  67592. product += '\\x00';
  67593. continue
  67594. }
  67595. }
  67596. if (replacements[c]) {
  67597. product += replacements[c];
  67598. continue
  67599. }
  67600. if (c < ' ') {
  67601. let hexString = c.charCodeAt(0).toString(16);
  67602. product += '\\x' + ('00' + hexString).substring(hexString.length);
  67603. continue
  67604. }
  67605. product += c;
  67606. }
  67607. const quoteChar = quote || Object.keys(quotes).reduce((a, b) => (quotes[a] < quotes[b]) ? a : b);
  67608. product = product.replace(new RegExp(quoteChar, 'g'), replacements[quoteChar]);
  67609. return quoteChar + product + quoteChar
  67610. }
  67611. function serializeObject (value) {
  67612. if (stack.indexOf(value) >= 0) {
  67613. throw TypeError('Converting circular structure to JSON5')
  67614. }
  67615. stack.push(value);
  67616. let stepback = indent;
  67617. indent = indent + gap;
  67618. let keys = propertyList || Object.keys(value);
  67619. let partial = [];
  67620. for (const key of keys) {
  67621. const propertyString = serializeProperty(key, value);
  67622. if (propertyString !== undefined) {
  67623. let member = serializeKey(key) + ':';
  67624. if (gap !== '') {
  67625. member += ' ';
  67626. }
  67627. member += propertyString;
  67628. partial.push(member);
  67629. }
  67630. }
  67631. let final;
  67632. if (partial.length === 0) {
  67633. final = '{}';
  67634. } else {
  67635. let properties;
  67636. if (gap === '') {
  67637. properties = partial.join(',');
  67638. final = '{' + properties + '}';
  67639. } else {
  67640. let separator = ',\n' + indent;
  67641. properties = partial.join(separator);
  67642. final = '{\n' + indent + properties + ',\n' + stepback + '}';
  67643. }
  67644. }
  67645. stack.pop();
  67646. indent = stepback;
  67647. return final
  67648. }
  67649. function serializeKey (key) {
  67650. if (key.length === 0) {
  67651. return quoteString(key, true)
  67652. }
  67653. const firstChar = String.fromCodePoint(key.codePointAt(0));
  67654. if (!util.isIdStartChar(firstChar)) {
  67655. return quoteString(key, true)
  67656. }
  67657. for (let i = firstChar.length; i < key.length; i++) {
  67658. if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) {
  67659. return quoteString(key, true)
  67660. }
  67661. }
  67662. return key
  67663. }
  67664. function serializeArray (value) {
  67665. if (stack.indexOf(value) >= 0) {
  67666. throw TypeError('Converting circular structure to JSON5')
  67667. }
  67668. stack.push(value);
  67669. let stepback = indent;
  67670. indent = indent + gap;
  67671. let partial = [];
  67672. for (let i = 0; i < value.length; i++) {
  67673. const propertyString = serializeProperty(String(i), value);
  67674. partial.push((propertyString !== undefined) ? propertyString : 'null');
  67675. }
  67676. let final;
  67677. if (partial.length === 0) {
  67678. final = '[]';
  67679. } else {
  67680. if (gap === '') {
  67681. let properties = partial.join(',');
  67682. final = '[' + properties + ']';
  67683. } else {
  67684. let separator = ',\n' + indent;
  67685. let properties = partial.join(separator);
  67686. final = '[\n' + indent + properties + ',\n' + stepback + ']';
  67687. }
  67688. }
  67689. stack.pop();
  67690. indent = stepback;
  67691. return final
  67692. }
  67693. };
  67694. const JSON5$1 = {
  67695. parse,
  67696. stringify,
  67697. };
  67698. var lib = JSON5$1;
  67699. class Sidebar{
  67700. constructor(viewer){
  67701. this.viewer = viewer;
  67702. this.measuringTool = viewer.measuringTool;
  67703. this.profileTool = viewer.profileTool;
  67704. this.volumeTool = viewer.volumeTool;
  67705. this.dom = $("#sidebar_root");
  67706. }
  67707. createToolIcon(icon, title, callback){
  67708. let element = $(`
  67709. <img src="${icon}"
  67710. style="width: 32px; height: 32px"
  67711. class="button-icon"
  67712. data-i18n="${title}" />
  67713. `);
  67714. element.click(callback);
  67715. return element;
  67716. }
  67717. init(){
  67718. if(Potree.settings.editType == 'merge'){
  67719. this.initMergeBar();
  67720. this.initToolbar();
  67721. this.initScene();
  67722. this.initNavigation();
  67723. }else {
  67724. this.initAccordion();
  67725. this.initAppearance();
  67726. this.initToolbar();
  67727. this.initScene();
  67728. this.initNavigation();
  67729. this.initFilters();
  67730. //this.initClippingTool(); //因为修改了clipping,所以这项有bug不能使用
  67731. this.initSettings();
  67732. }
  67733. $('#potree_version_number').html(Potree.version.major + "." + Potree.version.minor + Potree.version.suffix);
  67734. }
  67735. initAlignment(){
  67736. let Alignment = viewer.modules.Alignment;
  67737. var pannel = $('#alignment');
  67738. var buttons = pannel.find('[name="transform"] button');
  67739. var applyToPointcloud = (fun, value)=>{
  67740. return function(){
  67741. var selected = $('#alignment li[name="selectPointCloud"] input:checked' );
  67742. Array.from(selected).forEach(e=>{
  67743. var pointcloud = viewer.scene.pointclouds.find(p=>p.name == e.name);
  67744. fun(pointcloud, value);
  67745. });
  67746. }
  67747. };
  67748. //逆时针是正数
  67749. buttons.eq(0).on('click', applyToPointcloud(Alignment.rotate, 10));
  67750. //viewer.scene.pointclouds[0].rotation.z += THREE.Math.degToRad(10)
  67751. buttons.eq(1).on('click' ,applyToPointcloud(Alignment.rotate, 1));
  67752. buttons.eq(2).on('click', applyToPointcloud(Alignment.rotate, 0.1));
  67753. buttons.eq(3).on('click', applyToPointcloud(Alignment.rotate, -10));
  67754. buttons.eq(4).on('click',applyToPointcloud(Alignment.rotate, -1));
  67755. buttons.eq(5).on('click',applyToPointcloud(Alignment.rotate, -0.1));
  67756. buttons.eq(6).on('click', applyToPointcloud(Alignment.translate, new Vector3(-1,0,0)));
  67757. buttons.eq(7).on('click', applyToPointcloud(Alignment.translate, new Vector3(1,0,0)));
  67758. buttons.eq(8).on('click', applyToPointcloud(Alignment.translate, new Vector3(0,-1,0)));
  67759. buttons.eq(9).on('click', applyToPointcloud(Alignment.translate, new Vector3(0,1,0)));
  67760. buttons.eq(10).on('click', applyToPointcloud(Alignment.translate, new Vector3(0,0,-1)));
  67761. buttons.eq(11).on('click', applyToPointcloud(Alignment.translate, new Vector3(0,0,1)));
  67762. pannel.find('#startAlignment').on('click', ()=>{
  67763. Alignment.enter();
  67764. });
  67765. pannel.find('#exitAlignment').on('click', ()=>{
  67766. Alignment.save();
  67767. Alignment.leave();
  67768. });
  67769. pannel.find('#rotTool').on('click', ()=>{
  67770. Alignment.switchHandle('rotate');
  67771. });
  67772. pannel.find('#moveTool').on('click', ()=>{
  67773. Alignment.switchHandle('translate');
  67774. });
  67775. }
  67776. initMergeBar(){//多元融合模块
  67777. var pannel = $('#mergeModel');
  67778. var buttons = pannel.find('button');
  67779. let MergeEditor = viewer.modules.MergeEditor;
  67780. let loading = false;
  67781. pannel.find('ul[name="model"] li button').on('click',(e)=>{
  67782. if(loading)return console.log('还在加载', loading)
  67783. let $elem = $(e.target);
  67784. let parent = $elem.parent();
  67785. let name = parent.attr('name');
  67786. if($elem.attr('name') == 'select'){
  67787. return Potree.selectModel(name)
  67788. }
  67789. if($elem.text() == '添加'){
  67790. let startTime = Date.now();
  67791. Potree.addModel(name,()=>{
  67792. loading = false;
  67793. $elem.text('删除');
  67794. let now = Date.now();
  67795. console.log('加载完毕', name, '用时', (now-startTime)/1000, 's');
  67796. });
  67797. loading = name;
  67798. }else {
  67799. Potree.removeModel(name);
  67800. $elem.text('添加');
  67801. }
  67802. });
  67803. pannel.find('li button[name="splitScreen"]').on('click',(e)=>{
  67804. let $elem = $(e.target);
  67805. if($elem.text() == '分屏'){
  67806. $elem.text('恢复');
  67807. MergeEditor.enterSplit();
  67808. }else {
  67809. $elem.text('分屏');
  67810. MergeEditor.leaveSplit();
  67811. }
  67812. });
  67813. let addingTag = false;
  67814. pannel.find('li button[name="tag"]').on('click',(e)=>{
  67815. let $elem = $(e.target);
  67816. viewer.tagTool.startInsertion();
  67817. });
  67818. }
  67819. initClippingModel(){//实时裁剪
  67820. /* 总共两种box : 可见和不可见(都是并集)
  67821. 当有可见box时,需要在任一可见box内才可见
  67822. 当有不可见box时,不在所有不可见box内才可见 */
  67823. var clipping = viewer.modules.clipping;
  67824. var pannel = $('#clipping');
  67825. var addBtn = pannel.find('[name="operation"] button[name="add"] ');
  67826. var switchBtn = pannel.find('[name="operation"] button[name="switchView"] ');
  67827. var enterBtn = pannel.find(' button[name="enter"] ');
  67828. var exitBtn = pannel.find(' button[name="exit"] ');
  67829. let list = pannel.find('[name="list"] ul ');
  67830. enterBtn.on('click',()=>{
  67831. clipping.enter();
  67832. pannel.find('li[name=operation]').css('display','block');
  67833. pannel.find('li[name=list]').css('display','block');
  67834. });
  67835. exitBtn.on('click',()=>{
  67836. clipping.leave();
  67837. pannel.find('li[name=operation]').css('display','none');
  67838. pannel.find('li[name=list]').css('display','none');
  67839. });
  67840. switchBtn.on('click',()=>{
  67841. clipping.switchView(clipping.activeViewName == 'top' ? 'mainView' : 'top');
  67842. });
  67843. pannel.find('[name="operation"] button[name="translation"] ').on('click',()=>{
  67844. clipping.setTranMode('translation');
  67845. });
  67846. pannel.find('[name="operation"] button[name="rotation"] ').on('click',()=>{
  67847. clipping.setTranMode('rotation');
  67848. });
  67849. pannel.find('[name="operation"] button[name="scale"] ').on('click',()=>{
  67850. clipping.setTranMode('scale');
  67851. });
  67852. addBtn.on('click',()=>{
  67853. let volumeBox = this.volumeTool.startInsertion({clip: true, clipTask:Potree.ClipTask.SHOW_OUTSIDE});
  67854. let li = $("<li><button name='changeTask'>不可见</button><button name='chose'>选择</button><button name='delete'>删除</button></li>");
  67855. list.append(li);
  67856. li.find('button[name=changeTask]').on('click',(e)=>{
  67857. if(e.target.innerText == '不可见'){
  67858. volumeBox.clipTask = Potree.ClipTask.SHOW_INSIDE;
  67859. e.target.innerText = '可见';
  67860. }else {
  67861. volumeBox.clipTask = Potree.ClipTask.SHOW_OUTSIDE;
  67862. e.target.innerText = '不可见';
  67863. }
  67864. volumeBox.update();
  67865. });
  67866. li.find('button[name=chose]').on('click',(e)=>{
  67867. viewer.transformObject(volumeBox);//viewer.inputHandler.toggleSelection(volumeBox)
  67868. });
  67869. li.find('button[name=delete]').on('click',(e)=>{
  67870. li.remove();
  67871. viewer.scene.removeVolume(volumeBox);
  67872. });
  67873. });
  67874. pannel.find('button[name=save]').on('click',(e)=>{
  67875. let data = clipping.saveClipData();
  67876. });
  67877. }
  67878. addAlignmentButton(pointcloud){
  67879. var pannel = $('#alignment li[name="selectPointCloud"]>div');
  67880. var option = $(` <input name="${pointcloud.name}" class="editCheckbox" type="checkbox" >
  67881. <label for="showingLabels">${pointcloud.name}</label>`);
  67882. pannel.append(option);
  67883. /* option.find("input").on('change',function(){
  67884. })
  67885. */
  67886. }
  67887. initClipModel(){
  67888. let Clip = viewer.modules.Clip;
  67889. var pannel = $('#clipModel');
  67890. var buttons = pannel.find('button');
  67891. buttons.eq(0).on('click', Clip.enter.bind(Clip));
  67892. buttons.eq(1).on('click', Clip.download.bind(Clip));
  67893. buttons.eq(2).on('click', Clip.leave.bind(Clip));
  67894. }
  67895. initSiteModel(){
  67896. let SiteModel = viewer.modules.SiteModel;
  67897. var pannel = $('#siteModel');
  67898. pannel.find('button[name="start"] ').on('click', SiteModel.enter.bind(SiteModel));
  67899. pannel.find('button[name="exit"] ').on('click', SiteModel.leave.bind(SiteModel));
  67900. pannel.find('button[name="building"] ').on('click', SiteModel.startInsertion.bind(SiteModel,'building'));
  67901. pannel.find('button[name="floor"] ').on('click', ()=>{
  67902. SiteModel.addFloor(SiteModel.buildings[0], 'top');
  67903. } );
  67904. pannel.find('button[name="room"] ').on('click', ()=>{
  67905. SiteModel.startInsertion('room', SiteModel.buildings[0].buildChildren[0]);
  67906. });
  67907. pannel.find('button[name="digHole"] ').on('click', ()=>{
  67908. SiteModel.selected && SiteModel.startInsertion('hole', SiteModel.selected);
  67909. });
  67910. pannel.find('button[name="selectBuilding"] ').on('click', ()=>{
  67911. SiteModel.selectEntity(SiteModel.buildings[0] );
  67912. } );
  67913. pannel.find('button[name="selectFloor"] ').on('click', ()=>{
  67914. SiteModel.selectEntity(SiteModel.buildings[0].buildChildren[0]);
  67915. } );
  67916. pannel.find('button[name="selectRoom"] ').on('click', ()=>{
  67917. SiteModel.selectEntity(SiteModel.buildings[0].buildChildren[0].buildChildren[0]);
  67918. });
  67919. pannel.find('button[name="removeFirstBuilding"] ').on('click', ()=>{
  67920. SiteModel.removeEntity(SiteModel.buildings[0]);
  67921. });
  67922. pannel.find('button[name="removeFirstFloor"] ').on('click', ()=>{
  67923. SiteModel.removeEntity(SiteModel.buildings[0].buildChildren[0]);
  67924. });
  67925. pannel.find('button[name="removeFirstRoom"] ').on('click', ()=>{
  67926. SiteModel.removeEntity(SiteModel.buildings[0].buildChildren[0].buildChildren[0]);
  67927. });
  67928. pannel.find('button[name="removeFirstHole"] ').on('click', ()=>{
  67929. SiteModel.selected.removeHole(SiteModel.selected.holes[0]);
  67930. });
  67931. pannel.find('button[name="removeFirstMarker"] ').on('click', ()=>{
  67932. //SiteModel.removeMarker(SiteModel.selected.markers[0])
  67933. SiteModel.selected.removeMarker(0);
  67934. });
  67935. }
  67936. initParitcle(){
  67937. let ParticleEditor = viewer.modules.ParticleEditor;
  67938. var pannel = $('#particle');
  67939. pannel.find('button[name="addFire"] ').on('click', ()=>{
  67940. ParticleEditor.startInsertion('fire+smoke');
  67941. });
  67942. pannel.find('button[name="addExplode"] ').on('click', ()=>{
  67943. ParticleEditor.startInsertion('explode');
  67944. });
  67945. }
  67946. initPanosEdit(){
  67947. let PanoEditor = viewer.modules.PanoEditor;
  67948. let Alignment = viewer.modules.Alignment;
  67949. var pannel = $('#panos');
  67950. pannel.find('button[name="save"] ').on('click', ()=>{
  67951. console.log('saveData',PanoEditor.exportSavingData());
  67952. });
  67953. pannel.find('button[name="translate"] ').on('click', ()=>{
  67954. Alignment.switchHandle('translate');
  67955. });
  67956. pannel.find('button[name="rotate"] ').on('click', ()=>{
  67957. Alignment.switchHandle('rotate');
  67958. });
  67959. pannel.find('button[name="topView"] ').on('click', ()=>{
  67960. PanoEditor.switchView('top');
  67961. });
  67962. pannel.find('button[name="sideView"] ').on('click', ()=>{
  67963. PanoEditor.switchView('right');
  67964. });
  67965. pannel.find('button[name="3DView"] ').on('click', ()=>{
  67966. PanoEditor.switchView('mainView');
  67967. });
  67968. pannel.find('button[name="addLink"] ').on('click', ()=>{
  67969. PanoEditor.setLinkOperateState('addLink', true);
  67970. });
  67971. pannel.find('button[name="removeLink"] ').on('click', ()=>{
  67972. PanoEditor.setLinkOperateState('removeLink', true);
  67973. });
  67974. pannel.find('button[name="getCloser"] ').on('click', ()=>{
  67975. PanoEditor.setZoomInState(true);
  67976. });
  67977. }
  67978. initToolbar(){
  67979. // ANGLE
  67980. let elToolbar = $('#tools');
  67981. elToolbar.append(this.createToolIcon(
  67982. Potree.resourcePath + '/icons/angle.png',
  67983. '[title]tt.angle_measurement',
  67984. () => {
  67985. $('#menu_measurements').next().slideDown();
  67986. let measurement = this.measuringTool.startInsertion({
  67987. showDistances: false,
  67988. showAngles: true,
  67989. showArea: false,
  67990. closed: true,
  67991. maxMarkers: 3,
  67992. minMarkers:3,
  67993. measureType: 'Angle'});
  67994. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  67995. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  67996. $.jstree.reference(jsonNode.id).deselect_all();
  67997. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  67998. }
  67999. ));
  68000. // POINT
  68001. elToolbar.append(this.createToolIcon(
  68002. Potree.resourcePath + '/icons/point.svg',
  68003. '[title]tt.point_measurement',
  68004. () => {
  68005. $('#menu_measurements').next().slideDown();
  68006. let measurement = this.measuringTool.startInsertion({
  68007. showDistances: false,
  68008. showAngles: false,
  68009. showCoordinates: true,
  68010. showEdges:false,
  68011. showArea: false,
  68012. closed: true,
  68013. maxMarkers: 1,
  68014. minMarkers:1,
  68015. measureType: 'Point'});
  68016. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68017. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68018. $.jstree.reference(jsonNode.id).deselect_all();
  68019. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68020. }
  68021. ));
  68022. // DISTANCE
  68023. elToolbar.append(this.createToolIcon(
  68024. Potree.resourcePath + '/icons/distance.svg',
  68025. '[title]tt.distance_measurement',
  68026. () => {
  68027. $('#menu_measurements').next().slideDown();
  68028. let measurement = this.measuringTool.startInsertion({
  68029. showDistances: true,
  68030. showArea: false,
  68031. closed: false,
  68032. minMarkers:2,
  68033. maxMarkers: 2,
  68034. measureType: 'Distance'
  68035. });
  68036. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68037. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68038. $.jstree.reference(jsonNode.id).deselect_all();
  68039. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68040. }
  68041. ));
  68042. // DISTANCE 带箭头的
  68043. elToolbar.append(this.createToolIcon(
  68044. Potree.resourcePath + '/icons/distance.svg',
  68045. '[title]arrow DISTANCE',
  68046. () => {
  68047. $('#menu_measurements').next().slideDown();
  68048. let measurement = this.measuringTool.startInsertion({
  68049. showDistances: true,
  68050. showArea: false,
  68051. closed: false,
  68052. minMarkers:2,
  68053. maxMarkers: 2,
  68054. measureType: 'Distance-withArrow'
  68055. });
  68056. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68057. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68058. $.jstree.reference(jsonNode.id).deselect_all();
  68059. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68060. }
  68061. ));
  68062. // DISTANCE2
  68063. elToolbar.append(this.createToolIcon(
  68064. Potree.resourcePath + '/icons/distance.svg',
  68065. '[title]MulDistance',
  68066. () => {
  68067. $('#menu_measurements').next().slideDown();
  68068. let measurement = this.measuringTool.startInsertion({
  68069. showDistances: true,
  68070. showArea: false,
  68071. closed: false,
  68072. minMarkers:2,
  68073. measureType: 'MulDistance'
  68074. });
  68075. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68076. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68077. $.jstree.reference(jsonNode.id).deselect_all();
  68078. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68079. }
  68080. ));
  68081. elToolbar.append(this.createToolIcon(
  68082. Potree.resourcePath + '/icons/distance.svg',
  68083. '[title]Ver MulDistance',
  68084. () => {
  68085. $('#menu_measurements').next().slideDown();
  68086. let measurement = this.measuringTool.startInsertion({
  68087. measureType: 'Ver MulDistance'
  68088. });
  68089. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68090. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68091. $.jstree.reference(jsonNode.id).deselect_all();
  68092. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68093. }
  68094. ));
  68095. elToolbar.append(this.createToolIcon(
  68096. Potree.resourcePath + '/icons/distance.svg',
  68097. '[title]Hor MulDistance',
  68098. () => {
  68099. $('#menu_measurements').next().slideDown();
  68100. let measurement = this.measuringTool.startInsertion({
  68101. measureType: 'Hor MulDistance'
  68102. });
  68103. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68104. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68105. $.jstree.reference(jsonNode.id).deselect_all();
  68106. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68107. }
  68108. ));
  68109. // HEIGHT
  68110. elToolbar.append(this.createToolIcon(
  68111. Potree.resourcePath + '/icons/height.svg',
  68112. '[title]tt.height_measurement',
  68113. () => {
  68114. $('#menu_measurements').next().slideDown();
  68115. let measurement = this.measuringTool.startInsertion({
  68116. showDistances: true,//false,
  68117. showHeight: true,
  68118. showArea: false,
  68119. closed: false,
  68120. maxMarkers: 2,
  68121. minMarkers:2,
  68122. //showGuideLine: true: true
  68123. measureType: 'Ver Distance',
  68124. });
  68125. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68126. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68127. $.jstree.reference(jsonNode.id).deselect_all();
  68128. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68129. }
  68130. ));
  68131. // CIRCLE
  68132. elToolbar.append(this.createToolIcon(
  68133. Potree.resourcePath + '/icons/circle.svg',
  68134. '[title]tt.circle_measurement',
  68135. () => {
  68136. $('#menu_measurements').next().slideDown();
  68137. let measurement = this.measuringTool.startInsertion({
  68138. showDistances: false,
  68139. showHeight: false,
  68140. showArea: false,
  68141. showCircle: true,
  68142. showEdges: false,
  68143. closed: false,
  68144. maxMarkers: 3,
  68145. minMarkers:3,
  68146. measureType: 'Circle'
  68147. });
  68148. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68149. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68150. $.jstree.reference(jsonNode.id).deselect_all();
  68151. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68152. }
  68153. ));
  68154. // AZIMUTH
  68155. elToolbar.append(this.createToolIcon(
  68156. Potree.resourcePath + '/icons/azimuth.svg',
  68157. 'Azimuth',
  68158. () => {
  68159. $('#menu_measurements').next().slideDown();
  68160. let measurement = this.measuringTool.startInsertion({
  68161. showDistances: false,
  68162. showHeight: false,
  68163. showArea: false,
  68164. showCircle: false,
  68165. showEdges: false,
  68166. showAzimuth: true,
  68167. closed: false,
  68168. maxMarkers: 2,
  68169. minMarkers:2,
  68170. measureType: 'Azimuth'});
  68171. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68172. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68173. $.jstree.reference(jsonNode.id).deselect_all();
  68174. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68175. }
  68176. ));
  68177. // AREA
  68178. elToolbar.append(this.createToolIcon(
  68179. Potree.resourcePath + '/icons/area.svg',
  68180. '[title]tt.area_measurement',
  68181. () => {
  68182. $('#menu_measurements').next().slideDown();
  68183. let measurement = this.measuringTool.startInsertion({
  68184. showDistances: true,
  68185. showArea: true,
  68186. closed: true,
  68187. minMarkers:3,
  68188. //showGuideLine: true: true,
  68189. measureType: 'Area'});
  68190. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68191. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68192. $.jstree.reference(jsonNode.id).deselect_all();
  68193. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68194. }
  68195. ));
  68196. //Hor AREA
  68197. elToolbar.append(this.createToolIcon(
  68198. Potree.resourcePath + '/icons/area.svg',
  68199. '[title]Hor Area',
  68200. () => {
  68201. $('#menu_measurements').next().slideDown();
  68202. let measurement = this.measuringTool.startInsertion({
  68203. showDistances: true,
  68204. showArea: true,
  68205. closed: true,
  68206. minMarkers:3,
  68207. measureType: 'Hor Area'});
  68208. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68209. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68210. $.jstree.reference(jsonNode.id).deselect_all();
  68211. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68212. }
  68213. ));
  68214. // Ver Area
  68215. elToolbar.append(this.createToolIcon(
  68216. Potree.resourcePath + '/icons/area.svg',
  68217. '[title]Ver Area',
  68218. () => {
  68219. $('#menu_measurements').next().slideDown();
  68220. let measurement = this.measuringTool.startInsertion({
  68221. showDistances: true,
  68222. showArea: true,
  68223. closed: true,
  68224. minMarkers:3,
  68225. measureType: 'Ver Area'});
  68226. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68227. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68228. $.jstree.reference(jsonNode.id).deselect_all();
  68229. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68230. }
  68231. ));
  68232. // rect area freedom direction
  68233. elToolbar.append(this.createToolIcon(
  68234. Potree.resourcePath + '/icons/area.svg',
  68235. '[title]area_freedom_rect',
  68236. () => {
  68237. $('#menu_measurements').next().slideDown();
  68238. let measurement = this.measuringTool.startInsertion({
  68239. showDistances: true,
  68240. showArea: true,
  68241. closed: true,
  68242. minMarkers:4,
  68243. maxMarkers:4,
  68244. //showGuideLine: true: true,
  68245. isRect:true,
  68246. measureType: 'Rect Area'});
  68247. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68248. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68249. $.jstree.reference(jsonNode.id).deselect_all();
  68250. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68251. }
  68252. ));
  68253. // rect area horizontal
  68254. elToolbar.append(this.createToolIcon(
  68255. Potree.resourcePath + '/icons/area.svg',
  68256. '[title]area_horizontal_rect',
  68257. () => {
  68258. $('#menu_measurements').next().slideDown();
  68259. let measurement = this.measuringTool.startInsertion({
  68260. showDistances: true,
  68261. showArea: true,
  68262. closed: true,
  68263. minMarkers:4,
  68264. maxMarkers:4,
  68265. //showGuideLine: true: true,
  68266. isRect:true,
  68267. faceDirection:"horizontal",
  68268. measureType: 'Hor Rect Area'});
  68269. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68270. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68271. $.jstree.reference(jsonNode.id).deselect_all();
  68272. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68273. }
  68274. ));
  68275. // rect area vertical
  68276. elToolbar.append(this.createToolIcon(
  68277. Potree.resourcePath + '/icons/area.svg',
  68278. '[title]area_vertical_rect',
  68279. () => {
  68280. $('#menu_measurements').next().slideDown();
  68281. let measurement = this.measuringTool.startInsertion({
  68282. showDistances: true,
  68283. showArea: true,
  68284. closed: true,
  68285. minMarkers:4,
  68286. maxMarkers:4,
  68287. //showGuideLine: true: true,
  68288. isRect:true,
  68289. faceDirection:"vertical",
  68290. measureType: 'Ver Rect Area'});
  68291. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68292. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  68293. $.jstree.reference(jsonNode.id).deselect_all();
  68294. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68295. }
  68296. ));
  68297. // VOLUME
  68298. elToolbar.append(this.createToolIcon(
  68299. Potree.resourcePath + '/icons/volume.svg',
  68300. '[title]tt.volume_measurement',
  68301. () => {
  68302. let volume = this.volumeTool.startInsertion();
  68303. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68304. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === volume.uuid);
  68305. $.jstree.reference(jsonNode.id).deselect_all();
  68306. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68307. }
  68308. ));
  68309. // SPHERE VOLUME
  68310. elToolbar.append(this.createToolIcon(
  68311. Potree.resourcePath + '/icons/sphere_distances.svg',
  68312. '[title]tt.volume_measurement',
  68313. () => {
  68314. let volume = this.volumeTool.startInsertion({type: SphereVolume$2});
  68315. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68316. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === volume.uuid);
  68317. $.jstree.reference(jsonNode.id).deselect_all();
  68318. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68319. }
  68320. ));
  68321. // PROFILE
  68322. elToolbar.append(this.createToolIcon(
  68323. Potree.resourcePath + '/icons/profile.svg',
  68324. '[title]tt.height_profile',
  68325. () => {
  68326. $('#menu_measurements').next().slideDown(); ;
  68327. let profile = this.profileTool.startInsertion();
  68328. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68329. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === profile.uuid);
  68330. $.jstree.reference(jsonNode.id).deselect_all();
  68331. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68332. }
  68333. ));
  68334. // ANNOTATION
  68335. elToolbar.append(this.createToolIcon(
  68336. Potree.resourcePath + '/icons/annotation.svg',
  68337. '[title]tt.annotation',
  68338. () => {
  68339. $('#menu_measurements').next().slideDown(); ;
  68340. let annotation = this.viewer.annotationTool.startInsertion();
  68341. let annotationsRoot = $("#jstree_scene").jstree().get_json("annotations");
  68342. let jsonNode = annotationsRoot.children.find(child => child.data.uuid === annotation.uuid);
  68343. $.jstree.reference(jsonNode.id).deselect_all();
  68344. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68345. }
  68346. ));
  68347. // REMOVE ALL
  68348. elToolbar.append(this.createToolIcon(
  68349. Potree.resourcePath + '/icons/reset_tools.svg',
  68350. '[title]tt.remove_all_measurement',
  68351. () => {
  68352. this.viewer.scene.removeAllMeasurements();
  68353. }
  68354. ));
  68355. { // SHOW / HIDE Measurements
  68356. let elShow = $("#measurement_options_show");
  68357. elShow.selectgroup({title: "Show/Hide labels"});
  68358. elShow.find("input").click( (e) => {
  68359. const show = e.target.value === "SHOW";
  68360. this.measuringTool.showLabels = show;
  68361. });
  68362. let currentShow = this.measuringTool.showLabels ? "SHOW" : "HIDE";
  68363. elShow.find(`input[value=${currentShow}]`).trigger("click");
  68364. }
  68365. }
  68366. initScene(){
  68367. let elScene = $("#menu_scene");
  68368. let elObjects = elScene.next().find("#scene_objects");
  68369. let elProperties = elScene.next().find("#scene_object_properties");
  68370. {
  68371. let elExport = elScene.next().find("#scene_export");
  68372. let geoJSONIcon = `${Potree.resourcePath}/icons/file_geojson.svg`;
  68373. let dxfIcon = `${Potree.resourcePath}/icons/file_dxf.svg`;
  68374. let potreeIcon = `${Potree.resourcePath}/icons/file_potree.svg`;
  68375. elExport.append(`
  68376. Export: <br>
  68377. <a href="#" download="measure.json"><img name="geojson_export_button" src="${geoJSONIcon}" class="button-icon" style="height: 24px" /></a>
  68378. <a href="#" download="measure.dxf"><img name="dxf_export_button" src="${dxfIcon}" class="button-icon" style="height: 24px" /></a>
  68379. <a href="#" download="potree.json5"><img name="potree_export_button" src="${potreeIcon}" class="button-icon" style="height: 24px" /></a>
  68380. `);
  68381. let elDownloadJSON = elExport.find("img[name=geojson_export_button]").parent();
  68382. elDownloadJSON.click( (event) => {
  68383. let scene = this.viewer.scene;
  68384. let measurements = [...scene.measurements, ...scene.profiles, ...scene.volumes];
  68385. if(measurements.length > 0){
  68386. let geoJson = GeoJSONExporter.toString(measurements);
  68387. let url = window.URL.createObjectURL(new Blob([geoJson], {type: 'data:application/octet-stream'}));
  68388. elDownloadJSON.attr('href', url);
  68389. }else {
  68390. this.viewer.postError("nothing to export");
  68391. event.preventDefault();
  68392. }
  68393. });
  68394. let elDownloadDXF = elExport.find("img[name=dxf_export_button]").parent();
  68395. elDownloadDXF.click( (event) => {
  68396. let scene = this.viewer.scene;
  68397. let measurements = [...scene.measurements, ...scene.profiles, ...scene.volumes];
  68398. if(measurements.length > 0){
  68399. let dxf = DXFExporter.toString(measurements);
  68400. let url = window.URL.createObjectURL(new Blob([dxf], {type: 'data:application/octet-stream'}));
  68401. elDownloadDXF.attr('href', url);
  68402. }else {
  68403. this.viewer.postError("no measurements to export");
  68404. event.preventDefault();
  68405. }
  68406. });
  68407. let elDownloadPotree = elExport.find("img[name=potree_export_button]").parent();
  68408. elDownloadPotree.click( (event) => {
  68409. let data = Potree.saveProject(this.viewer);
  68410. let dataString = lib.stringify(data, null, "\t");
  68411. let url = window.URL.createObjectURL(new Blob([dataString], {type: 'data:application/octet-stream'}));
  68412. elDownloadPotree.attr('href', url);
  68413. });
  68414. }
  68415. let propertiesPanel = new PropertiesPanel(elProperties, this.viewer);
  68416. propertiesPanel.setScene(this.viewer.scene);
  68417. localStorage.removeItem('jstree');
  68418. let tree = $(`<div id="jstree_scene"></div>`);
  68419. elObjects.append(tree);
  68420. tree.jstree({
  68421. 'plugins': ["checkbox", "state"],
  68422. 'core': {
  68423. "dblclick_toggle": false,
  68424. "state": {
  68425. "checked" : true
  68426. },
  68427. 'check_callback': true,
  68428. "expand_selected_onload": true
  68429. },
  68430. "checkbox" : {
  68431. "keep_selected_style": true,
  68432. "three_state": false,
  68433. "whole_node": false,
  68434. "tie_selection": false,
  68435. },
  68436. });
  68437. let createNode = (parent, text, icon, object) => {
  68438. let nodeID = tree.jstree('create_node', parent, {
  68439. "text": text,
  68440. "icon": icon,
  68441. "data": object
  68442. },
  68443. "last", false, false);
  68444. if(object.visible){
  68445. tree.jstree('check_node', nodeID);
  68446. }else {
  68447. tree.jstree('uncheck_node', nodeID);
  68448. }
  68449. return nodeID;
  68450. };
  68451. let pcID = tree.jstree('create_node', "#", { "text": "<b>Point Clouds</b>", "id": "pointclouds"}, "last", false, false);
  68452. let measurementID = tree.jstree('create_node', "#", { "text": "<b>Measurements</b>", "id": "measurements" }, "last", false, false);
  68453. let annotationsID = tree.jstree('create_node', "#", { "text": "<b>Annotations</b>", "id": "annotations" }, "last", false, false);
  68454. let otherID = tree.jstree('create_node', "#", { "text": "<b>Other</b>", "id": "other" }, "last", false, false);
  68455. let vectorsID = tree.jstree('create_node', "#", { "text": "<b>Vectors</b>", "id": "vectors" }, "last", false, false);
  68456. let imagesID = tree.jstree('create_node', "#", { "text": "<b> Images</b>", "id": "images" }, "last", false, false);
  68457. tree.jstree("check_node", pcID);
  68458. tree.jstree("check_node", measurementID);
  68459. tree.jstree("check_node", annotationsID);
  68460. tree.jstree("check_node", otherID);
  68461. tree.jstree("check_node", vectorsID);
  68462. tree.jstree("check_node", imagesID);
  68463. tree.on('create_node.jstree', (e, data) => {
  68464. tree.jstree("open_all");
  68465. });
  68466. tree.on("select_node.jstree", (e, data) => {
  68467. let object = data.node.data;
  68468. propertiesPanel.set(object);
  68469. this.viewer.inputHandler.deselectAll();
  68470. if(object instanceof Volume$1){
  68471. this.viewer.inputHandler.toggleSelection(object);
  68472. }
  68473. $(this.viewer.renderer.domElement).focus();
  68474. });
  68475. tree.on("deselect_node.jstree", (e, data) => {
  68476. propertiesPanel.set(null);
  68477. });
  68478. tree.on("delete_node.jstree", (e, data) => {
  68479. propertiesPanel.set(null);
  68480. });
  68481. tree.on('dblclick','.jstree-anchor', (e) => {
  68482. let instance = $.jstree.reference(e.target);
  68483. let node = instance.get_node(e.target);
  68484. let object = node.data;
  68485. // ignore double click on checkbox
  68486. if(e.target.classList.contains("jstree-checkbox")){
  68487. return;
  68488. }
  68489. if(object instanceof PointCloudTree){
  68490. let box = this.viewer.getBoundingBox([object]);
  68491. let node = new Object3D();
  68492. node.boundingBox = box;
  68493. this.viewer.zoomTo(node, 1, 500);
  68494. }else if(object instanceof Measure$1){
  68495. let points = object.points.map(p => p.position);
  68496. let box = new Box3().setFromPoints(points);
  68497. if(box.getSize(new Vector3()).length() == 0){
  68498. box.min = box.max.clone();//禁止相同
  68499. box.expandByVector(new Vector3(1,1,1));
  68500. }
  68501. let node = new Object3D();
  68502. node.boundingBox = box;
  68503. this.viewer.zoomTo(node, 2, 500);
  68504. }else if(object instanceof Profile){
  68505. let points = object.points;
  68506. let box = new Box3().setFromPoints(points);
  68507. if(box.getSize(new Vector3()).length() > 0){
  68508. let node = new Object3D();
  68509. node.boundingBox = box;
  68510. this.viewer.zoomTo(node, 1, 500);
  68511. }
  68512. }else if(object instanceof Volume$1){
  68513. let box = object.boundingBox.clone().applyMatrix4(object.matrixWorld);
  68514. if(box.getSize(new Vector3()).length() > 0){
  68515. let node = new Object3D();
  68516. node.boundingBox = box;
  68517. this.viewer.zoomTo(node, 1, 500);
  68518. }
  68519. }else if(object instanceof Annotation){
  68520. object.moveHere(this.viewer.scene.getActiveCamera());
  68521. }else if(object instanceof PolygonClipVolume){
  68522. let dir = object.camera.getWorldDirection(new Vector3());
  68523. let target;
  68524. if(object.camera instanceof OrthographicCamera){
  68525. dir.multiplyScalar(object.camera.right);
  68526. target = new Vector3().addVectors(object.camera.position, dir);
  68527. this.viewer.setCameraMode(CameraMode.ORTHOGRAPHIC);
  68528. }else if(object.camera instanceof PerspectiveCamera){
  68529. dir.multiplyScalar(this.viewer.scene.view.radius);
  68530. target = new Vector3().addVectors(object.camera.position, dir);
  68531. this.viewer.setCameraMode(CameraMode.PERSPECTIVE);
  68532. }
  68533. this.viewer.scene.view.position.copy(object.camera.position);
  68534. this.viewer.scene.view.lookAt(target);
  68535. }else if(object.type === "SpotLight"){
  68536. let distance = (object.distance > 0) ? object.distance / 4 : 5 * 1000;
  68537. let position = object.position;
  68538. let target = new Vector3().addVectors(
  68539. position,
  68540. object.getWorldDirection(new Vector3()).multiplyScalar(distance));
  68541. this.viewer.scene.view.position.copy(object.position);
  68542. this.viewer.scene.view.lookAt(target);
  68543. }else if(object instanceof Object3D){
  68544. let box = new Box3().setFromObject(object);
  68545. if(box.getSize(new Vector3()).length() > 0){
  68546. let node = new Object3D();
  68547. node.boundingBox = box;
  68548. this.viewer.zoomTo(node, 1, 500);
  68549. }
  68550. }else if(object instanceof OrientedImage){
  68551. // TODO zoom to images
  68552. // let box = new THREE.Box3().setFromObject(object);
  68553. // if(box.getSize(new THREE.Vector3()).length() > 0){
  68554. // let node = new THREE.Object3D();
  68555. // node.boundingBox = box;
  68556. // this.viewer.zoomTo(node, 1, 500);
  68557. // }
  68558. }else if(object instanceof Images360){
  68559. // TODO
  68560. }else if(object instanceof Geopackage){
  68561. // TODO
  68562. }
  68563. });
  68564. tree.on("uncheck_node.jstree", (e, data) => {
  68565. let object = data.node.data;
  68566. if(object){
  68567. object.visible = false;
  68568. }
  68569. });
  68570. tree.on("check_node.jstree", (e, data) => {
  68571. let object = data.node.data;
  68572. if(object){
  68573. object.visible = true;
  68574. }
  68575. });
  68576. let onPointCloudAdded = (e) => {
  68577. let pointcloud = e.pointcloud;
  68578. let cloudIcon = `${Potree.resourcePath}/icons/cloud.svg`;
  68579. let node = createNode(pcID, pointcloud.name, cloudIcon, pointcloud);
  68580. pointcloud.addEventListener("visibility_changed", () => {
  68581. if(pointcloud.visible){
  68582. tree.jstree('check_node', node);
  68583. }else {
  68584. tree.jstree('uncheck_node', node);
  68585. }
  68586. });
  68587. };
  68588. let onMeasurementAdded = (e) => {
  68589. let measurement = e.measurement;
  68590. let icon = Utils.getMeasurementIcon(measurement);
  68591. createNode(measurementID, measurement.name, icon, measurement);
  68592. };
  68593. let onVolumeAdded = (e) => {
  68594. let volume = e.volume;
  68595. let icon = Utils.getMeasurementIcon(volume);
  68596. let node = createNode(measurementID, volume.name, icon, volume);
  68597. volume.addEventListener("visibility_changed", () => {
  68598. if(volume.visible){
  68599. tree.jstree('check_node', node);
  68600. }else {
  68601. tree.jstree('uncheck_node', node);
  68602. }
  68603. });
  68604. };
  68605. let onProfileAdded = (e) => {
  68606. let profile = e.profile;
  68607. let icon = Utils.getMeasurementIcon(profile);
  68608. createNode(measurementID, profile.name, icon, profile);
  68609. };
  68610. let onAnnotationAdded = (e) => {
  68611. let annotation = e.annotation;
  68612. let annotationIcon = `${Potree.resourcePath}/icons/annotation.svg`;
  68613. let parentID = this.annotationMapping.get(annotation.parent);
  68614. let annotationID = createNode(parentID, annotation.title, annotationIcon, annotation);
  68615. this.annotationMapping.set(annotation, annotationID);
  68616. annotation.addEventListener("annotation_changed", (e) => {
  68617. let annotationsRoot = $("#jstree_scene").jstree().get_json("annotations");
  68618. let jsonNode = annotationsRoot.children.find(child => child.data.uuid === annotation.uuid);
  68619. $.jstree.reference(jsonNode.id).rename_node(jsonNode.id, annotation.title);
  68620. });
  68621. };
  68622. let onCameraAnimationAdded = (e) => {
  68623. const animation = e.animation;
  68624. const animationIcon = `${Potree.resourcePath}/icons/camera_animation.svg`;
  68625. createNode(otherID, "animation", animationIcon, animation);
  68626. };
  68627. let onOrientedImagesAdded = (e) => {
  68628. const images = e.images;
  68629. const imagesIcon = `${Potree.resourcePath}/icons/picture.svg`;
  68630. const node = createNode(imagesID, "images", imagesIcon, images);
  68631. images.addEventListener("visibility_changed", () => {
  68632. if(images.visible){
  68633. tree.jstree('check_node', node);
  68634. }else {
  68635. tree.jstree('uncheck_node', node);
  68636. }
  68637. });
  68638. };
  68639. let onImages360Added = (e) => {
  68640. const images = e.images;
  68641. const imagesIcon = `${Potree.resourcePath}/icons/picture.svg`;
  68642. const node = createNode(imagesID, "360° images", imagesIcon, images);
  68643. images.addEventListener("visibility_changed", () => {
  68644. if(images.visible){
  68645. tree.jstree('check_node', node);
  68646. }else {
  68647. tree.jstree('uncheck_node', node);
  68648. }
  68649. });
  68650. };
  68651. const onGeopackageAdded = (e) => {
  68652. const geopackage = e.geopackage;
  68653. const geopackageIcon = `${Potree.resourcePath}/icons/triangle.svg`;
  68654. const tree = $(`#jstree_scene`);
  68655. const parentNode = "vectors";
  68656. for(const layer of geopackage.node.children){
  68657. const name = layer.name;
  68658. let shpPointsID = tree.jstree('create_node', parentNode, {
  68659. "text": name,
  68660. "icon": geopackageIcon,
  68661. "object": layer,
  68662. "data": layer,
  68663. },
  68664. "last", false, false);
  68665. tree.jstree(layer.visible ? "check_node" : "uncheck_node", shpPointsID);
  68666. }
  68667. };
  68668. this.viewer.scene.addEventListener("pointcloud_added", onPointCloudAdded);
  68669. this.viewer.scene.addEventListener("measurement_added", onMeasurementAdded);
  68670. this.viewer.scene.addEventListener("profile_added", onProfileAdded);
  68671. this.viewer.scene.addEventListener("volume_added", onVolumeAdded);
  68672. this.viewer.scene.addEventListener("camera_animation_added", onCameraAnimationAdded);
  68673. this.viewer.scene.addEventListener("oriented_images_added", onOrientedImagesAdded);
  68674. this.viewer.scene.addEventListener("360_images_added", onImages360Added);
  68675. this.viewer.scene.addEventListener("geopackage_added", onGeopackageAdded);
  68676. this.viewer.scene.addEventListener("polygon_clip_volume_added", onVolumeAdded);
  68677. this.viewer.scene.annotations.addEventListener("annotation_added", onAnnotationAdded);
  68678. let onMeasurementRemoved = (e) => {
  68679. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68680. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.measurement.uuid);
  68681. tree.jstree("delete_node", jsonNode.id);
  68682. };
  68683. let onVolumeRemoved = (e) => {
  68684. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68685. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.volume.uuid);
  68686. tree.jstree("delete_node", jsonNode.id);
  68687. };
  68688. let onPolygonClipVolumeRemoved = (e) => {
  68689. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68690. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.volume.uuid);
  68691. tree.jstree("delete_node", jsonNode.id);
  68692. };
  68693. let onProfileRemoved = (e) => {
  68694. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68695. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.profile.uuid);
  68696. tree.jstree("delete_node", jsonNode.id);
  68697. };
  68698. this.viewer.scene.addEventListener("measurement_removed", onMeasurementRemoved);
  68699. this.viewer.scene.addEventListener("volume_removed", onVolumeRemoved);
  68700. this.viewer.scene.addEventListener("polygon_clip_volume_removed", onPolygonClipVolumeRemoved);
  68701. this.viewer.scene.addEventListener("profile_removed", onProfileRemoved);
  68702. {
  68703. let annotationIcon = `${Potree.resourcePath}/icons/annotation.svg`;
  68704. this.annotationMapping = new Map();
  68705. this.annotationMapping.set(this.viewer.scene.annotations, annotationsID);
  68706. this.viewer.scene.annotations.traverseDescendants(annotation => {
  68707. let parentID = this.annotationMapping.get(annotation.parent);
  68708. let annotationID = createNode(parentID, annotation.title, annotationIcon, annotation);
  68709. this.annotationMapping.set(annotation, annotationID);
  68710. });
  68711. }
  68712. const scene = this.viewer.scene;
  68713. for(let pointcloud of scene.pointclouds){
  68714. onPointCloudAdded({pointcloud: pointcloud});
  68715. }
  68716. for(let measurement of scene.measurements){
  68717. onMeasurementAdded({measurement: measurement});
  68718. }
  68719. for(let volume of [...scene.volumes, ...scene.polygonClipVolumes]){
  68720. onVolumeAdded({volume: volume});
  68721. }
  68722. for(let animation of scene.cameraAnimations){
  68723. onCameraAnimationAdded({animation: animation});
  68724. }
  68725. for(let images of scene.orientedImages){
  68726. onOrientedImagesAdded({images: images});
  68727. }
  68728. for(let images of scene.images360){
  68729. onImages360Added({images: images});
  68730. }
  68731. for(const geopackage of scene.geopackages){
  68732. onGeopackageAdded({geopackage: geopackage});
  68733. }
  68734. for(let profile of scene.profiles){
  68735. onProfileAdded({profile: profile});
  68736. }
  68737. {
  68738. createNode(otherID, "Camera", null, new Camera());
  68739. }
  68740. this.viewer.addEventListener("scene_changed", (e) => {
  68741. propertiesPanel.setScene(e.scene);
  68742. e.oldScene.removeEventListener("pointcloud_added", onPointCloudAdded);
  68743. e.oldScene.removeEventListener("measurement_added", onMeasurementAdded);
  68744. e.oldScene.removeEventListener("profile_added", onProfileAdded);
  68745. e.oldScene.removeEventListener("volume_added", onVolumeAdded);
  68746. e.oldScene.removeEventListener("polygon_clip_volume_added", onVolumeAdded);
  68747. e.oldScene.removeEventListener("measurement_removed", onMeasurementRemoved);
  68748. e.scene.addEventListener("pointcloud_added", onPointCloudAdded);
  68749. e.scene.addEventListener("measurement_added", onMeasurementAdded);
  68750. e.scene.addEventListener("profile_added", onProfileAdded);
  68751. e.scene.addEventListener("volume_added", onVolumeAdded);
  68752. e.scene.addEventListener("polygon_clip_volume_added", onVolumeAdded);
  68753. e.scene.addEventListener("measurement_removed", onMeasurementRemoved);
  68754. });
  68755. }
  68756. initClippingTool(){
  68757. this.viewer.addEventListener("cliptask_changed", (event) => {
  68758. console.log("TODO");
  68759. });
  68760. this.viewer.addEventListener("clipmethod_changed", (event) => {
  68761. console.log("TODO");
  68762. });
  68763. {
  68764. let elClipTask = $("#cliptask_options");
  68765. elClipTask.selectgroup({title: "Clip Task"});
  68766. elClipTask.find("input").click( (e) => {
  68767. this.viewer.setClipTask(ClipTask[e.target.value]);
  68768. });
  68769. let currentClipTask = Object.keys(ClipTask)
  68770. .filter(key => ClipTask[key] === this.viewer.clipTask);
  68771. elClipTask.find(`input[value=${currentClipTask}]`).trigger("click");
  68772. }
  68773. {
  68774. let elClipMethod = $("#clipmethod_options");
  68775. elClipMethod.selectgroup({title: "Clip Method"});
  68776. elClipMethod.find("input").click( (e) => {
  68777. this.viewer.setClipMethod(ClipMethod[e.target.value]);
  68778. });
  68779. let currentClipMethod = Object.keys(ClipMethod)
  68780. .filter(key => ClipMethod[key] === this.viewer.clipMethod);
  68781. elClipMethod.find(`input[value=${currentClipMethod}]`).trigger("click");
  68782. }
  68783. let clippingToolBar = $("#clipping_tools");
  68784. // CLIP VOLUME
  68785. clippingToolBar.append(this.createToolIcon(
  68786. Potree.resourcePath + '/icons/clip_volume.svg',
  68787. '[title]tt.clip_volume',
  68788. () => {
  68789. let item = this.volumeTool.startInsertion({clip: true});
  68790. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68791. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid);
  68792. $.jstree.reference(jsonNode.id).deselect_all();
  68793. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68794. }
  68795. ));
  68796. // CLIP POLYGON
  68797. clippingToolBar.append(this.createToolIcon(
  68798. Potree.resourcePath + "/icons/clip-polygon.svg",
  68799. "[title]tt.clip_polygon",
  68800. () => {
  68801. let item = this.viewer.clippingTool.startInsertion({type: "polygon"});
  68802. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68803. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid);
  68804. $.jstree.reference(jsonNode.id).deselect_all();
  68805. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68806. }
  68807. ));
  68808. {// SCREEN BOX SELECT
  68809. let boxSelectTool = new ScreenBoxSelectTool(this.viewer);
  68810. clippingToolBar.append(this.createToolIcon(
  68811. Potree.resourcePath + "/icons/clip-screen.svg",
  68812. "[title]tt.screen_clip_box",
  68813. () => {
  68814. if(!(this.viewer.scene.getActiveCamera() instanceof OrthographicCamera)){
  68815. this.viewer.postMessage(`Switch to Orthographic Camera Mode before using the Screen-Box-Select tool.`,
  68816. {duration: 2000});
  68817. return;
  68818. }
  68819. let item = boxSelectTool.startInsertion();
  68820. let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  68821. let jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid);
  68822. $.jstree.reference(jsonNode.id).deselect_all();
  68823. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  68824. }
  68825. ));
  68826. }
  68827. { // REMOVE CLIPPING TOOLS
  68828. clippingToolBar.append(this.createToolIcon(
  68829. Potree.resourcePath + "/icons/remove.svg",
  68830. "[title]tt.remove_all_clipping_volumes",
  68831. () => {
  68832. this.viewer.scene.removeAllClipVolumes();
  68833. }
  68834. ));
  68835. }
  68836. }
  68837. initFilters(){
  68838. this.initClassificationList();
  68839. this.initReturnFilters();
  68840. this.initGPSTimeFilters();
  68841. this.initPointSourceIDFilters();
  68842. }
  68843. initReturnFilters(){
  68844. let elReturnFilterPanel = $('#return_filter_panel');
  68845. { // RETURN NUMBER
  68846. let sldReturnNumber = elReturnFilterPanel.find('#sldReturnNumber');
  68847. let lblReturnNumber = elReturnFilterPanel.find('#lblReturnNumber');
  68848. sldReturnNumber.slider({
  68849. range: true,
  68850. min: 0, max: 7, step: 1,
  68851. values: [0, 7],
  68852. slide: (event, ui) => {
  68853. this.viewer.setFilterReturnNumberRange(ui.values[0], ui.values[1]);
  68854. }
  68855. });
  68856. let onReturnNumberChanged = (event) => {
  68857. let [from, to] = this.viewer.filterReturnNumberRange;
  68858. lblReturnNumber[0].innerHTML = `${from} to ${to}`;
  68859. sldReturnNumber.slider({values: [from, to]});
  68860. };
  68861. this.viewer.addEventListener('filter_return_number_range_changed', onReturnNumberChanged);
  68862. onReturnNumberChanged();
  68863. }
  68864. { // NUMBER OF RETURNS
  68865. let sldNumberOfReturns = elReturnFilterPanel.find('#sldNumberOfReturns');
  68866. let lblNumberOfReturns = elReturnFilterPanel.find('#lblNumberOfReturns');
  68867. sldNumberOfReturns.slider({
  68868. range: true,
  68869. min: 0, max: 7, step: 1,
  68870. values: [0, 7],
  68871. slide: (event, ui) => {
  68872. this.viewer.setFilterNumberOfReturnsRange(ui.values[0], ui.values[1]);
  68873. }
  68874. });
  68875. let onNumberOfReturnsChanged = (event) => {
  68876. let [from, to] = this.viewer.filterNumberOfReturnsRange;
  68877. lblNumberOfReturns[0].innerHTML = `${from} to ${to}`;
  68878. sldNumberOfReturns.slider({values: [from, to]});
  68879. };
  68880. this.viewer.addEventListener('filter_number_of_returns_range_changed', onNumberOfReturnsChanged);
  68881. onNumberOfReturnsChanged();
  68882. }
  68883. }
  68884. initGPSTimeFilters(){
  68885. let elGPSTimeFilterPanel = $('#gpstime_filter_panel');
  68886. {
  68887. let slider = new HierarchicalSlider({
  68888. levels: 4,
  68889. slide: (event) => {
  68890. this.viewer.setFilterGPSTimeRange(...event.values);
  68891. },
  68892. });
  68893. let initialized = false;
  68894. let initialize = () => {
  68895. let elRangeContainer = $("#gpstime_multilevel_range_container");
  68896. elRangeContainer[0].prepend(slider.element);
  68897. let extent = this.viewer.getGpsTimeExtent();
  68898. slider.setRange(extent);
  68899. slider.setValues(extent);
  68900. initialized = true;
  68901. };
  68902. this.viewer.addEventListener("update", (e) => {
  68903. let extent = this.viewer.getGpsTimeExtent();
  68904. let gpsTimeAvailable = extent[0] !== Infinity;
  68905. if(!initialized && gpsTimeAvailable){
  68906. initialize();
  68907. }
  68908. slider.setRange(extent); //高耗cpu
  68909. });
  68910. }
  68911. {
  68912. const txtGpsTime = elGPSTimeFilterPanel.find("#txtGpsTime");
  68913. const btnFindGpsTime = elGPSTimeFilterPanel.find("#btnFindGpsTime");
  68914. let targetTime = null;
  68915. txtGpsTime.on("input", (e) => {
  68916. const str = txtGpsTime.val();
  68917. if(!isNaN(str)){
  68918. const value = parseFloat(str);
  68919. targetTime = value;
  68920. txtGpsTime.css("background-color", "");
  68921. }else {
  68922. targetTime = null;
  68923. txtGpsTime.css("background-color", "#ff9999");
  68924. }
  68925. });
  68926. btnFindGpsTime.click( () => {
  68927. if(targetTime !== null){
  68928. viewer.moveToGpsTimeVicinity(targetTime);
  68929. }
  68930. });
  68931. }
  68932. }
  68933. initPointSourceIDFilters() {
  68934. let elPointSourceIDFilterPanel = $('#pointsourceid_filter_panel');
  68935. {
  68936. let slider = new HierarchicalSlider({
  68937. levels: 4,
  68938. range: [0, 65535],
  68939. precision: 1,
  68940. slide: (event) => {
  68941. let values = event.values;
  68942. this.viewer.setFilterPointSourceIDRange(values[0], values[1]);
  68943. }
  68944. });
  68945. let initialized = false;
  68946. let initialize = () => {
  68947. elPointSourceIDFilterPanel[0].prepend(slider.element);
  68948. initialized = true;
  68949. };
  68950. this.viewer.addEventListener("update", (e) => {
  68951. let extent = this.viewer.filterPointSourceIDRange;
  68952. if(!initialized){
  68953. initialize();
  68954. slider.setValues(extent);
  68955. }
  68956. });
  68957. }
  68958. // let lblPointSourceID = elPointSourceIDFilterPanel.find("#lblPointSourceID");
  68959. // let elPointSourceID = elPointSourceIDFilterPanel.find("#spnPointSourceID");
  68960. // let slider = new ZoomableSlider();
  68961. // elPointSourceID[0].appendChild(slider.element);
  68962. // slider.update();
  68963. // slider.change( () => {
  68964. // let range = slider.chosenRange;
  68965. // this.viewer.setFilterPointSourceIDRange(range[0], range[1]);
  68966. // });
  68967. // let onPointSourceIDExtentChanged = (event) => {
  68968. // let range = this.viewer.filterPointSourceIDExtent;
  68969. // slider.setVisibleRange(range);
  68970. // };
  68971. // let onPointSourceIDChanged = (event) => {
  68972. // let range = this.viewer.filterPointSourceIDRange;
  68973. // let precision = 1;
  68974. // let from = `${Utils.addCommas(range[0].toFixed(precision))}`;
  68975. // let to = `${Utils.addCommas(range[1].toFixed(precision))}`;
  68976. // lblPointSourceID[0].innerHTML = `${from} to ${to}`;
  68977. // slider.setRange(range);
  68978. // };
  68979. // this.viewer.addEventListener('filter_point_source_id_range_changed', onPointSourceIDChanged);
  68980. // this.viewer.addEventListener('filter_point_source_id_extent_changed', onPointSourceIDExtentChanged);
  68981. }
  68982. initClassificationList(){
  68983. let elClassificationList = $('#classificationList');
  68984. let addClassificationItem = (code, name) => {
  68985. const classification = this.viewer.classifications[code];
  68986. const inputID = 'chkClassification_' + code;
  68987. const colorPickerID = 'colorPickerClassification_' + code;
  68988. const checked = classification.visible ? "checked" : "";
  68989. let element = $(`
  68990. <li>
  68991. <label style="whitespace: nowrap; display: flex">
  68992. <input id="${inputID}" type="checkbox" ${checked}/>
  68993. <span style="flex-grow: 1">${name}</span>
  68994. <input id="${colorPickerID}" style="zoom: 0.5" />
  68995. </label>
  68996. </li>
  68997. `);
  68998. const elInput = element.find('input');
  68999. const elColorPicker = element.find(`#${colorPickerID}`);
  69000. elInput.click(event => {
  69001. this.viewer.setClassificationVisibility(code, event.target.checked);
  69002. });
  69003. let defaultColor = classification.color.map(c => c * 255).join(", ");
  69004. defaultColor = `rgb(${defaultColor})`;
  69005. elColorPicker.spectrum({
  69006. // flat: true,
  69007. color: defaultColor,
  69008. showInput: true,
  69009. preferredFormat: 'rgb',
  69010. cancelText: '',
  69011. chooseText: 'Apply',
  69012. move: color => {
  69013. let rgb = color.toRgb();
  69014. const c = [rgb.r / 255, rgb.g / 255, rgb.b / 255, 1];
  69015. classification.color = c;
  69016. },
  69017. change: color => {
  69018. let rgb = color.toRgb();
  69019. const c = [rgb.r / 255, rgb.g / 255, rgb.b / 255, 1];
  69020. classification.color = c;
  69021. }
  69022. });
  69023. elClassificationList.append(element);
  69024. };
  69025. const addToggleAllButton = () => { // toggle all button
  69026. const element = $(`
  69027. <li>
  69028. <label style="whitespace: nowrap">
  69029. <input id="toggleClassificationFilters" type="checkbox" checked/>
  69030. <span>show/hide all</span>
  69031. </label>
  69032. </li>
  69033. `);
  69034. let elInput = element.find('input');
  69035. elInput.click(event => {
  69036. this.viewer.toggleAllClassificationsVisibility();
  69037. });
  69038. elClassificationList.append(element);
  69039. };
  69040. const addInvertButton = () => {
  69041. const element = $(`
  69042. <li>
  69043. <input type="button" value="invert" />
  69044. </li>
  69045. `);
  69046. let elInput = element.find('input');
  69047. elInput.click( () => {
  69048. const classifications = this.viewer.classifications;
  69049. for(let key of Object.keys(classifications)){
  69050. let value = classifications[key];
  69051. this.viewer.setClassificationVisibility(key, !value.visible);
  69052. }
  69053. });
  69054. elClassificationList.append(element);
  69055. };
  69056. const populate = () => {
  69057. addToggleAllButton();
  69058. for (let classID in this.viewer.classifications) {
  69059. addClassificationItem(classID, this.viewer.classifications[classID].name);
  69060. }
  69061. addInvertButton();
  69062. };
  69063. populate();
  69064. this.viewer.addEventListener("classifications_changed", () => {
  69065. elClassificationList.empty();
  69066. populate();
  69067. });
  69068. this.viewer.addEventListener("classification_visibility_changed", () => {
  69069. { // set checked state of classification buttons
  69070. for(const classID of Object.keys(this.viewer.classifications)){
  69071. const classValue = this.viewer.classifications[classID];
  69072. let elItem = elClassificationList.find(`#chkClassification_${classID}`);
  69073. elItem.prop("checked", classValue.visible);
  69074. }
  69075. }
  69076. { // set checked state of toggle button based on state of all other buttons
  69077. let numVisible = 0;
  69078. let numItems = 0;
  69079. for(const key of Object.keys(this.viewer.classifications)){
  69080. if(this.viewer.classifications[key].visible){
  69081. numVisible++;
  69082. }
  69083. numItems++;
  69084. }
  69085. const allVisible = numVisible === numItems;
  69086. let elToggle = elClassificationList.find("#toggleClassificationFilters");
  69087. elToggle.prop("checked", allVisible);
  69088. }
  69089. });
  69090. }
  69091. initAccordion(){
  69092. $('.accordion > h3').each(function(){
  69093. let header = $(this);
  69094. let content = $(this).next();
  69095. //header.addClass('accordion-header ui-widget');
  69096. //content.addClass('accordion-content ui-widget');
  69097. content.hide();
  69098. header.click(() => {
  69099. content.slideToggle();
  69100. });
  69101. });
  69102. let languages = [
  69103. ["EN", "en"],
  69104. ["FR", "fr"],
  69105. ["DE", "de"],
  69106. ["JP", "jp"],
  69107. ["ES", "es"],
  69108. ["SE", "se"],
  69109. ["ZH", "zh"]
  69110. ];
  69111. let elLanguages = $('#potree_languages');
  69112. for(let i = 0; i < languages.length; i++){
  69113. let [key, value] = languages[i];
  69114. let element = $(`<a>${key}</a>`);
  69115. element.click(() => this.viewer.setLanguage(value));
  69116. if(i === 0){
  69117. element.css("margin-left", "30px");
  69118. }
  69119. elLanguages.append(element);
  69120. if(i < languages.length - 1){
  69121. elLanguages.append($(document.createTextNode(' - ')));
  69122. }
  69123. }
  69124. // to close all, call
  69125. // $(".accordion > div").hide()
  69126. // to open the, for example, tool menu, call:
  69127. // $("#menu_tools").next().show()
  69128. }
  69129. initAppearance(){
  69130. const sldPointBudget = this.dom.find('#sldPointBudget');
  69131. sldPointBudget.slider({
  69132. value: this.viewer.getPointBudget(),
  69133. min: 100 * 1000,
  69134. max: 10 * 1000 * 1000,
  69135. step: 1000,
  69136. slide: (event, ui) => { this.viewer.setPointBudget(ui.value); }
  69137. });
  69138. this.dom.find('#sldFOV').slider({
  69139. value: this.viewer.getFOV(),
  69140. min: 20,
  69141. max: 100,
  69142. step: 1,
  69143. slide: (event, ui) => { this.viewer.setFOV(ui.value); }
  69144. });
  69145. $('#sldEDLRadius').slider({
  69146. value: this.viewer.getEDLRadius(),
  69147. min: 1,
  69148. max: 4,
  69149. step: 0.01,
  69150. slide: (event, ui) => { this.viewer.setEDLRadius(ui.value); }
  69151. });
  69152. $('#sldEDLStrength').slider({
  69153. value: this.viewer.getEDLStrength(),
  69154. min: 0,
  69155. max: 5,
  69156. step: 0.01,
  69157. slide: (event, ui) => { this.viewer.setEDLStrength(ui.value); }
  69158. });
  69159. $('#sldEDLOpacity').slider({
  69160. value: this.viewer.getEDLOpacity(),
  69161. min: 0,
  69162. max: 1,
  69163. step: 0.01,
  69164. slide: (event, ui) => { this.viewer.setEDLOpacity(ui.value); }
  69165. });
  69166. this.viewer.addEventListener('point_budget_changed', (event) => {
  69167. $('#lblPointBudget')[0].innerHTML = Utils.addCommas(this.viewer.getPointBudget());
  69168. sldPointBudget.slider({value: this.viewer.getPointBudget()});
  69169. });
  69170. this.viewer.addEventListener('fov_changed', (event) => {
  69171. $('#lblFOV')[0].innerHTML = parseInt(this.viewer.getFOV());
  69172. $('#sldFOV').slider({value: this.viewer.getFOV()});
  69173. });
  69174. this.viewer.addEventListener('use_edl_changed', (event) => {
  69175. $('#chkEDLEnabled')[0].checked = this.viewer.getEDLEnabled();
  69176. });
  69177. this.viewer.addEventListener('edl_radius_changed', (event) => {
  69178. $('#lblEDLRadius')[0].innerHTML = this.viewer.getEDLRadius().toFixed(1);
  69179. $('#sldEDLRadius').slider({value: this.viewer.getEDLRadius()});
  69180. });
  69181. this.viewer.addEventListener('edl_strength_changed', (event) => {
  69182. $('#lblEDLStrength')[0].innerHTML = this.viewer.getEDLStrength().toFixed(1);
  69183. $('#sldEDLStrength').slider({value: this.viewer.getEDLStrength()});
  69184. });
  69185. this.viewer.addEventListener('background_changed', (event) => {
  69186. $("input[name=background][value='" + this.viewer.getBackground() + "']").prop('checked', true);
  69187. });
  69188. $('#lblPointBudget')[0].innerHTML = Utils.addCommas(this.viewer.getPointBudget());
  69189. $('#lblFOV')[0].innerHTML = parseInt(this.viewer.getFOV());
  69190. $('#lblEDLRadius')[0].innerHTML = this.viewer.getEDLRadius().toFixed(1);
  69191. $('#lblEDLStrength')[0].innerHTML = this.viewer.getEDLStrength().toFixed(1);
  69192. $('#chkEDLEnabled')[0].checked = this.viewer.getEDLEnabled();
  69193. {
  69194. let elBackground = $(`#background_options`);
  69195. elBackground.selectgroup();
  69196. elBackground.find("input").click( (e) => {
  69197. this.viewer.setBackground(e.target.value);
  69198. });
  69199. let currentBackground = this.viewer.getBackground();
  69200. try{
  69201. $(`input[name=background_options][value=${currentBackground}]`).trigger("click");
  69202. }catch(e){}
  69203. }
  69204. $('#chkEDLEnabled').click( () => {
  69205. this.viewer.setEDLEnabled($('#chkEDLEnabled').prop("checked"));
  69206. });
  69207. }
  69208. initNavigation(){
  69209. let elNavigation = $('#navigation');
  69210. let sldMoveSpeed = $('#sldMoveSpeed');
  69211. let lblMoveSpeed = $('#lblMoveSpeed');
  69212. elNavigation.append(this.createToolIcon(
  69213. Potree.resourcePath + '/icons/earth_controls_1.png',
  69214. '[title]tt.earth_control',
  69215. () => { this.viewer.setControls(this.viewer.earthControls); }
  69216. ));
  69217. elNavigation.append(this.createToolIcon(
  69218. Potree.resourcePath + '/icons/fps_controls.svg',
  69219. '[title]tt.flight_control',
  69220. () => {
  69221. this.viewer.setControls(this.viewer.fpControls);
  69222. this.viewer.fpControls.lockElevation = false;
  69223. }
  69224. ));
  69225. elNavigation.append(this.createToolIcon(
  69226. Potree.resourcePath + '/icons/helicopter_controls.svg',
  69227. '[title]tt.heli_control',
  69228. () => {
  69229. this.viewer.setControls(this.viewer.fpControls);
  69230. this.viewer.fpControls.lockElevation = true;
  69231. }
  69232. ));
  69233. elNavigation.append(this.createToolIcon(
  69234. Potree.resourcePath + '/icons/orbit_controls.svg',
  69235. '[title]tt.orbit_control',
  69236. () => { this.viewer.setControls(this.viewer.orbitControls); }
  69237. ));
  69238. elNavigation.append(this.createToolIcon(
  69239. Potree.resourcePath + '/icons/focus.svg',
  69240. '[title]tt.focus_control',
  69241. () => { this.viewer.fitToScreen(); }
  69242. ));
  69243. elNavigation.append(this.createToolIcon(
  69244. Potree.resourcePath + "/icons/navigation_cube.svg",
  69245. "[title]tt.navigation_cube_control",
  69246. () => {this.viewer.toggleNavigationCube();}
  69247. ));
  69248. elNavigation.append(this.createToolIcon(
  69249. Potree.resourcePath + "/images/compas.svg",
  69250. "[title]tt.compass",
  69251. () => {
  69252. const visible = !this.viewer.compass.isVisible();
  69253. this.viewer.compass.setVisible(visible);
  69254. }
  69255. ));
  69256. elNavigation.append(this.createToolIcon(
  69257. Potree.resourcePath + "/icons/camera_animation.svg",
  69258. "[title]tt.camera_animation",
  69259. () => {
  69260. const animation = CameraAnimation.defaultFromView(this.viewer);
  69261. viewer.scene.addCameraAnimation(animation);
  69262. }
  69263. ));
  69264. elNavigation.append("<br>");
  69265. elNavigation.append(this.createToolIcon(
  69266. Potree.resourcePath + "/icons/left.svg",
  69267. "[title]tt.left_view_control",
  69268. () => {this.viewer.setLeftView();}
  69269. ));
  69270. elNavigation.append(this.createToolIcon(
  69271. Potree.resourcePath + "/icons/right.svg",
  69272. "[title]tt.right_view_control",
  69273. () => {this.viewer.setRightView();}
  69274. ));
  69275. elNavigation.append(this.createToolIcon(
  69276. Potree.resourcePath + "/icons/front.svg",
  69277. "[title]tt.front_view_control",
  69278. () => {this.viewer.setFrontView();}
  69279. ));
  69280. elNavigation.append(this.createToolIcon(
  69281. Potree.resourcePath + "/icons/back.svg",
  69282. "[title]tt.back_view_control",
  69283. () => {this.viewer.setBackView();}
  69284. ));
  69285. elNavigation.append(this.createToolIcon(
  69286. Potree.resourcePath + "/icons/top.svg",
  69287. "[title]tt.top_view_control",
  69288. () => {this.viewer.setTopView();}
  69289. ));
  69290. elNavigation.append(this.createToolIcon(
  69291. Potree.resourcePath + "/icons/bottom.svg",
  69292. "[title]tt.bottom_view_control",
  69293. () => {this.viewer.setBottomView();}
  69294. ));
  69295. let elCameraProjection = $(`
  69296. <selectgroup id="camera_projection_options">
  69297. <option id="camera_projection_options_perspective" value="PERSPECTIVE">Perspective</option>
  69298. <option id="camera_projection_options_orthigraphic" value="ORTHOGRAPHIC">Orthographic</option>
  69299. </selectgroup>
  69300. `);
  69301. elNavigation.append(elCameraProjection);
  69302. elCameraProjection.selectgroup({title: "Camera Projection"});
  69303. elCameraProjection.find("input").click( (e) => {
  69304. this.viewer.setCameraMode(CameraMode[e.target.value]);
  69305. });
  69306. let cameraMode = Object.keys(CameraMode)
  69307. .filter(key => CameraMode[key] === this.viewer.scene.cameraMode);
  69308. elCameraProjection.find(`input[value=${cameraMode}]`).trigger("click");
  69309. let speedRange = new Vector2(1, 10 * 1000);
  69310. let toLinearSpeed = (value) => {
  69311. return Math.pow(value, 4) * speedRange.y + speedRange.x;
  69312. };
  69313. let toExpSpeed = (value) => {
  69314. return Math.pow((value - speedRange.x) / speedRange.y, 1 / 4);
  69315. };
  69316. sldMoveSpeed.slider({
  69317. value: toExpSpeed(this.viewer.getMoveSpeed()),
  69318. min: 0,
  69319. max: 1,
  69320. step: 0.01,
  69321. slide: (event, ui) => { this.viewer.setMoveSpeed(toLinearSpeed(ui.value)); }
  69322. });
  69323. this.viewer.addEventListener('move_speed_changed', (event) => {
  69324. lblMoveSpeed.html(this.viewer.getMoveSpeed().toFixed(1));
  69325. sldMoveSpeed.slider({value: toExpSpeed(this.viewer.getMoveSpeed())});
  69326. });
  69327. lblMoveSpeed.html(this.viewer.getMoveSpeed().toFixed(1));
  69328. }
  69329. initSettings(){
  69330. {
  69331. $('#sldMinNodeSize').slider({
  69332. value: this.viewer.getMinNodeSize(),
  69333. min: 0,
  69334. max: 1000,
  69335. step: 0.01,
  69336. slide: (event, ui) => { this.viewer.setMinNodeSize(ui.value); }
  69337. });
  69338. this.viewer.addEventListener('minnodesize_changed', (event) => {
  69339. $('#lblMinNodeSize').html(parseInt(this.viewer.getMinNodeSize()));
  69340. $('#sldMinNodeSize').slider({value: this.viewer.getMinNodeSize()});
  69341. });
  69342. $('#lblMinNodeSize').html(parseInt(this.viewer.getMinNodeSize()));
  69343. }
  69344. {
  69345. let elSplatQuality = $("#splat_quality_options");
  69346. elSplatQuality.selectgroup({title: "Splat Quality"});
  69347. elSplatQuality.find("input").click( (e) => {
  69348. if(e.target.value === "standard"){
  69349. this.viewer.useHQ = false;
  69350. }else if(e.target.value === "hq"){
  69351. this.viewer.useHQ = true;
  69352. }
  69353. });
  69354. let currentQuality = this.viewer.useHQ ? "hq" : "standard";
  69355. elSplatQuality.find(`input[value=${currentQuality}]`).trigger("click");
  69356. }
  69357. $('#show_bounding_box').click(() => {
  69358. this.viewer.setShowBoundingBox($('#show_bounding_box').prop("checked"));
  69359. });
  69360. $('#set_freeze').click(() => {
  69361. this.viewer.setFreeze($('#set_freeze').prop("checked"));
  69362. });
  69363. }
  69364. }
  69365. class AnnotationTool extends EventDispatcher$1{
  69366. constructor (viewer) {
  69367. super();
  69368. this.viewer = viewer;
  69369. this.renderer = viewer.renderer;
  69370. this.sg = new SphereGeometry(0.1);
  69371. this.sm = new MeshNormalMaterial();
  69372. this.s = new Mesh(this.sg, this.sm);
  69373. }
  69374. startInsertion (args = {}) {
  69375. let domElement = this.viewer.renderer.domElement;
  69376. let annotation = new Annotation({
  69377. position: [589748.270, 231444.540, 753.675],
  69378. title: "Annotation Title",
  69379. description: `Annotation Description`
  69380. });
  69381. this.dispatchEvent({type: 'start_inserting_annotation', annotation: annotation});
  69382. const annotations = this.viewer.scene.annotations;
  69383. annotations.add(annotation);
  69384. let callbacks = {
  69385. cancel: null,
  69386. finish: null,
  69387. };
  69388. let insertionCallback = (e) => {
  69389. if (e.button === MOUSE.LEFT) {
  69390. callbacks.finish();
  69391. } else if (e.button === MOUSE.RIGHT) {
  69392. callbacks.cancel();
  69393. }
  69394. };
  69395. callbacks.cancel = e => {
  69396. annotations.remove(annotation);
  69397. domElement.removeEventListener('mouseup', insertionCallback, true);
  69398. };
  69399. callbacks.finish = e => {
  69400. domElement.removeEventListener('mouseup', insertionCallback, true);
  69401. };
  69402. domElement.addEventListener('mouseup', insertionCallback, true);
  69403. let drag = (e) => {
  69404. let I = Utils.getMousePointCloudIntersection(
  69405. e.drag.end,
  69406. e.viewer.scene.getActiveCamera(),
  69407. e.viewer,
  69408. e.viewer.scene.pointclouds,
  69409. {pickClipped: true});
  69410. if (I) {
  69411. this.s.position.copy(I.location);
  69412. annotation.position.copy(I.location);
  69413. }
  69414. };
  69415. let drop = (e) => {
  69416. viewer.scene.scene.remove(this.s);
  69417. this.s.removeEventListener("drag", drag);
  69418. this.s.removeEventListener("drop", drop);
  69419. };
  69420. this.s.addEventListener('drag', drag);
  69421. this.s.addEventListener('drop', drop);
  69422. this.viewer.scene.scene.add(this.s);
  69423. this.viewer.inputHandler.startDragging(this.s);
  69424. return annotation;
  69425. }
  69426. update(){
  69427. // let camera = this.viewer.scene.getActiveCamera();
  69428. // let domElement = this.renderer.domElement;
  69429. // let measurements = this.viewer.scene.measurements;
  69430. // const renderAreaSize = this.renderer.getSize(new THREE.Vector2());
  69431. // let clientWidth = renderAreaSize.width;
  69432. // let clientHeight = renderAreaSize.height;
  69433. }
  69434. render(){
  69435. //this.viewer.renderer.render(this.scene, this.viewer.scene.getActiveCamera());
  69436. }
  69437. };
  69438. //处理cursor优先级
  69439. var CursorDeal = {
  69440. priorityEvent : [//在前面的优先级高
  69441. {'zoomInCloud':'zoom-in'},
  69442. {'hoverPano':'pointer'},
  69443. {'connectPano':`url({Potree.resourcePath}/images/connect.png),auto`},
  69444. {'disconnectPano':`url({Potree.resourcePath}/images/connect-dis.png),auto`},
  69445. {'hoverLine':'pointer'},
  69446. {'hoverTranHandle':'grab'},
  69447. {"movePointcloud":'move'},
  69448. {"polygon_isIntersectSelf":'not-allowed'},
  69449. {"polygon_AtWrongPlace":'not-allowed'},
  69450. {"markerMove":'grab'},
  69451. {'mapClipMove':'move'},
  69452. {'mapClipRotate':`url({Potree.resourcePath}/images/rotate-cursor.png),auto`},
  69453. {'rotatePointcloud':`url({Potree.resourcePath}/images/rotate-cursor.png),auto`},
  69454. {'siteModelFloorDrag':'row-resize'},
  69455. {'addSth':'cell'},//or crosshair
  69456. ],
  69457. list:[], //当前存在的cursor状态
  69458. currentCursorIndex:null,
  69459. init : function(viewer, viewers){
  69460. this.priorityEvent.forEach(e=>{//刚开始Potree.resourcePath没值,现在换
  69461. for(let i in e){
  69462. e[i] = Common$1.replaceAll(e[i],'{Potree.resourcePath}',Potree.resourcePath);
  69463. }
  69464. });
  69465. this.domElements = viewers.map(e=>e.renderArea);
  69466. viewer.addEventListener("CursorChange",(e)=>{
  69467. if(e.action == 'add'){
  69468. this.add(e.name);
  69469. }else {
  69470. this.remove(e.name);
  69471. }
  69472. });
  69473. },
  69474. add : function(name){
  69475. var priorityItem = this.priorityEvent.find(e=>e[name]);
  69476. if(!priorityItem){
  69477. console.error('CursorDeal 未定义优先级 name:'+ name);
  69478. return
  69479. }
  69480. if(!this.list.includes(name)){
  69481. this.judge({addItem: priorityItem, name});
  69482. this.list.push(name);
  69483. }
  69484. },
  69485. remove : function(name){
  69486. var index = this.list.indexOf(name);
  69487. if(index > -1){
  69488. this.list.splice(index, 1);
  69489. this.judge();
  69490. }
  69491. },
  69492. judge:function(o={}){
  69493. //console.log(o,this.list)
  69494. if(o.addItem){
  69495. var addIndex = this.priorityEvent.indexOf(o.addItem);
  69496. if(addIndex < this.currentCursorIndex || this.currentCursorIndex == void 0){
  69497. this.domElements.forEach(e=>e.style.cursor = o.addItem[o.name] );
  69498. this.currentCursorIndex = addIndex;
  69499. }
  69500. }else {
  69501. var levelMax = {index:Infinity, cursor:null };
  69502. this.list.forEach(name=>{
  69503. var priorityItem = this.priorityEvent.find(e=>e[name]);
  69504. var index = this.priorityEvent.indexOf(priorityItem);
  69505. if(index < levelMax.index){
  69506. levelMax.index = index;
  69507. levelMax.cursor = priorityItem[name];
  69508. }
  69509. });
  69510. this.currentCursorIndex = levelMax.index;
  69511. this.domElements.forEach(e=>e.style.cursor = levelMax.cursor || '');
  69512. }
  69513. }
  69514. };
  69515. class SplitScreen extends EventDispatcher{
  69516. constructor (args = {}) {
  69517. super();
  69518. }
  69519. /*
  69520. viewport.targetPlane // bound中心点处的plane,方向和view一致
  69521. viewport.shiftTarget // camera的位置project在targetPlane上的位置
  69522. 这两个参数的主要目的是为了getPosOutOfModel,以及rotateSideCamera时保持相对位置
  69523. */
  69524. splitStart(cameraProps){
  69525. let viewports = [];
  69526. let subViewports = [viewer.mainViewport];
  69527. if(viewer.mapViewer){
  69528. subViewports.push(viewer.mapViewer.viewports[0]);
  69529. }
  69530. let length = cameraProps.length;
  69531. for(let i=0;i<length;i++){
  69532. let prop = cameraProps[i];
  69533. let viewport;
  69534. let v = subViewports.find(e=>e.name == (prop.name2||prop.name));
  69535. if(v){
  69536. viewport = v;
  69537. viewport.left = prop.left; viewport.bottom = prop.bottom; viewport.width = prop.width; viewport.height = prop.height;
  69538. }
  69539. if(!viewport){
  69540. let view = new ExtendView();
  69541. if(prop.limitBound)view.limitBound = prop.limitBound;
  69542. prop.direction && (view.direction = prop.direction);
  69543. viewport = new Viewport(view , this.getOrthoCamera(), prop );
  69544. if(prop.viewContainsPoints)viewport.viewContainsPoints = prop.viewContainsPoints;
  69545. //viewport.unableDepth = true //depthBasicMaterial等在此viewport中不开启depth
  69546. }
  69547. if(viewport.camera.type == 'OrthographicCamera' ){
  69548. viewport.targetPlane = new Plane();
  69549. viewport.shiftTarget = new Vector3; //project在targetPlane上的位置
  69550. }
  69551. viewport.fitMargin = prop.margin;
  69552. viewports.push(viewport);
  69553. }
  69554. viewer.viewports = viewports;
  69555. viewer.updateScreenSize({forceUpdateSize:true});
  69556. viewports.forEach(viewport=>{
  69557. if(viewport.name == 'MainView')return
  69558. this.viewportFitBound(viewport, viewer.bound.boundingBox , viewer.bound.center , 0, viewport.fitMargin);
  69559. });
  69560. return viewports
  69561. }
  69562. unSplit(){
  69563. this.unfocusViewport();
  69564. viewer.viewports = [viewer.mainViewport];
  69565. viewer.mainViewport.width = 1;
  69566. viewer.mainViewport.height = 1;
  69567. viewer.mainViewport.left = 0;
  69568. viewer.mainViewport.bottom = 0;
  69569. viewer.updateScreenSize({forceUpdateSize:true});
  69570. }
  69571. viewportFitBound(viewport, bound, center, duration=0, margin){
  69572. let view = viewport.view;
  69573. let info = {bound};
  69574. let {boundSize, boundCenter} = this.getViewBound(viewport, bound );
  69575. //this.setShiftTarget(viewport, boundCenter)
  69576. viewport.targetPlane.setFromNormalAndCoplanarPoint( view.direction.clone(), boundCenter );
  69577. viewport.targetPlane.projectPoint(center, viewport.shiftTarget); //target转换到过模型中心的平面,以保证镜头一定在模型外 this.shiftTarget是得到的
  69578. info.endPosition = this.getPosOutOfModel(viewport, boundSize);
  69579. //if(viewport.name == 'mapViewport')info.endPosition.z = Math.max(Potree.config.map.cameraHeight, info.endPosition.z)
  69580. info.margin = margin || {x:30, y:30};
  69581. view.moveOrthoCamera(viewport, info , duration );
  69582. }
  69583. getViewBound(viewport, boundingBox){
  69584. if(boundingBox){
  69585. boundSize = boundingBox.getSize(new Vector3);
  69586. center = boundingBox.getCenter(new Vector3);
  69587. }else {
  69588. var {boundSize, center, boundingBox} = viewer.bound;
  69589. }
  69590. if(viewport.viewContainsPoints){//视野范围内必须要包含的点,直接算入模型区域。这时候得到的boundCenter和模型中心不重合
  69591. boundingBox = boundingBox.clone();
  69592. viewport.viewContainsPoints.forEach(point=>{
  69593. boundingBox.expandByPoint(point);
  69594. });
  69595. boundSize = boundingBox.getSize(new Vector3);
  69596. center = boundingBox.getCenter(new Vector3);
  69597. }
  69598. return {boundSize, boundCenter:center }
  69599. }
  69600. getPosOutOfModel(viewport, boundSize){
  69601. //let {boundSize, center} = viewer.bound
  69602. boundSize = boundSize || this.getViewBound(viewport).boundSize;
  69603. let expand = 10;
  69604. let radius = boundSize.length(); // / 2
  69605. let position = viewport.shiftTarget.clone().sub(viewport.view.direction.clone().multiplyScalar(radius + expand));
  69606. return position
  69607. }
  69608. updateCameraOutOfModel(){//因为移动模型导致模型超出相机外,所以更新位置
  69609. viewer.viewports.forEach((viewport, i )=>{
  69610. if(viewport != viewer.mainViewport){
  69611. let {boundSize, boundCenter} = this.getViewBound(viewport);
  69612. /* viewport.targetPlane.setFromNormalAndCoplanarPoint( viewport.view.direction.clone(), boundCenter)
  69613. viewport.targetPlane.projectPoint(viewport.view.position, viewport.shiftTarget) //target转换到过模型中心的平面,以保证镜头一定在模型外 this.shiftTarget是得到的
  69614. */
  69615. this.setShiftTarget(viewport, boundCenter);
  69616. let endPosition = this.getPosOutOfModel(viewport, boundSize);
  69617. //if(viewport.name == 'mapViewport')endPosition.z = Math.max(Potree.config.map.cameraHeight, endPosition.z)
  69618. viewport.view.position.copy(endPosition);
  69619. }
  69620. });
  69621. }
  69622. setShiftTarget(viewport, center){
  69623. if(!viewport.targetPlane ){
  69624. viewport.targetPlane = new Plane();
  69625. viewport.shiftTarget = new Vector3; //project在targetPlane上的位置
  69626. }
  69627. viewport.targetPlane.setFromNormalAndCoplanarPoint(viewport.view.direction, center );
  69628. viewport.targetPlane.projectPoint(viewport.view.position, viewport.shiftTarget ); //target转换到过模型中心的平面,以保证镜头一定在模型外
  69629. }
  69630. rotateSideCamera(viewport, angle){//侧视图绕模型中心水平旋转
  69631. //let {boundSize, center} = viewer.bound
  69632. let {boundSize, boundCenter } = this.getViewBound(viewport);
  69633. let center = this.focusCenter || boundCenter; //旋转中心,一般是所有模型的中心,除非想指定中心点
  69634. this.setShiftTarget(viewport, center);
  69635. //找到平移向量
  69636. let vec = new Vector3().subVectors(center, viewport.shiftTarget);//相对于中心的偏移值,旋转后偏移值也旋转
  69637. //旋转
  69638. var rotMatrix = new Matrix4().makeRotationAxis(new Vector3(0,0,1), angle);
  69639. viewport.view.direction = viewport.view.direction.applyMatrix4(rotMatrix);
  69640. vec.applyMatrix4(rotMatrix);
  69641. viewport.shiftTarget.subVectors(center,vec); //新的
  69642. viewport.view.position = this.getPosOutOfModel(viewport, boundSize);
  69643. }
  69644. getOrthoCamera(){
  69645. let camera = new OrthographicCamera(-100, 100, 100, 100, 0.01, 10000);
  69646. camera.up.set(0,0,1);
  69647. return camera
  69648. }
  69649. focusOnViewport(name){//全屏
  69650. viewer.viewports.forEach((viewport, i )=>{
  69651. if(viewport.name == name){
  69652. this.focusInfo = {
  69653. name,
  69654. left : viewport.left, bottom : viewport.bottom, height : viewport.height, width : viewport.width
  69655. };
  69656. viewport.left = 0; viewport.bottom = 0; viewport.height = 1; viewport.width = 1;
  69657. }else {
  69658. viewport.active = false;
  69659. }
  69660. });
  69661. viewer.updateScreenSize({forceUpdateSize:true});
  69662. }
  69663. unfocusViewport(){
  69664. if(!this.focusInfo)return
  69665. viewer.viewports.forEach((viewport, i )=>{
  69666. if(this.focusInfo.name == viewport.name){//全屏的恢复
  69667. viewport.left = this.focusInfo.left;
  69668. viewport.bottom = this.focusInfo.bottom;
  69669. viewport.height = this.focusInfo.height;
  69670. viewport.width = this.focusInfo.width;
  69671. }
  69672. viewport.active = true;
  69673. });
  69674. viewer.updateScreenSize({forceUpdateSize:true});
  69675. this.focusInfo = null;
  69676. }
  69677. }
  69678. const FEET_TO_INCHES_FACTOR = 12;
  69679. const EIGHTHS_SYMBOLS = ["", "⅛", "¼", "⅜", "½", "⅝", "¾", "⅞"];//eighths 八分之……
  69680. class UnitOfMeasurement{//转化单位工具
  69681. constructor(t, e, n, i){
  69682. this.name = t,
  69683. this.symbol = e,
  69684. this.base = n,
  69685. this.factor = i;
  69686. }
  69687. toBase(t) {//换算到base
  69688. return t * this.factor
  69689. }
  69690. fromBase(t) {//换算到当前
  69691. return t / this.factor
  69692. }
  69693. }
  69694. /* var o = function t(e) {
  69695. this.gettext = e,
  69696. t.METRIC = this.gettext("metric", void 0, "measurement system"),
  69697. t.IMPERIAL = this.gettext("imperial", void 0, "measurement system")
  69698. };
  69699. e.UoMSystem = o;
  69700. let UoMSystem = {
  69701. } */
  69702. /* var MeasurementDomain = {
  69703. DISTANCE : "DISTANCE",
  69704. t.AREA = "AREA",
  69705. t.VOLUME = "VOLUME",
  69706. t.DATA = "DATA",
  69707. t
  69708. }
  69709. */
  69710. var UnitsOfMeasurement = {
  69711. MILLIMETER : ["Millimeter", "mm"],
  69712. CENTIMETER : ["Centimeter", "cm"],
  69713. METER : ["Meter", "m"],
  69714. KILOMETER : ["Kilometer", "km"],
  69715. INCH : ["Inch", "in"],
  69716. FOOT : ["Foot", "ft"],
  69717. MILE : ["Mile", "mi"],
  69718. SQUAREMETER : ["SquareMeter", "m²"],
  69719. SQUAREFOOT : ["SquareFoot", "ft²"],
  69720. CUBICMETER : ["CubicMeter", "m³"],
  69721. CUBICFOOT : ["CubicFoot", "ft³"],
  69722. BYTE : ["Byte", "B"],
  69723. KILOBYTE : ["Kilobyte", "kB"],
  69724. MEGABYTE : ["Megabyte", "MB"],
  69725. GIGABYTE : ["Gigabyte", "GB"],
  69726. TERABYTE : ["Terabyte", "TB"],
  69727. PETABYTE : ["Petabyte", "PB"],
  69728. init : function() {
  69729. var e, n, i, a, s, c, l, u, d, p, h,
  69730. f = new UnitOfMeasurement(UnitsOfMeasurement.METER[0],UnitsOfMeasurement.METER[1],void 0,1),
  69731. g = new UnitOfMeasurement(UnitsOfMeasurement.SQUAREMETER[0],UnitsOfMeasurement.SQUAREMETER[1],void 0,1),
  69732. m = new UnitOfMeasurement(UnitsOfMeasurement.CUBICMETER[0],UnitsOfMeasurement.CUBICMETER[1],void 0,1),
  69733. v = new UnitOfMeasurement(UnitsOfMeasurement.BYTE[0],UnitsOfMeasurement.BYTE[1],void 0,1);
  69734. UnitsOfMeasurement.DISTANCE = (
  69735. (e = {})['metric'] = ((n = {})[UnitsOfMeasurement.MILLIMETER[0]] = new UnitOfMeasurement(UnitsOfMeasurement.MILLIMETER[0],UnitsOfMeasurement.MILLIMETER[1],f,.001),
  69736. n[UnitsOfMeasurement.CENTIMETER[0]] = new UnitOfMeasurement(UnitsOfMeasurement.CENTIMETER[0],UnitsOfMeasurement.CENTIMETER[1],f,.01),
  69737. n[UnitsOfMeasurement.METER[0]] = f,
  69738. n[UnitsOfMeasurement.KILOMETER[0]] = new UnitOfMeasurement(UnitsOfMeasurement.KILOMETER[0],UnitsOfMeasurement.KILOMETER[1],f,1e3),
  69739. n),
  69740. e['imperial'] = ((i = {})[UnitsOfMeasurement.INCH[0]] = new UnitOfMeasurement(UnitsOfMeasurement.INCH[0],UnitsOfMeasurement.INCH[1],f,.0254),
  69741. i[UnitsOfMeasurement.FOOT[0]] = new UnitOfMeasurement(UnitsOfMeasurement.FOOT[0],UnitsOfMeasurement.FOOT[1],f,.3048),
  69742. i[UnitsOfMeasurement.MILE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.MILE[0],UnitsOfMeasurement.MILE[1],f,1609.344),
  69743. i),
  69744. e);
  69745. UnitsOfMeasurement.AREA = ((a = {})['metric'] = ((s = {})[UnitsOfMeasurement.SQUAREMETER[0]] = g,
  69746. s),
  69747. a['imperial'] = ((c = {})[UnitsOfMeasurement.SQUAREFOOT[0]] = new UnitOfMeasurement(UnitsOfMeasurement.SQUAREFOOT[0],UnitsOfMeasurement.SQUAREFOOT[1],g,.092903),
  69748. c),
  69749. a);
  69750. UnitsOfMeasurement.VOLUME = ((l = {})['metric'] = ((u = {})[UnitsOfMeasurement.CUBICMETER[0]] = m,
  69751. u),
  69752. l['imperial'] = ((d = {})[UnitsOfMeasurement.CUBICFOOT[0]] = new UnitOfMeasurement(UnitsOfMeasurement.CUBICFOOT[0],UnitsOfMeasurement.CUBICFOOT[1],m,.0283168),
  69753. d),
  69754. l);
  69755. //数据大小
  69756. var y = ((p = {})[UnitsOfMeasurement.BYTE[0]] = v,
  69757. p[UnitsOfMeasurement.KILOBYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.KILOBYTE[0],UnitsOfMeasurement.KILOBYTE[1],v,1e3),
  69758. p[UnitsOfMeasurement.MEGABYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.MEGABYTE[0],UnitsOfMeasurement.MEGABYTE[1],v,1e6),
  69759. p[UnitsOfMeasurement.GIGABYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.GIGABYTE[0],UnitsOfMeasurement.GIGABYTE[1],v,1e9),
  69760. p[UnitsOfMeasurement.TERABYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.TERABYTE[0],UnitsOfMeasurement.TERABYTE[1],v,1e12),
  69761. p[UnitsOfMeasurement.PETABYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.PETABYTE[0],UnitsOfMeasurement.PETABYTE[1],v,1e15),
  69762. p);
  69763. UnitsOfMeasurement.DATA = ((h = {})['metric'] = y,
  69764. h['imperial'] = y,
  69765. h);
  69766. }
  69767. ,
  69768. getUnitsOfMeasurementByDomain : function(e) {
  69769. return this[e.toUpperCase()]
  69770. /* switch (e.toUpperCase()) {
  69771. case a.DISTANCE:
  69772. return t.DISTANCE;
  69773. case a.AREA:
  69774. return t.AREA;
  69775. case a.VOLUME:
  69776. return t.VOLUME;
  69777. case a.DATA:
  69778. return t.DATA;
  69779. default:
  69780. console.error(e + " measurement domain is not supported.")
  69781. } */
  69782. }
  69783. ,
  69784. getUnitsOfMeasurementByDomainAndSystem : function(domain, system) {
  69785. var r = this.getUnitsOfMeasurementByDomain(domain);
  69786. if (r.hasOwnProperty(system.toLowerCase()))
  69787. return r[system.toLowerCase()];
  69788. console.error(n + " measurement system is not supported.");
  69789. }
  69790. ,
  69791. getDefaultUnitByDomainAndSystem : function(e, n) {
  69792. switch (e.toUpperCase()) {
  69793. case 'DISTANCE':
  69794. switch (n.toLowerCase()) {
  69795. case 'metric':
  69796. return this.DISTANCE['metric'][this.METER[0]];
  69797. case 'imperial':
  69798. return this.DISTANCE['imperial'][this.FOOT[0]];
  69799. default:
  69800. console.error(n + " measurement system is not supported.");
  69801. }
  69802. case 'AREA':
  69803. switch (n.toLowerCase()) {
  69804. case 'metric':
  69805. return this.AREA['metric'][this.SQUAREMETER[0]];
  69806. case 'imperial':
  69807. return this.AREA['imperial'][this.SQUAREFOOT[0]];
  69808. default:
  69809. console.error(n + " measurement system is not supported.");
  69810. }
  69811. case 'VOLUME':
  69812. switch (n.toLowerCase()) {
  69813. case 'metric':
  69814. return this.VOLUME['metric'][this.CUBICMETER[0]];
  69815. case 'imperial':
  69816. return this.VOLUME['imperial'][this.CUBICFOOT[0]];
  69817. default:
  69818. console.error(n + " measurement system is not supported.");
  69819. }
  69820. case 'DATA':
  69821. switch (n.toLowerCase()) {
  69822. case 'metric':
  69823. return this.DATA['metric'][this.BYTE[0]];
  69824. case 'imperial':
  69825. return this.DATA['imperial'][this.BYTE[0]];
  69826. default:
  69827. console.error(n + " measurement system is not supported.");
  69828. }
  69829. default:
  69830. console.error(e + " measurement domain is not supported.");
  69831. }
  69832. }
  69833. };
  69834. class UnitService{
  69835. constructor(/* e, n, i */){
  69836. //this.LanguageService = e,
  69837. //this.localStorageService = n,
  69838. //this.gettext = i,
  69839. //this.unitChanged = new r.Signal,
  69840. this.LOCAL_STORAGE_KEY = "iv_unit_key";//?
  69841. UnitsOfMeasurement.init();
  69842. this.unitSystems = ['metric', 'imperial'];//[o.UoMSystem.METRIC, o.UoMSystem.IMPERIAL],
  69843. this.defaultSystem = 'metric';//'imperial'
  69844. //var a = this.LanguageService.getBrowserLocaleString().toLowerCase();
  69845. //this.defaultSystem = t.isLocaleImperial(a) ? o.UoMSystem.IMPERIAL : o.UoMSystem.METRIC,
  69846. //this.initUnit()
  69847. }
  69848. /* initUnit() {
  69849. var t = this.localStorageService.get(this.LOCAL_STORAGE_KEY);
  69850. if (t)
  69851. for (var e = 0, n = this.unitSystems; e < n.length; e++) {
  69852. var i = n[e];
  69853. if (i === t)
  69854. return void this.setUnit(i, !0)
  69855. }
  69856. this.setUnit(this.defaultSystem, !1)
  69857. }
  69858. setUnit(t, e) {
  69859. this.currentSystem !== t && (this.currentSystem = t,
  69860. this.unitChanged.emit()),
  69861. e && this.localStorageService.set(this.LOCAL_STORAGE_KEY, t)
  69862. } */
  69863. /*isLocaleImperial(e) {
  69864. return t.IMPERIAL_LOCALES.indexOf(e.toLowerCase()) >= 0
  69865. }
  69866. ,
  69867. t.IMPERIAL_LOCALES = ["en_us"],
  69868. t.ɵfac(e) {
  69869. return new (e || t)(c.ɵɵinject(l.LanguageService),
  69870. c.ɵɵinject("localStorageService"),c.ɵɵinject("gettext"))
  69871. }
  69872. ,
  69873. t.ɵprov = c.ɵɵdefineInjectable({
  69874. token: t,
  69875. factory: t.ɵfac,
  69876. providedIn: "root"
  69877. }), */
  69878. }
  69879. class UoMService{
  69880. constructor(/* UnitService */){
  69881. this.UnitService = new UnitService();/* UnitService */
  69882. }
  69883. scopedConvert (t, n, precision = 2, r, minFactor) {
  69884. return this.convert(t, n, precision, r, minFactor)
  69885. }
  69886. convert(number, domain, precision = 2, system, minFactor, ifEighths = !1) {
  69887. if (!number) return "";
  69888. var s = this.getMostRelevantMeasurement(domain, system || this.UnitService.currentSystem, number, minFactor);
  69889. return this.getFormattedMeasurementString(s[0], s[1], precision, ifEighths)
  69890. }
  69891. convertBack(number, domain, precision = 2, fromSystem, minFactor ) { //从英制转到'metric'
  69892. if (!number) return "";
  69893. var d = UnitsOfMeasurement.getDefaultUnitByDomainAndSystem(domain,'metric');
  69894. var s = this.getMostRelevantMeasurement2(domain, fromSystem, number, minFactor);
  69895. return this.getFormattedMeasurementString(s[0], d, precision )
  69896. /* 栗子:
  69897. viewer.unitConvert.convertBack(1, 'area', 5, 'imperial')
  69898. '0.09290 m²'
  69899. viewer.unitConvert.convertBack(1, 'Distance', 2, 'imperial')
  69900. '0.03 m'
  69901. */
  69902. }
  69903. getFormattedMeasurementString(number, unit, precision, ifEighths) {
  69904. var result;
  69905. if(ifEighths && unit.name === UnitsOfMeasurement.FOOT[0]){
  69906. result = this.formatImperialDistance(number * FEET_TO_INCHES_FACTOR);
  69907. }else if(ifEighths && unit.name === UnitsOfMeasurement.INCH[0]){
  69908. result = this.formatImperialDistance(number);
  69909. }else {
  69910. result = number.toLocaleString(void 0, {
  69911. minimumFractionDigits: precision,
  69912. maximumFractionDigits: precision
  69913. }) + " " + unit.symbol;
  69914. }
  69915. return result
  69916. }
  69917. formatImperialDistance(e) {
  69918. var n = Math.round(8 * e)
  69919. , i = Math.floor(n / 8)
  69920. , r = Math.floor(i / FEET_TO_INCHES_FACTOR)
  69921. , o = i - r * FEET_TO_INCHES_FACTOR
  69922. , a = EIGHTHS_SYMBOLS[n % 8]
  69923. , s = 0 === o && "" !== a ? "" : o;
  69924. "" !== s && "" !== a && (a = " " + a);
  69925. return 0 !== r ? r + "' " + s + a + '"' : "" + s + a + '"'
  69926. }
  69927. getMostRelevantMeasurement(domain, system, number, minFactor=0) {
  69928. /* var a = r.values(UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system))
  69929. , s = r.filter(a, function(t) {
  69930. return t.factor >= i
  69931. })
  69932. , c = r.reduce(s, function(t, e) {
  69933. return e.fromBase(number) < t.fromBase(number) && e.fromBase(number) >= 1 ? e : t
  69934. }); */
  69935. let a = [];
  69936. let u = UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system);
  69937. for(let i in u){a.push(u[i]);}
  69938. let s = a.filter(m=>m.factor >= minFactor);
  69939. let c = s.reduce(function(prev, currentValue) {//reduce最终值是最后一次return的值 ( 没看懂这句话作用)
  69940. return currentValue.fromBase(number) < prev.fromBase(number) && currentValue.fromBase(number) >= 1 ? currentValue : prev
  69941. });
  69942. return c ? [c.fromBase(number), c] : void 0
  69943. }
  69944. getMostRelevantMeasurement2(domain, system, number, minFactor=0) {//add
  69945. let a = [];
  69946. let u = UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system);
  69947. for(let i in u){a.push(u[i]);}
  69948. let s = a.filter(m=>m.factor >= minFactor);
  69949. let c = s.reduce(function(prev, currentValue) {//reduce最终值是最后一次return的值 ( 没看懂这句话作用)
  69950. return currentValue.toBase(number) < prev.toBase(number) && currentValue.toBase(number) >= 1 ? currentValue : prev
  69951. });
  69952. return c ? [c.toBase(number), c] : void 0
  69953. }
  69954. /* ɵfac(e){
  69955. return new (e || t)(c.ɵɵinject(l.UnitService))
  69956. }
  69957. ɵprov = c.ɵɵdefineInjectable({
  69958. token: t,
  69959. factory: t.ɵfac,
  69960. providedIn: "root"
  69961. }) */
  69962. }
  69963. let texLoader$6 = new TextureLoader();
  69964. let color$1 = new Color(config$1.clip.color);
  69965. let markerMats$1;
  69966. let markerSizeInfo$1 = {width2d: 40};
  69967. const pickOrders = {
  69968. marker:1,
  69969. area: 0,
  69970. };
  69971. class mapClipBox extends ctrlPolygon {
  69972. constructor (center, scale) {
  69973. center = center.clone().setZ(0);//所有Z都为0
  69974. let prop = {
  69975. points : getPoints(center, scale, 0),
  69976. closed : true,
  69977. atPlane: true,
  69978. isRect : true,
  69979. dimension : '2d'
  69980. };
  69981. super('mapClipBox', prop);
  69982. this.angle = 0;
  69983. this.createRotateBar();
  69984. this.edgeMarkers = [];
  69985. //addMarkers:
  69986. this.initData(prop);
  69987. {//areaPlane event 能拖动
  69988. this.areaPlane.addEventListener('mouseover',()=>{
  69989. viewer.dispatchEvent({
  69990. type : "CursorChange", action : "add", name:"mapClipMove"
  69991. });
  69992. });
  69993. this.areaPlane.addEventListener('mouseleave',()=>{
  69994. viewer.dispatchEvent({
  69995. type : "CursorChange", action : "remove", name:"mapClipMove"
  69996. });
  69997. });
  69998. let lastPos;
  69999. let drag = (e)=>{
  70000. let intersect = e.intersect.orthoIntersect;
  70001. if(lastPos){
  70002. let moveVec = new Vector3().subVectors(intersect, lastPos).setZ(0);
  70003. this.center.add(moveVec);
  70004. this.updatePoints();
  70005. this.dispatchEvent({type:'repos'});
  70006. }
  70007. lastPos = intersect.clone();
  70008. };
  70009. let drop = (e)=>{
  70010. lastPos = null;
  70011. };
  70012. this.areaPlane.addEventListener('drag', drag);
  70013. this.areaPlane.addEventListener('drop', drop);
  70014. }
  70015. /* this.addEventListener('dragChange',()=>{
  70016. this.updateTwoMidMarker(index+1)
  70017. }) */
  70018. Potree.Utils.setObjectLayers(this, 'mapObjects' );
  70019. }
  70020. getScale(){
  70021. return new Vector3(this.points[0].distanceTo(this.points[1]), this.points[1].distanceTo(this.points[2]) ,1)
  70022. }
  70023. addMarker(o={} ){
  70024. let marker = new Sprite$2({mat:this.getMarkerMaterial('default'), pickOrder:pickOrders.marker, sizeInfo: markerSizeInfo$1, dontFixOrient: true, viewports:viewer.mapViewer.viewports, name:"mapClipBox_marker", } );
  70025. marker.renderOrder = 3;
  70026. //marker.markerSelectStates = {}
  70027. let edge = LineDraw.createLine([new Vector3,new Vector3],{color: color$1 });
  70028. let edgeMarker = new Sprite$2({mat:this.getMarkerMaterial('default'), pickOrder:pickOrders.marker, sizeInfo: markerSizeInfo$1, dontFixOrient: true, viewports:viewer.mapViewer.viewports, name:"mapClipBox_edgePoint"} );
  70029. let mouseover = (e) => {
  70030. this.setMarkerSelected(e.object, true, 'single');
  70031. viewer.dispatchEvent({
  70032. type : "CursorChange", action : "add", name:"markerMove"
  70033. });
  70034. };
  70035. let mouseleave = (e) => {
  70036. this.setMarkerSelected(e.object, false, 'single');
  70037. viewer.dispatchEvent({
  70038. type : "CursorChange", action : "remove", name:"markerMove"
  70039. });
  70040. };
  70041. edgeMarker.addEventListener('mouseover', mouseover);
  70042. edgeMarker.addEventListener('mouseleave', mouseleave);
  70043. let dragInfo = {lastPos:null};
  70044. edgeMarker.addEventListener('drag', this.dragEdge.bind(this,dragInfo));
  70045. edgeMarker.addEventListener('drop', this.dropEdge.bind(this,dragInfo));
  70046. this.edgeMarkers.push(edgeMarker);
  70047. this.add(edgeMarker);
  70048. marker.dispatchEvent('addHoverEvent');
  70049. super.addMarker({point:o.point, marker:marker, edge});
  70050. }
  70051. dragEdge(dragInfo, e){//拖拽一个边(或一个边类型的marker),带动它的两个端点。 可以转化为拖拽marker往法线方向
  70052. var I, atMap;
  70053. atMap = e.dragViewport.name == 'mapViewport';
  70054. I = e.intersect.orthoIntersect;
  70055. if (I && dragInfo.lastPos) {
  70056. let i = this.edgeMarkers.indexOf(e.drag.object);
  70057. if (i !== -1) {
  70058. let lineNormal = math.getNormal2d({p1:this.points[i], p2:this.points[(i+1)%4]});
  70059. let moveVec = new Vector3().subVectors(I, dragInfo.lastPos).setZ(0);//移动的向量
  70060. let dragVec = moveVec.projectOnVector(lineNormal).setZ(0);//在法线上移动的向量
  70061. let newPos = new Vector3().addVectors(this.points[i], dragVec); //marker应到的位置
  70062. this.dragChange(newPos, i, atMap); //转化为这个marker的拖拽
  70063. }
  70064. }
  70065. dragInfo.lastPos = I.clone();
  70066. }
  70067. dropEdge(dragInfo, e){
  70068. dragInfo.lastPos = null;
  70069. this.setMarkerSelected(e.drag.object, false, 'single'); //拖拽时似乎没有触发mouseout
  70070. }
  70071. createAreaPlane(){
  70072. var planeMat = new MeshBasicMaterial({
  70073. color: color$1,//"#00eeff",
  70074. side:DoubleSide,
  70075. opacity:0.3,
  70076. transparent:true,
  70077. depthTest:false
  70078. });
  70079. return super.createAreaPlane(planeMat)
  70080. }
  70081. getMarkerMaterial(type) {
  70082. if(!markerMats$1){
  70083. markerMats$1 = {
  70084. default: new MeshBasicMaterial({
  70085. transparent: !0,
  70086. color: color$1,
  70087. opacity: 0.8,
  70088. map: texLoader$6.load(Potree.resourcePath+'/textures/whiteCircle.png' ),
  70089. }),
  70090. select: new MeshBasicMaterial({
  70091. transparent: !0,
  70092. color: color$1,
  70093. opacity: 1,
  70094. map: texLoader$6.load(Potree.resourcePath+'/textures/whiteCircle.png' ),
  70095. }),
  70096. };
  70097. mapClipBox.markerMats = markerMats$1;
  70098. }
  70099. return markerMats$1[type]
  70100. }
  70101. setMarkerSelected(marker, state, hoverObject){
  70102. //console.warn(marker.id , state, hoverObject)
  70103. if(state == 'hover'){
  70104. marker.material = this.getMarkerMaterial('select');
  70105. }else {
  70106. marker.material = this.getMarkerMaterial('default');
  70107. }
  70108. /* marker.markerSelectStates[hoverObject] = state
  70109. let absoluteState = false
  70110. for(var i in marker.markerSelectStates){
  70111. if(marker.markerSelectStates[i]){
  70112. absoluteState = true; break;
  70113. }
  70114. }
  70115. if(absoluteState){
  70116. marker.material = this.getMarkerMaterial('select')
  70117. }else{
  70118. marker.material = this.getMarkerMaterial('default')
  70119. }
  70120. marker.selected = absoluteState */
  70121. viewer.mapViewer.dispatchEvent('content_changed');
  70122. }
  70123. createRotateBar(){
  70124. //中心点在线的一端,整体初始在box上方
  70125. const lineLen = 1.5, circleWidth = 2, barOpacity = 0.7;
  70126. let object = new Object3D;
  70127. let bar = new Sprite$2({mat:new MeshBasicMaterial({
  70128. side:DoubleSide,
  70129. opacity: barOpacity,
  70130. transparent:true,
  70131. depthTest:false,
  70132. map: texLoader$6.load(Potree.resourcePath+'/textures/rotation_circle.png' ),
  70133. }) ,
  70134. root:object,
  70135. sizeInfo: markerSizeInfo$1,
  70136. dontFixOrient: true,
  70137. viewports:viewer.mapViewer.viewports,
  70138. name:"mapClipRotateBar"
  70139. });
  70140. bar.position.set(0,lineLen+circleWidth/2,0);
  70141. bar.scale.set(circleWidth,circleWidth,circleWidth);
  70142. bar.addEventListener('mouseover',()=>{
  70143. bar.material.opacity = 1;
  70144. viewer.dispatchEvent({
  70145. type : "CursorChange", action : "add", name:"mapClipRotate"
  70146. });
  70147. viewer.mapViewer.dispatchEvent('content_changed');
  70148. });
  70149. let leave = ()=>{
  70150. bar.material.opacity = barOpacity;
  70151. viewer.dispatchEvent({
  70152. type : "CursorChange", action : "remove", name:"mapClipRotate"
  70153. });
  70154. viewer.mapViewer.dispatchEvent('content_changed');
  70155. };
  70156. bar.addEventListener('mouseleave',leave);
  70157. this.addEventListener('dispose', leave);
  70158. let lastPos;
  70159. bar.addEventListener('drag',(e)=>{
  70160. var intersect = e.intersect.orthoIntersect;
  70161. if(lastPos){
  70162. let vec1 = new Vector3().subVectors(lastPos, this.center).setZ(0);
  70163. let vec2 = new Vector3().subVectors(intersect, this.center).setZ(0);
  70164. let angle = math.getAngle(vec1,vec2,'z');
  70165. this.angle += angle;
  70166. this.rotateBar.rotation.z = this.angle;
  70167. this.updatePoints();
  70168. this.dispatchEvent({type:'rotate', angle: this.angle});
  70169. }
  70170. lastPos = intersect.clone();
  70171. });
  70172. bar.addEventListener('drop',()=>{
  70173. lastPos = null;
  70174. viewer.dispatchEvent({
  70175. type : "CursorChange", action : "remove", name:"mapClipRotate"
  70176. });
  70177. });
  70178. let line = LineDraw.createLine([new Vector3, new Vector3(0,lineLen,0)],{color: color$1});
  70179. object.add(bar);
  70180. object.add(line);
  70181. this.add(object);
  70182. this.rotateBar = object;
  70183. this.rotateBar.bar = bar;
  70184. }
  70185. updatePoints(scale){
  70186. this.points = getPoints(this.center, scale || this.getScale(), this.angle);
  70187. this.getPoint2dInfo(this.points);
  70188. this.update({ifUpdateMarkers:true});
  70189. }
  70190. update(options={}){
  70191. super.update(options);
  70192. {//update rotateBar
  70193. let center = new Vector3().addVectors(this.points[0], this.points[1]).multiplyScalar(0.5);
  70194. this.rotateBar.position.copy(center);
  70195. this.rotateBar.bar.update();//更新sprite matrix
  70196. }
  70197. {
  70198. for(let i=0;i<4;i++){
  70199. let current = this.points[i];
  70200. let next = this.points[(i+1)%4];
  70201. let mid = new Vector3().addVectors(current, next).multiplyScalar(0.5);
  70202. this.updateMarker(this.edgeMarkers[i], mid);
  70203. }
  70204. }
  70205. }
  70206. dispose(){
  70207. super.dispose();
  70208. this.dispatchEvent('dispose');
  70209. }
  70210. }
  70211. function getPoints(center, scale, angle=0){
  70212. let points = [
  70213. new Vector3(-scale.x/2, +scale.y/2, 0),
  70214. new Vector3(+scale.x/2, +scale.y/2, 0),
  70215. new Vector3(+scale.x/2, -scale.y/2, 0),
  70216. new Vector3(-scale.x/2, -scale.y/2, 0),
  70217. ];
  70218. var rotMatrix = new Matrix4().makeRotationAxis(new Vector3(0,0,1), angle);//再旋转
  70219. points.forEach(e=>{
  70220. e.applyMatrix4(rotMatrix);
  70221. e.add(center);
  70222. });
  70223. return points
  70224. }
  70225. const defaultBoxWidth = 16; //navvis: 10
  70226. //navvis position: si {x: 0, y: 0, z: 0}
  70227. var Clip = {
  70228. bus : new EventDispatcher,
  70229. selectedDatasets : [],
  70230. changeCallback(force){
  70231. viewer.controls.setTarget(this.box.position);//绕其旋转
  70232. if(Potree.settings.isOfficial){
  70233. let fun = ()=>{
  70234. let pointclouds = this.getIntersectPointcloud();
  70235. if( Common$1.getDifferenceSet(pointclouds,this.selectedDatasets).length){
  70236. this.selectedDatasets = pointclouds;
  70237. //console.error('clipSelectedDatasets',selectedDatasets)
  70238. this.bus.dispatchEvent({type:'updateSelectedDatasets', selectedDatasets:pointclouds.map(e=>e.dataset_id) });
  70239. }
  70240. };
  70241. if(force)fun();
  70242. else Common$1.intervalTool.isWaiting('clipSelectedDatasets', fun , 300);
  70243. }
  70244. },
  70245. enter:function(){
  70246. this.previousView = {
  70247. position: viewer.images360.position,
  70248. target: viewer.scene.view.getPivot(),
  70249. displayMode : Potree.settings.displayMode,
  70250. //---
  70251. ifShowMarker : Potree.settings.ifShowMarker,
  70252. };
  70253. let pointcloud = this.getPointcloud();
  70254. let bound = pointcloud.bound; //只选取其中一个数据集的bound,而非整体,是因为担心两个数据集中间有空隙,于是刚好落在没有点云的地方。
  70255. let boundSize = bound.getSize(new Vector3());
  70256. let target = this.getTarget(bound.getCenter(new Vector3())); //navvis的位置xy是用相机位置 this.ViewService.mainView.getCamera().position 我觉得也可以用第一个漫游点的,或者最接近bound中心的漫游点
  70257. let scale = new Vector3(defaultBoxWidth,defaultBoxWidth, boundSize.z);//z和navvis一样
  70258. let eyeDir = viewer.scene.view.direction.clone().setZ(0/* -boundSize.z/3 */).multiplyScalar(-defaultBoxWidth); //为了使所在楼层不变,不修改z
  70259. //let eyeDir = scale.clone().setZ(boundSize.z/3).multiplyScalar(1.3)
  70260. let position = new Vector3().addVectors(target, eyeDir);
  70261. Potree.settings.displayMode = 'showPointCloud';
  70262. viewer.setView({
  70263. position ,
  70264. target,
  70265. duration:300,
  70266. callback:function(){
  70267. }
  70268. });
  70269. //viewer.setControls(viewer.orbitControls);
  70270. viewer.setLimitFar(false);
  70271. //viewer.setClipState(false) //暂时关闭旧的clipping
  70272. {
  70273. this.box = new BoxVolume$1({
  70274. clip:true
  70275. });
  70276. this.box.clipTask = ClipTask['SHOW_INSIDE_Big' /* "SHOW_INSIDE" */];
  70277. this.box.showBox = false;
  70278. this.box.name = "ClipBox";
  70279. this.box.position.copy(target);
  70280. this.box.scale.copy(scale);
  70281. //带动mapBox
  70282. this.box.addEventListener('position_changed',e=>{
  70283. this.mapBox.center.setX(this.box.position.x);
  70284. this.mapBox.center.setY(this.box.position.y);
  70285. this.mapBox.updatePoints();
  70286. this.changeCallback();
  70287. });
  70288. this.box.addEventListener('scale_changed',e=>{
  70289. var scale = this.box.scale;
  70290. this.mapBox.updatePoints(scale);
  70291. this.changeCallback();
  70292. });
  70293. this.box.addEventListener('orientation_changed',e=>{
  70294. this.mapBox.angle = this.box.rotation.z;
  70295. this.mapBox.rotateBar.rotation.z = this.mapBox.angle;
  70296. this.mapBox.updatePoints();
  70297. this.changeCallback();
  70298. });
  70299. viewer.scene.addVolume(this.box);
  70300. }
  70301. {//map
  70302. let boxRotateBack = ()=>{//不知道是不是这么写。 因为可能z的旋转不一定都在z
  70303. this.box.rotation.x = 0;
  70304. this.box.rotation.y = 0;
  70305. };
  70306. this.mapBox = new mapClipBox(target, scale);
  70307. viewer.mapViewer.scene.add(this.mapBox);
  70308. //带动box
  70309. this.mapBox.addEventListener('repos',e=>{
  70310. this.box.position.setX(this.mapBox.center.x);
  70311. this.box.position.setY(this.mapBox.center.y);
  70312. boxRotateBack();
  70313. this.changeCallback();
  70314. });
  70315. this.mapBox.addEventListener('dragChange',e=>{
  70316. var scale = this.mapBox.getScale();
  70317. this.box.scale.setX(scale.x);
  70318. this.box.scale.setY(scale.y);
  70319. this.box.position.setX(this.mapBox.center.x);
  70320. this.box.position.setY(this.mapBox.center.y);
  70321. boxRotateBack();
  70322. this.changeCallback();
  70323. });
  70324. this.mapBox.addEventListener('rotate',e=>{
  70325. this.box.rotation.z = this.mapBox.angle;
  70326. boxRotateBack();
  70327. this.changeCallback();
  70328. });
  70329. }
  70330. {
  70331. //viewer.setClipTask(ClipTask["SHOW_INSIDE"])
  70332. }
  70333. Potree.settings.unableNavigate = true;
  70334. Potree.settings.ifShowMarker = false;
  70335. Potree.Utils.updateVisible(viewer.measuringTool.scene, 'clipModel', false);
  70336. //Potree.Utils.updateVisible(viewer.mapViewer.cursor, 'clipModel', false)//隐藏地图游标
  70337. viewer.inputHandler.toggleSelection(this.box);
  70338. viewer.inputHandler.fixSelection = true;
  70339. viewer.transformationTool.frame.material.color.set(Potree.config.clip.color);//navvis 15899953
  70340. viewer.setPointStandardMat(true);
  70341. {
  70342. let mapVisi = false;
  70343. this.events = {
  70344. flyToPos : (e)=>{
  70345. let dis = 2;
  70346. let target = e.position;
  70347. //position = new THREE.Vector3().subVectors(target, this.scene.view.direction)
  70348. //永远朝向框的中心
  70349. /* let dir = new THREE.Vector3().subVectors(this.box.position, e.position).normalize()
  70350. position = new THREE.Vector3().subVectors(target, dir) */
  70351. target = this.box.position;
  70352. position = e.position;
  70353. //为了方便缩放操作,直接使用box中心作为target
  70354. let duration = e.duration == void 0 ? 1000 : e.duration;
  70355. viewer.scene.view.setView({position, duration, target});
  70356. },
  70357. mapVisiChange(e){
  70358. mapVisi = e.visible;
  70359. let delay = 100; //因resize了camera需要时间更新projectionMatrix
  70360. setTimeout(()=>{
  70361. let boundingBox = Clip.box.boundingBox.clone().applyMatrix4(Clip.box.matrixWorld);
  70362. if(mapVisi){//切换地图
  70363. if(viewer.fpVisiDatasets.length == 0){//不会显示任何一个floorplan图,就要就近移动到一个可见数据集里
  70364. let clouds = viewer.scene.pointclouds.filter(e=>e.visible);
  70365. if(clouds.length == 0)clouds = viewer.scene.pointclouds;
  70366. let scores = clouds.map((e,i)=>{
  70367. return [ -viewer.scene.view.position.distanceToSquared(e.bound2) , i]
  70368. });
  70369. scores = scores.sort((a,b)=> a[0] - b[0]);
  70370. let neareast = clouds[scores[0][1]];
  70371. viewer.flyToDataset({ pointcloud : neareast, duration:0});
  70372. }
  70373. if(Clip.switchMapCount == 0 || !Potree.Utils.getPos2d(viewer.scene.view.position, viewer.mapViewer.camera, viewer.mapViewer.renderArea, viewer.mapViewer.viewports[0]).inSight
  70374. || !Potree.Utils.isInsideFrustum(boundingBox, viewer.mapViewer.camera)){ //要使box框和游标都在屏幕内。因为游标是3d的当前位置,很可能是准备去框住的位置
  70375. let bound = boundingBox.clone();
  70376. bound.expandByPoint(viewer.scene.view.position);
  70377. let size = bound.getSize(new Vector3);
  70378. let center = bound.getCenter(new Vector3);
  70379. let margin = viewer.mainViewport.resolution.clone().multiplyScalar(0.3);
  70380. viewer.mapViewer.moveTo(center, size, 100, margin);
  70381. }
  70382. Clip.switchMapCount++;
  70383. //关于究竟是focus box还是dataset有点纠结,又或是两个的union。box和数据集可能离得很远,且无法确定当前想选择的数据集,且数据集可能无floorplan, 即使有可能也不展示……
  70384. }else {//切换3d
  70385. if(!Potree.Utils.isInsideFrustum(boundingBox, viewer.scene.getActiveCamera())){//屏幕上没有box的话
  70386. viewer.focusOnObject({boundingBox}, 'boundingBox', 100 );
  70387. }
  70388. }
  70389. },delay);
  70390. }
  70391. };
  70392. this.switchMapCount = 0;
  70393. this.bus.addEventListener('flyToPos',this.events.flyToPos);
  70394. viewer.mapViewer.addEventListener('forceVisible',this.events.mapVisiChange);
  70395. }
  70396. this.editing = true;
  70397. setTimeout(()=>{this.changeCallback(true);},1);
  70398. },
  70399. leave:function(){
  70400. viewer.inputHandler.fixSelection = false;
  70401. viewer.scene.removeVolume(this.box);
  70402. this.mapBox.dispose();
  70403. //viewer.setControls(viewer.fpControls);
  70404. Potree.settings.unableNavigate = false;
  70405. Potree.settings.ifShowMarker = this.previousView.ifShowMarker;
  70406. Potree.Utils.updateVisible(viewer.measuringTool.scene, 'clipModel', true);
  70407. //Potree.Utils.updateVisible(viewer.mapViewer.cursor, 'clipModel', true)
  70408. viewer.setView(this.previousView);
  70409. viewer.setLimitFar(true);
  70410. viewer.setPointStandardMat(false);
  70411. //viewer.setClipState(true)
  70412. viewer.controls.setTarget(null);
  70413. {
  70414. this.bus.removeEventListener('flyToPos',this.events.flyToPos);
  70415. viewer.mapViewer.removeEventListener('forceVisible',this.events.mapVisiChange);
  70416. this.events = null;
  70417. }
  70418. this.editing = false;
  70419. },
  70420. getPointcloud:function(){ //找一个离当前最近的点云,且最好有漫游点
  70421. let pointclouds = viewer.scene.pointclouds.filter(e=>e.panos.length>0);
  70422. if(pointclouds.length == 0)pointclouds = viewer.scene.pointclouds;
  70423. let result = Common$1.sortByScore(pointclouds,[],[e=>{
  70424. let center = e.bound.getCenter(new Vector3);
  70425. let size = e.bound.getSize(new Vector3).length() / 2;
  70426. let posToCenter = viewer.images360.position.distanceTo(center);
  70427. return size / posToCenter
  70428. }]);
  70429. return result[0].item
  70430. },
  70431. getTarget:function(boundCenter){//box位置。要找一个有点云的地方。方案1相机位置, 方案2接近相机的漫游点, 方案3接近中心的漫游点。选择方案2,因最大概率有点云
  70432. var target = new Vector3();
  70433. var cameraPos = viewer.images360.position;
  70434. var pano = Common$1.find(viewer.images360.panos , [], [Images360.sortFunctions.floorDisSquaredToPoint(cameraPos)]);
  70435. if(pano){
  70436. target.copy(pano.position);
  70437. target.setZ(boundCenter.z);
  70438. }else {
  70439. target.copy(boundCenter);
  70440. }
  70441. return target
  70442. },
  70443. /* switchMap:function(state){
  70444. }, */
  70445. download:function( ){
  70446. if(this.getIntersectPointcloud().length == 0){
  70447. return null
  70448. }
  70449. var visiPointclouds = viewer.scene.pointclouds.filter(e=> Potree.Utils.getObjVisiByReason(e, 'datasetSelection'));
  70450. let data = {
  70451. transformation_matrix: visiPointclouds.map((cloud)=>{
  70452. let data = {
  70453. id: cloud.dataset_id,
  70454. matrix : this.getTransformationMatrix(cloud).elements, //剪裁大框
  70455. VisiMatrixes: cloud.material.clipBoxes_in.map(e=>this.getTransformationMatrix(cloud, e.inverse).elements), //若干个可见型小框(虽然现在用不到了,因为普通界面不展示这些剪裁区域)
  70456. UnVisiMatrixes: cloud.material.clipBoxes_out.map(e=>this.getTransformationMatrix(cloud, e.inverse).elements), //若干个不可见型小框
  70457. modelMatrix:(new Matrix4).copy(cloud.transformMatrix).transpose().elements
  70458. };
  70459. return data
  70460. }) ,
  70461. aabb: "b-0.5 -0.5 -0.5 0.5 0.5 0.5" //剪裁空间( 所有点在乘上这个矩阵后, 还能落在 1 * 1 * 1的box内的点就是所裁剪的
  70462. };
  70463. return data
  70464. //https://testlaser.4dkankan.com/indoor/t-ia44BhY/api/pointcloud/crop
  70465. },
  70466. downloadNoCrop(){//不剪裁 下载整个点云
  70467. var visiPointclouds = viewer.scene.pointclouds.filter(e=> Potree.Utils.getObjVisiByReason(e, 'datasetSelection'));
  70468. let data = {
  70469. transformation_matrix: visiPointclouds.map((cloud)=>{
  70470. let data = {
  70471. id: cloud.dataset_id,
  70472. matrix : new Matrix4().elements, //固定值
  70473. modelMatrix:(new Matrix4).copy(cloud.transformMatrix).transpose().elements
  70474. };
  70475. return data
  70476. }) ,
  70477. aabb: "b-12742000 -12742000 -12742000 12742000 12742000 12742000" //固定剪裁空间
  70478. };
  70479. console.log(data);
  70480. return data
  70481. },
  70482. getTransformationMatrix:function(pointcloud, invMatrix) {//剪裁矩阵
  70483. var invMatrix = invMatrix || this.box.matrixWorld.clone().invert();
  70484. return (new Matrix4).multiplyMatrices(invMatrix, pointcloud.transformMatrix).transpose()
  70485. },
  70486. /* getIntersectPointcloud(){
  70487. var boxBound = new THREE.Box3(
  70488. new THREE.Vector3(-0.5,-0.5,-0.5), new THREE.Vector3(0.5,0.5,0.5),
  70489. ).applyMatrix4(this.box.matrixWorld) //large boundingbox
  70490. let boxMatrixInverse = new THREE.Matrix4().copy(this.box.matrixWorld).invert();
  70491. let boxPoints = [
  70492. new THREE.Vector3(boxBound.min.x, boxBound.min.y,0),
  70493. new THREE.Vector3(boxBound.max.x, boxBound.min.y,0),
  70494. new THREE.Vector3(boxBound.max.x, boxBound.max.y,0),
  70495. new THREE.Vector3(boxBound.min.x, boxBound.max.y,0)
  70496. ]
  70497. var intersect = (pointcloud)=>{
  70498. if(!pointcloud.bound.intersectsBox(boxBound))return false
  70499. //判断box和点云的tight bound是否相交(因为box可以任意旋转,且实在找不到三维中的立方体相交的函数,所以直接用boxBound)
  70500. var points = pointcloud.getUnrotBoundPoint('all')
  70501. let rings = math.getPolygonsMixedRings([points.slice(0,4), boxPoints] , true)
  70502. //console.log(pointcloud.dataset_id, pointcloud.name, rings.length)
  70503. if(rings.length > 1 )return false
  70504. {//再用frustum和数据集的sphere相交试试,能排除一些错误
  70505. let a = Potree.Utils.isIntersectBox(points, this.box.matrixWorld)
  70506. if(!a){
  70507. console.log('没能经过isInsideBox测试')
  70508. }
  70509. return a
  70510. }
  70511. return true
  70512. }
  70513. return viewer.scene.pointclouds.filter(e=>intersect(e))
  70514. } */
  70515. getIntersectPointcloud(){
  70516. var intersect = (pointcloud)=>{
  70517. if(pointcloud.intersectBox(this.box.matrixWorld))return true
  70518. };
  70519. return viewer.scene.pointclouds.filter(e=>intersect(e))
  70520. }
  70521. };
  70522. /*
  70523. 裁剪点云时,2D界面显示全部平面图,按楼层切换显示。
  70524. */
  70525. var TransformControls = function ( camera, domElement, options ) {
  70526. if ( domElement === undefined ) {
  70527. console.warn( 'THREE.TransformControls: The second parameter "domElement" is now mandatory.' );
  70528. domElement = document;
  70529. }
  70530. Object3D.call( this );
  70531. this.visible = false;
  70532. this.domElement = domElement;
  70533. var _gizmo = new TransformControlsGizmo(options);
  70534. this.add( _gizmo );
  70535. this._gizmo = _gizmo;
  70536. var _plane = new TransformControlsPlane(options);
  70537. this.add( _plane );
  70538. /* this.linesAssistance = new TransformControlsLines(options); //水平 垂直 辅助
  70539. this.add( this.linesAssistance ); */
  70540. var scope = this;
  70541. //this.player = options.player;//xzw add
  70542. this.options = options;//xzw add
  70543. // Define properties with getters/setter
  70544. // Setting the defined property will automatically trigger change event
  70545. // Defined properties are passed down to gizmo and plane
  70546. defineProperty( "camera", camera );
  70547. defineProperty( "object", undefined );
  70548. defineProperty( "enabled", true );
  70549. defineProperty( "axis", null );
  70550. defineProperty( "mode", "translate" );
  70551. defineProperty( "translationSnap", null );
  70552. defineProperty( "rotationSnap", null );
  70553. defineProperty( "scaleSnap", null );
  70554. defineProperty( "space", "world" );
  70555. defineProperty( "size", 1 );
  70556. defineProperty( "dragging", false );
  70557. defineProperty( "showX", true );
  70558. defineProperty( "showY", true );
  70559. defineProperty( "showZ", true );
  70560. var changeEvent = { type: "change" };
  70561. var mouseDownEvent = { type: "mouseDown" };
  70562. var mouseUpEvent = { type: "mouseUp", mode: scope.mode };
  70563. var objectChangeEvent = { type: "objectChange" };
  70564. // Reusable utility variables
  70565. var ray = new Raycaster();
  70566. var _tempVector = new Vector3();
  70567. var _tempVector2 = new Vector3();
  70568. var _tempQuaternion = new Quaternion();
  70569. var _unit = {
  70570. X: new Vector3( 1, 0, 0 ),
  70571. Y: new Vector3( 0, 1, 0 ),
  70572. Z: new Vector3( 0, 0, 1 )
  70573. };
  70574. var pointStart = new Vector3();
  70575. var pointEnd = new Vector3();
  70576. var offset = new Vector3();
  70577. var rotationAxis = new Vector3();
  70578. var startNorm = new Vector3();
  70579. var endNorm = new Vector3();
  70580. var rotationAngle = 0;
  70581. var cameraPosition = new Vector3();
  70582. var cameraQuaternion = new Quaternion();
  70583. var cameraScale = new Vector3();
  70584. var parentPosition = new Vector3();
  70585. var parentQuaternion = new Quaternion();
  70586. var parentQuaternionInv = new Quaternion();
  70587. var parentScale = new Vector3();
  70588. var worldPositionStart = new Vector3();
  70589. var worldQuaternionStart = new Quaternion();
  70590. var worldScaleStart = new Vector3();
  70591. var worldPosition = new Vector3();
  70592. var worldQuaternion = new Quaternion();
  70593. var worldQuaternionInv = new Quaternion();
  70594. var worldScale = new Vector3();
  70595. var eye = new Vector3();
  70596. var positionStart = new Vector3();
  70597. var quaternionStart = new Quaternion();
  70598. var scaleStart = new Vector3();
  70599. // TODO: remove properties unused in plane and gizmo
  70600. defineProperty( "worldPosition", worldPosition );
  70601. defineProperty( "worldPositionStart", worldPositionStart );
  70602. defineProperty( "worldQuaternion", worldQuaternion );
  70603. defineProperty( "worldQuaternionStart", worldQuaternionStart );
  70604. defineProperty( "cameraPosition", cameraPosition );
  70605. defineProperty( "cameraQuaternion", cameraQuaternion );
  70606. defineProperty( "pointStart", pointStart );
  70607. defineProperty( "pointEnd", pointEnd );
  70608. defineProperty( "rotationAxis", rotationAxis );
  70609. defineProperty( "rotationAngle", rotationAngle );
  70610. defineProperty( "eye", eye );
  70611. {
  70612. domElement.addEventListener( "mousedown", onPointerDown, false );
  70613. domElement.addEventListener( "touchstart", onPointerDown, false );
  70614. domElement.addEventListener( "mousemove", onPointerHover, false );
  70615. domElement.addEventListener( "touchmove", onPointerHover, false );
  70616. domElement.addEventListener( "touchmove", onPointerMove, false );
  70617. document.addEventListener( "mouseup", onPointerUp, false );
  70618. domElement.addEventListener( "touchend", onPointerUp, false );
  70619. domElement.addEventListener( "touchcancel", onPointerUp, false );
  70620. domElement.addEventListener( "touchleave", onPointerUp, false );
  70621. let drag = ()=>{
  70622. if(this.dragging){
  70623. this.pointerMove();
  70624. return {stopContinue:true}
  70625. }
  70626. };
  70627. this.addEventListener('dragging',drag,{importance:10});
  70628. viewer.addEventListener('global_drag',drag,{importance:10});
  70629. }
  70630. this.setRotateMethod = function(number){//add 注意为2时 旋转期间不能改变位置 space可能不能为local ._gizmo.hideAxis = { rotate:[这里必须包含'e' ] }
  70631. this.rotateMethod = number;
  70632. };
  70633. this.dispose = function () {
  70634. domElement.removeEventListener( "mousedown", onPointerDown );
  70635. domElement.removeEventListener( "touchstart", onPointerDown );
  70636. domElement.removeEventListener( "mousemove", onPointerHover );
  70637. domElement.removeEventListener( "mousemove", onPointerMove );
  70638. domElement.removeEventListener( "touchmove", onPointerHover );
  70639. domElement.removeEventListener( "touchmove", onPointerMove );
  70640. document.removeEventListener( "mouseup", onPointerUp );
  70641. domElement.removeEventListener( "touchend", onPointerUp );
  70642. domElement.removeEventListener( "touchcancel", onPointerUp );
  70643. domElement.removeEventListener( "touchleave", onPointerUp );
  70644. this.traverse( function ( child ) {
  70645. if ( child.geometry ) child.geometry.dispose();
  70646. if ( child.material ) child.material.dispose();
  70647. } );
  70648. };
  70649. // Set current object
  70650. this.attach = function ( object ) {
  70651. this.object = object;
  70652. this.visible = true;
  70653. //Config.keyCon = false;//add
  70654. //this.linesAssistance.setVisible(true)
  70655. viewer.dispatchEvent('content_changed');
  70656. return this;
  70657. };
  70658. // Detatch from object
  70659. this.detach = function () {
  70660. this.object = undefined;
  70661. this.visible = false;
  70662. this.axis = null;
  70663. //Config.keyCon = true;//add
  70664. //this.linesAssistance.setVisible(false)
  70665. viewer.dispatchEvent('content_changed');
  70666. return this;
  70667. };
  70668. //this.space = 'local'
  70669. /* this.hideAxis = function ( mode, axis=[] ) {//xzw add 设置不可见的axis
  70670. var handles = [];
  70671. handles = handles.concat( this._gizmo.picker[ mode ].children );
  70672. handles = handles.concat( this._gizmo.gizmo[ mode ].children );
  70673. handles = handles.concat( this._gizmo.helper[ mode ].children );
  70674. handles.forEach(e=>e.visible = false)
  70675. axis.forEach(name=>{
  70676. handles.filter(handle =>!handle.name.includes(name))
  70677. })
  70678. handles.forEach(e=>e.visible = true)
  70679. }; */
  70680. // Defined getter, setter and store for a property
  70681. function defineProperty( propName, defaultValue ) {
  70682. var propValue = defaultValue;
  70683. Object.defineProperty( scope, propName, {
  70684. get: function () {
  70685. return propValue !== undefined ? propValue : defaultValue;
  70686. },
  70687. set: function ( value ) {
  70688. if ( propValue !== value ) {
  70689. propValue = value;
  70690. _plane[ propName ] = value;
  70691. _gizmo[ propName ] = value;
  70692. scope.dispatchEvent( { type: propName + "-changed", value: value } );
  70693. scope.dispatchEvent( changeEvent );
  70694. }
  70695. }
  70696. } );
  70697. scope[ propName ] = defaultValue;
  70698. _plane[ propName ] = defaultValue;
  70699. _gizmo[ propName ] = defaultValue;
  70700. }
  70701. // updateMatrixWorld updates key transformation variables
  70702. this.updateMatrixWorld = function () {
  70703. if(!this.visible)return//add
  70704. if ( this.object !== undefined ) {
  70705. this.object.updateMatrixWorld();
  70706. this.object.parent.matrixWorld.decompose( parentPosition, parentQuaternion, parentScale );
  70707. this.object.matrixWorld.decompose( worldPosition, worldQuaternion, worldScale );
  70708. //add
  70709. if(this.object.boundingBox){
  70710. let boundingBox = this.object.boundingBox.clone().applyMatrix4(this.object.matrixWorld);
  70711. boundingBox.getCenter(worldPosition); //bound中心
  70712. if(this.pivotOnBottom){
  70713. worldPosition.setZ(boundingBox.min.z); //中心点居于模型bound底部,因固定离地高度,旋转时旋转中心在地面上就不会变位置
  70714. }
  70715. }
  70716. parentQuaternionInv.copy( parentQuaternion ).invert();
  70717. worldQuaternionInv.copy( worldQuaternion ).invert();
  70718. }
  70719. this.camera.updateMatrixWorld();
  70720. this.camera.matrixWorld.decompose( cameraPosition, cameraQuaternion, cameraScale );
  70721. if(this.camera.type == "OrthographicCamera"){//xzw add
  70722. eye.copy( this.view.direction);
  70723. }else {
  70724. eye.copy( cameraPosition ).sub( worldPosition ).normalize();
  70725. }
  70726. Object3D.prototype.updateMatrixWorld.call( this );
  70727. };
  70728. this.pointerHover = function () {
  70729. let pointer = viewer.inputHandler.pointer;
  70730. if ( this.object === undefined)return
  70731. //if(this.dragging === true /* || ( pointer.button !== undefined && pointer.button !== 0 ) */) return;
  70732. if(!this.dragging){
  70733. let oldAxis = this.axis;
  70734. //ray.setFromCamera( pointer, this.camera ); //这句会在floorplan模式get不到intersect
  70735. let {origin, direction} = viewer.inputHandler.getMouseDirection();
  70736. ray.set(origin, direction);
  70737. Potree.Utils.setCameraLayers(ray, //设置能识别到的layers
  70738. ['sceneObjects','mapObjects','measure', 'transformationTool', 'model'],
  70739. viewer.inputHandler.hoverViewport && viewer.inputHandler.hoverViewport.extraEnableLayers
  70740. );
  70741. var intersect = ray.intersectObjects( _gizmo.picker[ this.mode ].children.filter(e=>e.visible), true )[ 0 ] || false;
  70742. if ( intersect ) {
  70743. this.axis = intersect.object.name;
  70744. } else {
  70745. this.axis = null;
  70746. }
  70747. if(oldAxis != this.axis){
  70748. viewer.dispatchEvent('content_changed');
  70749. }
  70750. }else {
  70751. //this.pointerMove()
  70752. }
  70753. };
  70754. this.pointerDown = function ( /* pointer */ ) {
  70755. let pointer = viewer.inputHandler.pointer;
  70756. if ( this.object === undefined || this.dragging === true /* || ( pointer.button !== undefined && pointer.button !== 0 ) */ ) return;
  70757. if ( /* ( pointer.button === 0 || pointer.button === undefined ) && */ this.axis !== null ) {
  70758. //ray.setFromCamera( pointer, this.camera ); //这句会在floorplan模式get不到intersect
  70759. let {origin, direction} = viewer.inputHandler.getMouseDirection();
  70760. ray.set(origin, direction);
  70761. Potree.Utils.setCameraLayers(ray, //设置能识别到的layers
  70762. ['sceneObjects','mapObjects','measure', 'transformationTool', 'model'],
  70763. viewer.inputHandler.hoverViewport && viewer.inputHandler.hoverViewport.extraEnableLayers
  70764. );
  70765. var planeIntersect = ray.intersectObjects( [ _plane ], true )[ 0 ] || false;
  70766. if ( planeIntersect ) {
  70767. var space = this.space;
  70768. if ( this.mode === 'scale' ) {
  70769. space = 'local';
  70770. } else if ( this.axis === 'E' || this.axis === 'XYZE' || this.axis === 'XYZ' ) {
  70771. space = 'world';
  70772. }
  70773. if ( space === 'local' && this.mode === 'rotate' ) {
  70774. var snap = this.rotationSnap;
  70775. if ( this.axis === 'X' && snap ) this.object.rotation.x = Math.round( this.object.rotation.x / snap ) * snap;
  70776. if ( this.axis === 'Y' && snap ) this.object.rotation.y = Math.round( this.object.rotation.y / snap ) * snap;
  70777. if ( this.axis === 'Z' && snap ) this.object.rotation.z = Math.round( this.object.rotation.z / snap ) * snap;
  70778. }
  70779. this.object.updateMatrixWorld();
  70780. this.object.parent.updateMatrixWorld();
  70781. positionStart.copy( this.object.position );
  70782. quaternionStart.copy( this.object.quaternion );
  70783. scaleStart.copy( this.object.scale );
  70784. this.object.matrixWorld.decompose( worldPositionStart, worldQuaternionStart, worldScaleStart );
  70785. //add: 使坐标轴在boundingBox中心
  70786. this.object.boundingBox && this.object.boundingBox.getCenter(worldPositionStart).applyMatrix4(this.object.matrixWorld);
  70787. pointStart.copy( planeIntersect.point ).sub( worldPositionStart );
  70788. /* if(this.player.cameraControls.activeControl){
  70789. //this.player.cameraControls.activeControl.locked = true; //add
  70790. this.player.cameraControls.activeControl.enabled = false; //add
  70791. } */
  70792. }
  70793. this.dragging = true;
  70794. mouseDownEvent.mode = this.mode;
  70795. this.dispatchEvent( mouseDownEvent );
  70796. }
  70797. };
  70798. this.pointerMove = function ( /* pointer */ ) {
  70799. let pointer = viewer.inputHandler.pointer;
  70800. var axis = this.axis;
  70801. var mode = this.mode;
  70802. var object = this.object;
  70803. var space = this.space;
  70804. if ( mode === 'scale' ) {
  70805. space = 'local';
  70806. } else if ( axis === 'E' || axis === 'XYZE' || axis === 'XYZ' ) {
  70807. space = 'world';
  70808. }
  70809. if ( object === undefined || axis === null || this.dragging === false || ( pointer.button !== undefined && pointer.button !== 0 ) ) return;
  70810. //ray.setFromCamera( pointer, this.camera ); //这句会在floorplan模式get不到intersect
  70811. let {origin, direction} = viewer.inputHandler.getMouseDirection();
  70812. ray.set(origin, direction);
  70813. Potree.Utils.setCameraLayers(ray, //设置能识别到的layers
  70814. ['sceneObjects','mapObjects','measure', 'transformationTool', 'model'],
  70815. viewer.inputHandler.hoverViewport && viewer.inputHandler.hoverViewport.extraEnableLayers
  70816. );
  70817. var planeIntersect = ray.intersectObjects( [ _plane ], true )[ 0 ] || false;
  70818. if ( planeIntersect === false ) return;
  70819. pointEnd.copy( planeIntersect.point ).sub( worldPositionStart );
  70820. if ( mode === 'translate' ) {
  70821. // Apply translate
  70822. offset.copy( pointEnd ).sub( pointStart );
  70823. if ( space === 'local' && axis !== 'XYZ' ) {
  70824. offset.applyQuaternion( worldQuaternionInv );
  70825. }
  70826. if ( axis.indexOf( 'X' ) === - 1 ) offset.x = 0;
  70827. if ( axis.indexOf( 'Y' ) === - 1 ) offset.y = 0;
  70828. if ( axis.indexOf( 'Z' ) === - 1 ) offset.z = 0;
  70829. if ( space === 'local' && axis !== 'XYZ' ) {
  70830. //xzw 加,否则会反向---------------
  70831. object.scale.x < 0 && (offset.x *= -1);
  70832. object.scale.y < 0 && (offset.y *= -1);
  70833. object.scale.z < 0 && (offset.z *= -1);
  70834. //---------------------------------
  70835. offset.applyQuaternion( quaternionStart ).divide( parentScale );
  70836. } else {
  70837. offset.applyQuaternion( parentQuaternionInv ).divide( parentScale );
  70838. }
  70839. object.position.copy( offset ).add( positionStart );
  70840. // Apply translation snap
  70841. if ( this.translationSnap ) {
  70842. if ( space === 'local' ) {
  70843. object.position.applyQuaternion( _tempQuaternion.copy( quaternionStart ).invert() );
  70844. if ( axis.search( 'X' ) !== - 1 ) {
  70845. object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;
  70846. }
  70847. if ( axis.search( 'Y' ) !== - 1 ) {
  70848. object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;
  70849. }
  70850. if ( axis.search( 'Z' ) !== - 1 ) {
  70851. object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;
  70852. }
  70853. object.position.applyQuaternion( quaternionStart );
  70854. }
  70855. if ( space === 'world' ) {
  70856. if ( object.parent ) {
  70857. object.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );
  70858. }
  70859. if ( axis.search( 'X' ) !== - 1 ) {
  70860. object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;
  70861. }
  70862. if ( axis.search( 'Y' ) !== - 1 ) {
  70863. object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;
  70864. }
  70865. if ( axis.search( 'Z' ) !== - 1 ) {
  70866. object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;
  70867. }
  70868. if ( object.parent ) {
  70869. object.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );
  70870. }
  70871. }
  70872. }
  70873. //add:
  70874. object.dispatchEvent({
  70875. type: "position_changed"
  70876. });
  70877. } else if ( mode === 'scale' ) {
  70878. if ( axis.search( 'XYZ' ) !== - 1 ) {
  70879. var d = pointEnd.length() / pointStart.length();
  70880. if ( pointEnd.dot( pointStart ) < 0 ) d *= - 1;
  70881. if(options.NoScaleZ){//xzw add
  70882. _tempVector2.set( d, d, 1 );
  70883. }else {
  70884. _tempVector2.set( d, d, d );
  70885. }
  70886. }else if ( axis.search( 'XY' ) !== - 1 ) { //add 等比例for plane
  70887. var d = pointEnd.length() / pointStart.length();
  70888. if ( pointEnd.dot( pointStart ) < 0 ) d *= - 1;
  70889. _tempVector2.set( d, d, 1 );
  70890. }else {
  70891. _tempVector.copy( pointStart );
  70892. _tempVector2.copy( pointEnd );
  70893. _tempVector.applyQuaternion( worldQuaternionInv );
  70894. _tempVector2.applyQuaternion( worldQuaternionInv );
  70895. _tempVector2.divide( _tempVector );
  70896. if ( axis.search( 'X' ) === - 1 ) {
  70897. _tempVector2.x = 1;
  70898. }
  70899. if ( axis.search( 'Y' ) === - 1 ) {
  70900. _tempVector2.y = 1;
  70901. }
  70902. if ( axis.search( 'Z' ) === - 1 ) {
  70903. _tempVector2.z = 1;
  70904. }
  70905. }
  70906. // Apply scale
  70907. object.scale.copy( scaleStart ).multiply( _tempVector2 );
  70908. if ( this.scaleSnap ) {
  70909. if ( axis.search( 'X' ) !== - 1 ) {
  70910. object.scale.x = Math.round( object.scale.x / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
  70911. }
  70912. if ( axis.search( 'Y' ) !== - 1 ) {
  70913. object.scale.y = Math.round( object.scale.y / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
  70914. }
  70915. if ( axis.search( 'Z' ) !== - 1 ) {
  70916. object.scale.z = Math.round( object.scale.z / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
  70917. }
  70918. }
  70919. //add:
  70920. object.dispatchEvent({
  70921. type: "scale_changed"
  70922. });
  70923. } else if ( mode === 'rotate' ) {
  70924. if(this.rotateMethod == 2){//新版参照transfromTool的写法,更跟手,但是有bug,在同时移动位置时或e轴上有问题
  70925. if ( axis === 'E' ) {//绕着视线转
  70926. rotationAxis.copy( eye );//旋转轴
  70927. rotationAngle = pointEnd.angleTo( pointStart );
  70928. startNorm.copy( pointStart ).normalize();
  70929. endNorm.copy( pointEnd ).normalize();
  70930. rotationAngle *= ( endNorm.cross( startNorm ).dot( eye ) < 0 ? 1 : - 1 ); //角度
  70931. }else {
  70932. if ( axis === 'XYZE' ) {//像滚球一样拨动,鼠标滑动方向为拨动方向,在plane面上滚动
  70933. offset.copy( pointEnd ).sub( pointStart );
  70934. rotationAxis.copy( offset ).cross( eye ).normalize();
  70935. }else {
  70936. rotationAxis.copy( _unit[ axis ] );
  70937. }
  70938. let center = new Vector3;//坐标轴位置
  70939. if(this.object.boundingBox){
  70940. center.copy(worldPosition);
  70941. }else {
  70942. center.copy(worldPositionStart);//boundingBox中心可能变化 这里可能要改成直接获取model的position
  70943. }
  70944. let rotationAxis_ = space === 'local' ? rotationAxis.clone().applyQuaternion(worldQuaternion) : rotationAxis;
  70945. let plane = new Plane().setFromNormalAndCoplanarPoint(rotationAxis_, center);//旋转过程中rotationAxis不会变化,但center可能会
  70946. let {origin, direction} = viewer.inputHandler.getMouseDirection();
  70947. ray.set(origin, direction);
  70948. let I = ray.ray.intersectPlane(plane, new Vector3());
  70949. if (I) {
  70950. let v2 = I.clone().sub(center);//.normalize();
  70951. if(!this.rotateStart){
  70952. this.rotateStart = {
  70953. v1: v2
  70954. };
  70955. return
  70956. }
  70957. let v1 = this.rotateStart.v1;
  70958. rotationAngle = math.getAngle( v1, v2, rotationAxis_);
  70959. if (Number.isNaN(rotationAngle)) {
  70960. return;
  70961. }
  70962. this.rotateStart.v1 = v2;
  70963. }
  70964. }
  70965. }else {
  70966. //pointStart 是起始intersect - object中心的向量
  70967. //pointEnd 是当前intersect - object中心的向量
  70968. offset.copy( pointEnd ).sub( pointStart );
  70969. var ROTATION_SPEED = 2 / worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) );
  70970. if ( axis === 'E' ) {//绕着视线转
  70971. rotationAxis.copy( eye );//旋转轴
  70972. rotationAngle = pointEnd.angleTo( pointStart );
  70973. startNorm.copy( pointStart ).normalize();
  70974. endNorm.copy( pointEnd ).normalize();
  70975. rotationAngle *= ( endNorm.cross( startNorm ).dot( eye ) < 0 ? 1 : - 1 ); //角度
  70976. } else if ( axis === 'XYZE' ) {//像滚球一样拨动,鼠标滑动方向为拨动方向,在plane面上滚动
  70977. rotationAxis.copy( offset ).cross( eye ).normalize();
  70978. rotationAngle = offset.dot( _tempVector.copy( rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED;
  70979. } else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) {
  70980. rotationAxis.copy( _unit[ axis ] );
  70981. _tempVector.copy( _unit[ axis ] );
  70982. if ( space === 'local' ) {
  70983. _tempVector.applyQuaternion( worldQuaternion );
  70984. }
  70985. rotationAngle = offset.dot( _tempVector.cross( eye ).normalize() ) * ROTATION_SPEED;
  70986. }
  70987. // Apply rotation snap
  70988. if ( this.rotationSnap ) rotationAngle = Math.round( rotationAngle / this.rotationSnap ) * this.rotationSnap;
  70989. this.rotationAngle = rotationAngle;
  70990. }
  70991. // Apply rotate
  70992. if ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) {
  70993. object.scale[axis.toLowerCase()] < 0 && (rotationAngle *= -1); //xzw 加,否则会反向
  70994. object.quaternion.copy( quaternionStart );
  70995. object.quaternion.multiply( _tempQuaternion.setFromAxisAngle( rotationAxis, rotationAngle ) ).normalize();
  70996. } else {
  70997. rotationAxis.applyQuaternion( parentQuaternionInv );
  70998. object.quaternion.copy( _tempQuaternion.setFromAxisAngle( rotationAxis, rotationAngle ) );
  70999. object.quaternion.multiply( quaternionStart ).normalize();
  71000. }
  71001. if ( this.rotateMethod == 2 && axis != 'E' ) {
  71002. quaternionStart.copy(object.quaternion);
  71003. }
  71004. //add:
  71005. object.dispatchEvent({
  71006. type: "rotation_changed"
  71007. });
  71008. }
  71009. this.dispatchEvent( changeEvent );
  71010. this.dispatchEvent( objectChangeEvent );
  71011. viewer.dispatchEvent('content_changed');
  71012. };
  71013. this.pointerUp = function ( pointer ) {
  71014. //if ( pointer.button !== undefined && pointer.button !== 0 ) return;
  71015. if ( this.dragging && ( this.axis !== null ) ) {
  71016. mouseUpEvent.mode = this.mode;
  71017. this.dispatchEvent( mouseUpEvent );
  71018. /* if(this.player.cameraControls.activeControl){
  71019. //this.player.cameraControls.activeControl.locked = false; //add
  71020. this.player.cameraControls.activeControl.pointerDragOn = false //add
  71021. this.player.cameraControls.activeControl.enabled = true
  71022. } */
  71023. this.rotateStart = null;//add
  71024. this.dispatchEvent({type:'transform_end'});
  71025. }
  71026. this.dragging = false;
  71027. //if ( pointer.button === undefined ) this.axis = null;
  71028. /* if(this.player.cameraControls.activeControl){
  71029. //this.player.cameraControls.activeControl.locked = false; //add
  71030. this.player.cameraControls.activeControl.pointerDragOn = false //add
  71031. this.player.cameraControls.activeControl.enabled = true
  71032. } */
  71033. };
  71034. // normalize mouse / touch pointer and remap {x,y} to view space.
  71035. function getPointer( event ) {
  71036. if(!event){
  71037. console.log('hhahhhahah');
  71038. return;
  71039. }
  71040. if ( document.pointerLockElement ) {
  71041. return {
  71042. x: 0,
  71043. y: 0,
  71044. button: event.button
  71045. };
  71046. } else {
  71047. var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
  71048. var rect = domElement.getBoundingClientRect();
  71049. return {
  71050. x: ( pointer.clientX - rect.left ) / rect.width * 2 - 1,
  71051. y: - ( pointer.clientY - rect.top ) / rect.height * 2 + 1,
  71052. button: event.button
  71053. };
  71054. }
  71055. }
  71056. // mouse / touch event handlers
  71057. function onPointerHover( event ) {
  71058. if ( ! scope.enabled ) return;
  71059. //scope.pointerHover( getPointer( event ) );
  71060. scope.pointerHover( );
  71061. }
  71062. function onPointerDown( event ) {
  71063. if ( ! scope.enabled ) return;
  71064. //document.addEventListener( "mousemove", onPointerMove, false );
  71065. /* scope.pointerHover( getPointer( event ) );
  71066. scope.pointerDown( getPointer( event ) ); */
  71067. scope.pointerHover( );
  71068. scope.pointerDown();
  71069. }
  71070. this.onPointerDown = onPointerDown;
  71071. function onPointerMove( event ) {
  71072. if ( ! scope.enabled || !this.dragging) return; //xzw change
  71073. //scope.pointerMove( getPointer( event ) );
  71074. scope.pointerMove( );
  71075. }
  71076. this.onPointerMove = onPointerMove;
  71077. function onPointerUp( event ) {
  71078. if ( ! scope.enabled ) return;
  71079. //document.removeEventListener( "mousemove", onPointerMove, false );
  71080. //scope.pointerUp( getPointer( event ) );
  71081. scope.pointerUp( );
  71082. }
  71083. this.onPointerUp = onPointerUp;
  71084. // TODO: deprecate
  71085. this.getMode = function () {
  71086. return scope.mode;
  71087. };
  71088. this.setMode = function ( mode ) {
  71089. scope.mode = mode;
  71090. };
  71091. this.setTranslationSnap = function ( translationSnap ) {
  71092. scope.translationSnap = translationSnap;
  71093. };
  71094. this.setRotationSnap = function ( rotationSnap ) {
  71095. scope.rotationSnap = rotationSnap;
  71096. };
  71097. this.setScaleSnap = function ( scaleSnap ) {
  71098. scope.scaleSnap = scaleSnap;
  71099. };
  71100. this.setSize = function ( size ) {
  71101. scope.size = size;
  71102. };
  71103. this.setSpace = function ( space ) {
  71104. scope.space = space;
  71105. };
  71106. this.update = function () {
  71107. console.warn( 'THREE.TransformControls: update function has no more functionality and therefore has been deprecated.' );
  71108. };
  71109. };
  71110. var TransformControlsGizmo = function (options) {
  71111. 'use strict';
  71112. Object3D.call( this );
  71113. this.type = 'TransformControlsGizmo';
  71114. // shared materials
  71115. this.hideAxis = {};
  71116. var gizmoMaterial = new MeshBasicMaterial( {
  71117. depthTest: false,
  71118. depthWrite: false,
  71119. transparent: true,
  71120. side: DoubleSide,
  71121. fog: false
  71122. } );
  71123. var gizmoLineMaterial = new LineBasicMaterial( {
  71124. depthTest: false,
  71125. depthWrite: false,
  71126. transparent: true,
  71127. fog: false
  71128. } );
  71129. // Make unique material for each axis/color
  71130. var matInvisible = gizmoMaterial.clone();
  71131. matInvisible.opacity = 0.15;
  71132. var matHelper = gizmoMaterial.clone();
  71133. matHelper.opacity = 0.1;
  71134. var matRed = gizmoMaterial.clone();
  71135. matRed.color.set( 0xff0000 );
  71136. var matGreen = gizmoMaterial.clone();
  71137. matGreen.color.set( 0x00ff00 );
  71138. var matBlue = gizmoMaterial.clone();
  71139. matBlue.color.set( 0x0000ff );
  71140. var matWhiteTransparent = gizmoMaterial.clone();
  71141. matWhiteTransparent.opacity = 0.35;
  71142. matWhiteTransparent.color.set( 0x00d0fd );//xzw add
  71143. var matYellowTransparent = matWhiteTransparent.clone();
  71144. matYellowTransparent.color.set( 0xffff00 );
  71145. var matCyanTransparent = matWhiteTransparent.clone();
  71146. matCyanTransparent.color.set( 0x00ffff );
  71147. var matMagentaTransparent = matWhiteTransparent.clone();
  71148. matMagentaTransparent.color.set( 0xff00ff );
  71149. var matYellow = gizmoMaterial.clone();
  71150. matYellow.color.set( 0xffff00 );
  71151. var matLineRed = gizmoLineMaterial.clone();
  71152. matLineRed.color.set( 0xff0000 );
  71153. var matLineGreen = gizmoLineMaterial.clone();
  71154. matLineGreen.color.set( 0x00ff00 );
  71155. var matLineBlue = gizmoLineMaterial.clone();
  71156. matLineBlue.color.set( 0x0000ff );
  71157. var matLineCyan = gizmoLineMaterial.clone();
  71158. matLineCyan.color.set( 0x00ffff );
  71159. var matLineMagenta = gizmoLineMaterial.clone();
  71160. matLineMagenta.color.set( 0xff00ff );
  71161. var matLineYellow = gizmoLineMaterial.clone();
  71162. matLineYellow.color.set( 0xffff00 );
  71163. var matLineGray = gizmoLineMaterial.clone();
  71164. matLineGray.color.set( 0x787878 );
  71165. var matLineYellowTransparent = matLineYellow.clone();
  71166. matLineYellowTransparent.opacity = 0.25;
  71167. // reusable geometry
  71168. var arrowGeometry = new CylinderBufferGeometry( 0, 0.05, 0.2, 12, 1, false );
  71169. var scaleHandleGeometry = new BoxBufferGeometry( 0.125, 0.125, 0.125 );
  71170. var lineGeometry = new BufferGeometry( );
  71171. //lineGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
  71172. lineGeometry.setAttribute("position", new BufferAttribute(new Float32Array([ 0, 0, 0, 1, 0, 0]), 3 ));
  71173. var CircleGeometry = function ( radius, arc ) {
  71174. var geometry = new BufferGeometry( );
  71175. var vertices = [];
  71176. for ( var i = 0; i <= 64 * arc; ++ i ) {
  71177. vertices.push( 0, Math.cos( i / 32 * Math.PI ) * radius, Math.sin( i / 32 * Math.PI ) * radius );
  71178. }
  71179. //geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
  71180. geometry.setAttribute("position", new BufferAttribute(new Float32Array(vertices), 3 ));
  71181. return geometry;
  71182. };
  71183. // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position
  71184. var TranslateHelperGeometry = function () {
  71185. var geometry = new BufferGeometry();
  71186. //geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) );
  71187. geometry.setAttribute("position", new BufferAttribute(new Float32Array([ 0, 0, 0, 1, 1, 1 ]), 3 ));
  71188. return geometry;
  71189. };
  71190. // Gizmo definitions - custom hierarchy definitions for setupGizmo() function
  71191. var gizmoTranslate = {
  71192. X: [
  71193. [ new Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, - Math.PI / 2 ], null, 'fwd' ],
  71194. //[ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, Math.PI / 2 ], null, 'bwd' ],
  71195. [ new Line( lineGeometry, matLineRed ) ]
  71196. ],
  71197. Y: [
  71198. [ new Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], null, null, 'fwd' ],
  71199. //[ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], [ Math.PI, 0, 0 ], null, 'bwd' ],
  71200. [ new Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ]]
  71201. ],
  71202. Z: [
  71203. [ new Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ Math.PI / 2, 0, 0 ], null, 'fwd' ],
  71204. //[ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ - Math.PI / 2, 0, 0 ], null, 'bwd' ],
  71205. [ new Line( lineGeometry, matLineBlue ), null, [ 0, - Math.PI / 2, 0 ]]
  71206. ],
  71207. /* XYZ: [
  71208. [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.1, 0 ), matWhiteTransparent.clone() ), [ 0, 0, 0 ], [ 0, 0, 0 ]]
  71209. ], */
  71210. XY: [
  71211. [ new Mesh( new PlaneBufferGeometry( 0.295, 0.295 ), matYellowTransparent.clone() ), [ 0.15, 0.15, 0 ]],
  71212. [ new Line( lineGeometry, matLineYellow ), [ 0.18, 0.3, 0 ], null, [ 0.125, 1, 1 ]],
  71213. [ new Line( lineGeometry, matLineYellow ), [ 0.3, 0.18, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]]
  71214. ],
  71215. YZ: [
  71216. [ new Mesh( new PlaneBufferGeometry( 0.295, 0.295 ), matCyanTransparent.clone() ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]],
  71217. [ new Line( lineGeometry, matLineCyan ), [ 0, 0.18, 0.3 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]],
  71218. [ new Line( lineGeometry, matLineCyan ), [ 0, 0.3, 0.18 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]
  71219. ],
  71220. XZ: [
  71221. [ new Mesh( new PlaneBufferGeometry( 0.295, 0.295 ), matMagentaTransparent.clone() ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]],
  71222. [ new Line( lineGeometry, matLineMagenta ), [ 0.18, 0, 0.3 ], null, [ 0.125, 1, 1 ]],
  71223. [ new Line( lineGeometry, matLineMagenta ), [ 0.3, 0, 0.18 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]
  71224. ]
  71225. };
  71226. var pickerTranslate = {
  71227. X: [
  71228. [ new Mesh( new CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]
  71229. ],
  71230. Y: [
  71231. [ new Mesh( new CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0.6, 0 ]]
  71232. ],
  71233. Z: [
  71234. [ new Mesh( new CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ]]
  71235. ],
  71236. /* XYZ: [
  71237. [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.2, 0 ), matInvisible ) ]
  71238. ], */
  71239. XY: [
  71240. [ new Mesh( new PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0.2, 0 ]]
  71241. ],
  71242. YZ: [
  71243. [ new Mesh( new PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0, 0.2, 0.2 ], [ 0, Math.PI / 2, 0 ]]
  71244. ],
  71245. XZ: [
  71246. [ new Mesh( new PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0, 0.2 ], [ - Math.PI / 2, 0, 0 ]]
  71247. ]
  71248. };
  71249. var helperTranslate = {
  71250. START: [
  71251. [ new Mesh( new OctahedronBufferGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]
  71252. ],
  71253. END: [
  71254. [ new Mesh( new OctahedronBufferGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]
  71255. ],
  71256. DELTA: [
  71257. [ new Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ]
  71258. ],
  71259. X: [
  71260. [ new Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
  71261. ],
  71262. Y: [
  71263. [ new Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]
  71264. ],
  71265. Z: [
  71266. [ new Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]
  71267. ]
  71268. };
  71269. let arc = options.rotFullCircle ? 1 : 0.5;//add
  71270. var gizmoRotate = {
  71271. X: [
  71272. [ new Line( CircleGeometry( 1, arc ), matLineRed ) ],
  71273. [ new Mesh( new OctahedronBufferGeometry( 0.04, 0 ), matRed ), [ 0, 0, 0.99 ], null, [ 1, 3, 1 ]],
  71274. ],
  71275. Y: [
  71276. [ new Line( CircleGeometry( 1, arc ), matLineGreen ), null, [ 0, 0, - Math.PI / 2 ]],
  71277. [ new Mesh( new OctahedronBufferGeometry( 0.04, 0 ), matGreen ), [ 0, 0, 0.99 ], null, [ 3, 1, 1 ]],
  71278. ],
  71279. Z: [
  71280. [ new Line( CircleGeometry( 1, arc ), matLineBlue ), null, [ 0, Math.PI / 2, 0 ]],
  71281. [ new Mesh( new OctahedronBufferGeometry( 0.04, 0 ), matBlue ), [ 0.99, 0, 0 ], null, [ 1, 3, 1 ]],
  71282. ],
  71283. E: [
  71284. [ new Line( CircleGeometry( 1.25, 1 ), matLineYellowTransparent ), null, [ 0, Math.PI / 2, 0 ]],
  71285. [ new Mesh( new CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 1.17, 0, 0 ], [ 0, 0, - Math.PI / 2 ], [ 1, 1, 0.001 ]],
  71286. [ new Mesh( new CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ - 1.17, 0, 0 ], [ 0, 0, Math.PI / 2 ], [ 1, 1, 0.001 ]],
  71287. [ new Mesh( new CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, - 1.17, 0 ], [ Math.PI, 0, 0 ], [ 1, 1, 0.001 ]],
  71288. [ new Mesh( new CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, 1.17, 0 ], [ 0, 0, 0 ], [ 1, 1, 0.001 ]],
  71289. ],
  71290. XYZE: [
  71291. [ new Line( CircleGeometry( 1, 1 ), matLineGray ), null, [ 0, Math.PI / 2, 0 ]]
  71292. ]
  71293. };
  71294. var helperRotate = {
  71295. AXIS: [
  71296. [ new Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
  71297. ]
  71298. };
  71299. var pickerRotate = {
  71300. X: [
  71301. [ new Mesh( new TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ]],
  71302. ],
  71303. Y: [
  71304. [ new Mesh( new TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],
  71305. ],
  71306. Z: [
  71307. [ new Mesh( new TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
  71308. ],
  71309. E: [
  71310. [ new Mesh( new TorusBufferGeometry( 1.25, 0.1, 2, 24 ), matInvisible ) ]
  71311. ],
  71312. XYZE: [
  71313. [ new Mesh( new SphereBufferGeometry( 0.7, 10, 8 ), matInvisible ) ]
  71314. ]
  71315. };
  71316. var gizmoScale = {
  71317. X: [
  71318. [ new Mesh( scaleHandleGeometry, matRed ), [ 0.8, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
  71319. [ new Line( lineGeometry, matLineRed ), null, null, [ 0.8, 1, 1 ]]
  71320. ],
  71321. Y: [
  71322. [ new Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.8, 0 ]],
  71323. [ new Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ], [ 0.8, 1, 1 ]]
  71324. ],
  71325. Z: [
  71326. [ new Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.8 ], [ Math.PI / 2, 0, 0 ]],
  71327. [ new Line( lineGeometry, matLineBlue ), null, [ 0, - Math.PI / 2, 0 ], [ 0.8, 1, 1 ]]
  71328. ],
  71329. XY: [
  71330. [ new Mesh( scaleHandleGeometry, matYellowTransparent ), [ 0.85, 0.85, 0 ], null, [ 2, 2, 0.2 ]],
  71331. [ new Line( lineGeometry, matLineYellow ), [ 0.855, 0.98, 0 ], null, [ 0.125, 1, 1 ]],
  71332. [ new Line( lineGeometry, matLineYellow ), [ 0.98, 0.855, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]]
  71333. ],
  71334. /* YZ: [
  71335. [ new THREE.Mesh( scaleHandleGeometry, matCyanTransparent ), [ 0, 0.85, 0.85 ], null, [ 0.2, 2, 2 ]],
  71336. [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.855, 0.98 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]],
  71337. [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.98, 0.855 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]
  71338. ],
  71339. XZ: [
  71340. [ new THREE.Mesh( scaleHandleGeometry, matMagentaTransparent ), [ 0.85, 0, 0.85 ], null, [ 2, 0.2, 2 ]],
  71341. [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.855, 0, 0.98 ], null, [ 0.125, 1, 1 ]],
  71342. [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.98, 0, 0.855 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]
  71343. ],
  71344. XYZX: [
  71345. [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 1.1, 0, 0 ]],
  71346. ],*/
  71347. XYZY: [
  71348. [ new Mesh( new BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 0, 1.1, 0 ]],
  71349. ]/* ,
  71350. XYZZ: [
  71351. [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 0, 0, 1.1 ]],
  71352. ] */
  71353. };
  71354. var pickerScale = {
  71355. X: [
  71356. [ new Mesh( new CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]
  71357. ],
  71358. Y: [
  71359. [ new Mesh( new CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0.5, 0 ]]
  71360. ],
  71361. Z: [
  71362. [ new Mesh( new CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]]
  71363. ],
  71364. XY: [
  71365. [ new Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0.85, 0 ], null, [ 3, 3, 0.2 ]],
  71366. ],
  71367. /*YZ: [
  71368. [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0, 0.85, 0.85 ], null, [ 0.2, 3, 3 ]],
  71369. ],
  71370. XZ: [
  71371. [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0, 0.85 ], null, [ 3, 0.2, 3 ]],
  71372. ],
  71373. XYZX: [
  71374. [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 1.1, 0, 0 ]],
  71375. ],*/
  71376. XYZY: [
  71377. [ new Mesh( new BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 1.1, 0 ]],
  71378. ]/* ,
  71379. XYZZ: [
  71380. [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 1.1 ]],
  71381. ] */
  71382. };
  71383. var helperScale = {
  71384. X: [
  71385. [ new Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
  71386. ],
  71387. Y: [
  71388. [ new Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]
  71389. ],
  71390. Z: [
  71391. [ new Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]
  71392. ]
  71393. };
  71394. // Creates an THREE.Object3D with gizmos described in custom hierarchy definition.
  71395. var setupGizmo = function ( gizmoMap ) {
  71396. var gizmo = new Object3D();
  71397. for ( var name in gizmoMap ) {
  71398. for ( var i = gizmoMap[ name ].length; i --; ) {
  71399. var object = gizmoMap[ name ][ i ][ 0 ].clone();
  71400. var position = gizmoMap[ name ][ i ][ 1 ];
  71401. var rotation = gizmoMap[ name ][ i ][ 2 ];
  71402. var scale = gizmoMap[ name ][ i ][ 3 ];
  71403. var tag = gizmoMap[ name ][ i ][ 4 ];
  71404. // name and tag properties are essential for picking and updating logic.
  71405. object.name = name;
  71406. object.tag = tag;
  71407. if ( position ) {
  71408. object.position.set( position[ 0 ], position[ 1 ], position[ 2 ] );
  71409. }
  71410. if ( rotation ) {
  71411. object.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] );
  71412. }
  71413. if ( scale ) {
  71414. object.scale.set( scale[ 0 ], scale[ 1 ], scale[ 2 ] );
  71415. }
  71416. object.updateMatrix();
  71417. var tempGeometry = object.geometry.clone();
  71418. tempGeometry.applyMatrix4( object.matrix );
  71419. object.geometry = tempGeometry;
  71420. object.renderOrder = Infinity;
  71421. object.position.set( 0, 0, 0 );
  71422. object.rotation.set( 0, 0, 0 );
  71423. object.scale.set( 1, 1, 1 );
  71424. gizmo.add( object );
  71425. }
  71426. }
  71427. return gizmo;
  71428. };
  71429. // Reusable utility variables
  71430. var tempVector = new Vector3( 0, 0, 0 );
  71431. var tempEuler = new Euler();
  71432. var alignVector = new Vector3( 0, 1, 0 );
  71433. var zeroVector = new Vector3( 0, 0, 0 );
  71434. var lookAtMatrix = new Matrix4();
  71435. var tempQuaternion = new Quaternion();
  71436. var tempQuaternion2 = new Quaternion();
  71437. var identityQuaternion = new Quaternion();
  71438. var unitX = new Vector3( 1, 0, 0 );
  71439. var unitY = new Vector3( 0, 1, 0 );
  71440. var unitZ = new Vector3( 0, 0, 1 );
  71441. // Gizmo creation
  71442. this.gizmo = {};
  71443. this.picker = {};
  71444. this.helper = {};
  71445. this.add( this.gizmo[ "translate" ] = setupGizmo( gizmoTranslate ) );
  71446. this.add( this.gizmo[ "rotate" ] = setupGizmo( gizmoRotate ) );
  71447. this.add( this.gizmo[ "scale" ] = setupGizmo( gizmoScale ) );
  71448. this.add( this.picker[ "translate" ] = setupGizmo( pickerTranslate ) );
  71449. this.add( this.picker[ "rotate" ] = setupGizmo( pickerRotate ) );
  71450. this.add( this.picker[ "scale" ] = setupGizmo( pickerScale ) );
  71451. this.add( this.helper[ "translate" ] = setupGizmo( helperTranslate ) );
  71452. this.add( this.helper[ "rotate" ] = setupGizmo( helperRotate ) );
  71453. this.add( this.helper[ "scale" ] = setupGizmo( helperScale ) );
  71454. // Pickers should be hidden always
  71455. this.picker[ "translate" ].visible = false;
  71456. this.picker[ "rotate" ].visible = false;
  71457. this.picker[ "scale" ].visible = false;
  71458. // updateMatrixWorld will update transformations and appearance of individual handles
  71459. this.updateMatrixWorld = function () {
  71460. if(!this.parent.visible)return //add
  71461. var space = this.space;
  71462. if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation
  71463. var quaternion = space === "local" ? this.worldQuaternion : identityQuaternion;
  71464. // Show only gizmos for current transform mode
  71465. this.gizmo[ "translate" ].visible = this.mode === "translate";
  71466. this.gizmo[ "rotate" ].visible = this.mode === "rotate";
  71467. this.gizmo[ "scale" ].visible = this.mode === "scale";
  71468. this.helper[ "translate" ].visible = this.mode === "translate";
  71469. this.helper[ "rotate" ].visible = this.mode === "rotate";
  71470. this.helper[ "scale" ].visible = this.mode === "scale";
  71471. var handles = [];
  71472. handles = handles.concat( this.picker[ this.mode ].children );
  71473. handles = handles.concat( this.gizmo[ this.mode ].children );
  71474. handles = handles.concat( this.helper[ this.mode ].children );
  71475. for ( var i = 0; i < handles.length; i ++ ) {
  71476. var handle = handles[ i ];
  71477. //add
  71478. if(this.hideAxis[this.mode] && this.hideAxis[this.mode].some(e=>handle.name.includes(e.toUpperCase()))){
  71479. Potree.Utils.updateVisible(handle, 'hidden', false);
  71480. continue
  71481. }
  71482. let visible = true;
  71483. // hide aligned to camera
  71484. handle.rotation.set( 0, 0, 0 );
  71485. handle.position.copy( this.worldPosition );
  71486. if(this.camera.type == "OrthographicCamera"){
  71487. var eyeDistance = 800 / this.camera.zoom;
  71488. }else {
  71489. var eyeDistance = this.worldPosition.distanceTo( this.cameraPosition );
  71490. }
  71491. handle.scale.set( 1, 1, 1 ).multiplyScalar( eyeDistance * this.size / 7 );
  71492. // TODO: simplify helpers and consider decoupling from gizmo
  71493. if ( handle.tag === 'helper' ) {
  71494. visible = false;
  71495. if ( handle.name === 'AXIS' ) {
  71496. handle.position.copy( this.worldPositionStart );
  71497. visible = !!this.axis;
  71498. if ( this.axis === 'X' ) {
  71499. tempQuaternion.setFromEuler( tempEuler.set( 0, 0, 0 ) );
  71500. handle.quaternion.copy( quaternion ).multiply( tempQuaternion );
  71501. if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
  71502. visible = false;
  71503. }
  71504. }
  71505. if ( this.axis === 'Y' ) {
  71506. tempQuaternion.setFromEuler( tempEuler.set( 0, 0, Math.PI / 2 ) );
  71507. handle.quaternion.copy( quaternion ).multiply( tempQuaternion );
  71508. if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
  71509. visible = false;
  71510. }
  71511. }
  71512. if ( this.axis === 'Z' ) {
  71513. tempQuaternion.setFromEuler( tempEuler.set( 0, Math.PI / 2, 0 ) );
  71514. handle.quaternion.copy( quaternion ).multiply( tempQuaternion );
  71515. if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
  71516. visible = false;
  71517. }
  71518. }
  71519. if ( this.axis === 'XYZE' ) {
  71520. tempQuaternion.setFromEuler( tempEuler.set( 0, Math.PI / 2, 0 ) );
  71521. alignVector.copy( this.rotationAxis );
  71522. handle.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( zeroVector, alignVector, unitY ) );
  71523. handle.quaternion.multiply( tempQuaternion );
  71524. visible = this.dragging;
  71525. }
  71526. if ( this.axis === 'E' ) {
  71527. visible = false;
  71528. }
  71529. } else if ( handle.name === 'START' ) {
  71530. handle.position.copy( this.worldPositionStart );
  71531. visible = this.dragging;
  71532. } else if ( handle.name === 'END' ) {
  71533. handle.position.copy( this.worldPosition );
  71534. visible = this.dragging;
  71535. } else if ( handle.name === 'DELTA' ) {
  71536. handle.position.copy( this.worldPositionStart );
  71537. handle.quaternion.copy( this.worldQuaternionStart );
  71538. tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( - 1 );
  71539. tempVector.applyQuaternion( this.worldQuaternionStart.clone().invert() );
  71540. handle.scale.copy( tempVector );
  71541. visible = this.dragging;
  71542. } else {
  71543. handle.quaternion.copy( quaternion );
  71544. if ( this.dragging ) {
  71545. handle.position.copy( this.worldPositionStart );
  71546. } else {
  71547. handle.position.copy( this.worldPosition );
  71548. }
  71549. if ( this.axis ) {
  71550. visible = this.axis.search( handle.name ) !== - 1;
  71551. }
  71552. }
  71553. // If updating helper, skip rest of the loop
  71554. Potree.Utils.updateVisible(handle, 'hidden', !!visible);
  71555. continue;
  71556. }
  71557. // Align handles to current local or world rotation
  71558. handle.quaternion.copy( quaternion );
  71559. if ( this.mode === 'translate' || this.mode === 'scale' ) {
  71560. // Hide translate and scale axis facing the camera
  71561. var AXIS_HIDE_TRESHOLD = 0.99;
  71562. var PLANE_HIDE_TRESHOLD = 0.2;
  71563. var AXIS_FLIP_TRESHOLD = 0.0;
  71564. if(options.dontHideWhenFaceCamera){//xzw add
  71565. //正对镜头时不隐藏箭头
  71566. }else {
  71567. if ( handle.name === 'X' || handle.name === 'XYZX' ) {
  71568. if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
  71569. handle.scale.set( 1e-10, 1e-10, 1e-10 );
  71570. visible = false;
  71571. }
  71572. }
  71573. if ( handle.name === 'Y' || handle.name === 'XYZY' ) {
  71574. if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
  71575. handle.scale.set( 1e-10, 1e-10, 1e-10 );
  71576. visible = false;
  71577. }
  71578. }
  71579. if ( handle.name === 'Z' || handle.name === 'XYZZ' ) {
  71580. if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
  71581. handle.scale.set( 1e-10, 1e-10, 1e-10 );
  71582. visible = false;
  71583. }
  71584. }
  71585. if ( handle.name === 'XY' ) {
  71586. if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
  71587. handle.scale.set( 1e-10, 1e-10, 1e-10 );
  71588. visible = false;
  71589. }
  71590. }
  71591. if ( handle.name === 'YZ' ) {
  71592. if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
  71593. handle.scale.set( 1e-10, 1e-10, 1e-10 );
  71594. visible = false;
  71595. }
  71596. }
  71597. if ( handle.name === 'XZ' ) {
  71598. if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
  71599. handle.scale.set( 1e-10, 1e-10, 1e-10 );
  71600. visible = false;
  71601. }
  71602. }
  71603. }
  71604. // Flip translate and scale axis ocluded behind another axis
  71605. //xzw 改 去掉反向箭头
  71606. if ( handle.name.search( 'X' ) !== - 1 ) {
  71607. if ( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) {
  71608. /* if ( handle.tag === 'fwd' ) {
  71609. handle.visible = false;
  71610. } else {
  71611. handle.scale.x *= - 1;
  71612. }
  71613. } else if ( handle.tag === 'bwd' ) {
  71614. handle.visible = false;*/
  71615. handle.scale.x *= - 1;
  71616. }
  71617. }
  71618. if ( handle.name.search( 'Y' ) !== - 1 ) {
  71619. if ( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) {
  71620. /* if ( handle.tag === 'fwd' ) {
  71621. handle.visible = false;
  71622. } else {
  71623. handle.scale.y *= - 1;
  71624. }
  71625. } else if ( handle.tag === 'bwd' ) {
  71626. handle.visible = false;
  71627. */
  71628. handle.scale.y *= - 1;
  71629. }
  71630. }
  71631. if ( handle.name.search( 'Z' ) !== - 1 ) {
  71632. if ( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) {
  71633. /* if ( handle.tag === 'fwd' ) {
  71634. handle.visible = false;
  71635. } else {
  71636. handle.scale.z *= - 1;
  71637. }
  71638. } else if ( handle.tag === 'bwd' ) {
  71639. handle.visible = false; */
  71640. handle.scale.z *= - 1;
  71641. }
  71642. }
  71643. } else if ( this.mode === 'rotate' ) {
  71644. // Align handles to current local or world rotation
  71645. tempQuaternion2.copy( quaternion );
  71646. alignVector.copy( this.eye ).applyQuaternion( tempQuaternion.copy( quaternion ).invert() );
  71647. if ( handle.name.search( "E" ) !== - 1 ) {
  71648. handle.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( this.eye, zeroVector, unitY ) );
  71649. }
  71650. if ( handle.name === 'X' ) {
  71651. tempQuaternion.setFromAxisAngle( unitX, Math.atan2( - alignVector.y, alignVector.z ) );
  71652. tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion );
  71653. handle.quaternion.copy( tempQuaternion );
  71654. }
  71655. if ( handle.name === 'Y' ) {
  71656. tempQuaternion.setFromAxisAngle( unitY, Math.atan2( alignVector.x, alignVector.z ) );
  71657. tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion );
  71658. handle.quaternion.copy( tempQuaternion );
  71659. }
  71660. if ( handle.name === 'Z' ) {
  71661. tempQuaternion.setFromAxisAngle( unitZ, Math.atan2( alignVector.y, alignVector.x ) );
  71662. tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion );
  71663. handle.quaternion.copy( tempQuaternion );
  71664. }
  71665. }
  71666. // Hide disabled axes
  71667. visible = visible && ( handle.name.indexOf( "X" ) === - 1 || this.showX );
  71668. visible = visible && ( handle.name.indexOf( "Y" ) === - 1 || this.showY );
  71669. visible = visible && ( handle.name.indexOf( "Z" ) === - 1 || this.showZ );
  71670. visible = visible && ( handle.name.indexOf( "E" ) === - 1 || ( this.showX && this.showY && this.showZ ) );
  71671. Potree.Utils.updateVisible(handle, 'hidden', !!visible);
  71672. // highlight selected axis
  71673. handle.material._opacity = handle.material._opacity || handle.material.opacity;
  71674. handle.material._color = handle.material._color || handle.material.color.clone();
  71675. handle.material.color.copy( handle.material._color );
  71676. handle.material.opacity = handle.material._opacity;
  71677. if ( ! this.enabled ) {
  71678. handle.material.opacity *= 0.5;
  71679. handle.material.color.lerp( new Color( 1, 1, 1 ), 0.5 );
  71680. } else if ( this.axis ) {
  71681. if ( handle.name === this.axis ) {
  71682. handle.material.opacity = 1.0;
  71683. handle.material.color.lerp( new Color( 1, 1, 1 ), 0.5 );
  71684. } else if ( this.axis.split( '' ).some( function ( a ) {
  71685. return handle.name === a;
  71686. } ) ) {
  71687. handle.material.opacity = 1.0;
  71688. handle.material.color.lerp( new Color( 1, 1, 1 ), 0.5 );
  71689. } else {
  71690. handle.material.opacity *= 0.25;
  71691. handle.material.color.lerp( new Color( 1, 1, 1 ), 0.5 );
  71692. }
  71693. }
  71694. }
  71695. Object3D.prototype.updateMatrixWorld.call( this );
  71696. };
  71697. };
  71698. /* var TransformControlsLines = function (options) {
  71699. THREE.Object3D.call( this)
  71700. let label1 = new Label2D({ innerHTML:`<div>与相机水平距离</div>` , domElement:$("#otherLabels")[0] ,autoUpdate:true })
  71701. let label2 = new Label2D({ innerHTML:`<div>与相机高度差</div>` , domElement:$("#otherLabels")[0] ,autoUpdate:true })
  71702. let css = {'opacity': 0.7, 'color': '#07fceb', transform:'translate(-50%, -50%)'}
  71703. label1.elem.css(css);
  71704. label2.elem.css(css)
  71705. //for(let i=0;i<2;i++){
  71706. // let line = LineDraw.createLine([new THREE.THREE.Vector3, new THREE.THREE.Vector3],{color:'#07fceb', opacity:0.7 })
  71707. // this.add(line)
  71708. //}
  71709. this.updateTransform = function(object){
  71710. object = object || this.parent.object;
  71711. let A = player.position.clone(); //当前相机位置
  71712. let B = object.position //物体位置
  71713. let C = B.clone().setY(A.y); //物体在相机的高度的位置
  71714. let D = A.clone().setY(B.y); //相机在物体的高度的位置
  71715. //LineDraw.moveLine(this.children[0], [B, C]) // 垂直线
  71716. //LineDraw.moveLine(this.children[1], [D, B]) // 水平线
  71717. let dis1 = toPrecision(D.distanceTo(B),1)
  71718. let dis2 = C.y - B.y
  71719. label1.elem.text('与相机水平距离: '+dis1+'米')
  71720. label2.elem.text('在相机之'+ (dis2>0?'下' : '上') +' :'+ toPrecision(dis2 , 1) +'米')
  71721. label1.setPos(new THREE.THREE.Vector3().addVectors(D,B).multiplyScalar(0.5))
  71722. label2.setPos(new THREE.THREE.Vector3().addVectors(B,C).multiplyScalar(0.5))
  71723. }
  71724. this.setVisible = (v,reason)=>{
  71725. label1.setVisible(v, reason || 'unvisi')
  71726. label2.setVisible(v, reason || 'unvisi')
  71727. this.visible = label1.visible
  71728. if(this.visible){
  71729. this.updateTransform()
  71730. }
  71731. }
  71732. this.setVisible(false)
  71733. player.on("mode.changing",(currentMode, mode, pano, duration)=>{
  71734. if(mode != 'panorama'){
  71735. this.setVisible(false, 'isPanorama')
  71736. }else{
  71737. this.setVisible(true, 'isPanorama')
  71738. }
  71739. })
  71740. player.on("flying.started",( )=>{
  71741. this.setVisible(false, 'flying')
  71742. })
  71743. player.on("flying.ended",( )=>{
  71744. this.setVisible(true, 'flying')
  71745. })
  71746. }
  71747. */
  71748. var TransformControlsPlane = function (options) {
  71749. 'use strict';
  71750. Mesh.call( this,
  71751. new PlaneBufferGeometry( 100000, 100000, 2, 2 ),
  71752. new MeshBasicMaterial( { color: "#ff0000", visible: false, wireframe: false, side: DoubleSide, transparent: true, opacity: 0.2 } )
  71753. );
  71754. this.type = 'TransformControlsPlane';
  71755. var unitX = new Vector3( 1, 0, 0 );
  71756. var unitY = new Vector3( 0, 1, 0 );
  71757. var unitZ = new Vector3( 0, 0, 1 );
  71758. var tempVector = new Vector3();
  71759. var dirVector = new Vector3();
  71760. var alignVector = new Vector3();
  71761. var tempMatrix = new Matrix4();
  71762. var identityQuaternion = new Quaternion();
  71763. this.updateMatrixWorld = function () {
  71764. if(!this.visible)return//add
  71765. var space = this.space;
  71766. this.position.copy( this.worldPosition );
  71767. if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation
  71768. unitX.set( 1, 0, 0 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion );
  71769. unitY.set( 0, 1, 0 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion );
  71770. unitZ.set( 0, 0, 1 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion );
  71771. // Align the plane for current transform mode, axis and space.
  71772. alignVector.copy( unitY );
  71773. switch ( this.mode ) {
  71774. case 'translate':
  71775. case 'scale':
  71776. switch ( this.axis ) {
  71777. case 'X':
  71778. alignVector.copy( this.eye ).cross( unitX );
  71779. dirVector.copy( unitX ).cross( alignVector );
  71780. break;
  71781. case 'Y':
  71782. alignVector.copy( this.eye ).cross( unitY );
  71783. dirVector.copy( unitY ).cross( alignVector );
  71784. break;
  71785. case 'Z':
  71786. alignVector.copy( this.eye ).cross( unitZ );
  71787. dirVector.copy( unitZ ).cross( alignVector );
  71788. break;
  71789. case 'XY':
  71790. dirVector.copy( unitZ );
  71791. break;
  71792. case 'YZ':
  71793. dirVector.copy( unitX );
  71794. break;
  71795. case 'XZ':
  71796. alignVector.copy( unitZ );
  71797. dirVector.copy( unitY );
  71798. break;
  71799. case 'XYZ':
  71800. case 'E':
  71801. default: //xzw add for scale xyzz
  71802. dirVector.set( 0, 0, 0 );
  71803. break;
  71804. }
  71805. break;
  71806. case 'rotate':
  71807. default:
  71808. // special case for rotate
  71809. dirVector.set( 0, 0, 0 );
  71810. }
  71811. if ( dirVector.length() === 0 ) {
  71812. // If in rotate mode, make the plane parallel to camera
  71813. this.quaternion.copy( this.cameraQuaternion );
  71814. } else {
  71815. tempMatrix.lookAt( tempVector.set( 0, 0, 0 ), dirVector, alignVector );
  71816. this.quaternion.setFromRotationMatrix( tempMatrix );
  71817. }
  71818. Object3D.prototype.updateMatrixWorld.call( this );
  71819. };
  71820. };
  71821. TransformControls.prototype = Object.assign( Object.create( Object3D.prototype ), {
  71822. constructor: TransformControls,
  71823. isTransformControls: true
  71824. } );
  71825. TransformControlsGizmo.prototype = Object.assign( Object.create( Object3D.prototype ), {
  71826. constructor: TransformControlsGizmo,
  71827. isTransformControlsGizmo: true
  71828. } );
  71829. TransformControlsPlane.prototype = Object.assign( Object.create( Mesh.prototype ), {
  71830. constructor: TransformControlsPlane,
  71831. isTransformControlsPlane: true
  71832. } );
  71833. /*
  71834. 备注:
  71835. //这里虽然 使坐标轴在boundingBox中心
  71836. boundingBox && this.object.boundingBox.getCenter(worldPosition).applyMatrix4(this.object.matrixWorld);
  71837. 但是旋转中心并不是这个坐标轴显示的位置,需要再执行 MergeEditor.maintainBoundXY()才能维持在这个中心
  71838. */
  71839. //import History from "../../utils/History.js"
  71840. const cameraProps = [
  71841. {
  71842. name : 'top',
  71843. axis:["x","y"],
  71844. direction : new Vector3(0,0,-1), //镜头朝向
  71845. openCount:0,
  71846. }
  71847. ];
  71848. class Clipping extends EventDispatcher{ //实时剪裁
  71849. constructor(){
  71850. super();
  71851. this.views = {};
  71852. this.cameras = {};
  71853. this.orthoCamera = new OrthographicCamera(-100, 100, 100, 100, 0.01, 10000);
  71854. this.orthoCamera.up.set(0,0,1);
  71855. }
  71856. init(){
  71857. if(this.inited)return
  71858. this.initViews();
  71859. this.inited = true;
  71860. this.prepareRecord = true;
  71861. this.activeViewName = 'mainView';
  71862. this.events = {
  71863. transfromCallback:(e)=>{//拖拽变化时
  71864. this.adjustCamHeight();
  71865. //检测漫游点、回退等
  71866. /* if(this.prepareRecord){
  71867. let box = viewer.transformationTool.selection[0]
  71868. this.history.writeIn({box, matrix:box.matrix.clone()})
  71869. this.prepareRecord = false
  71870. } */
  71871. },
  71872. /* onTransfromEnd:(e)=>{//拖拽结束、松开
  71873. this.prepareRecord = true
  71874. }, */
  71875. selectCallback:(e)=>{
  71876. this.adjustCamHeight();
  71877. let unableNavigate = this.activeViewName != 'mainView' || e.selection.length > 0;
  71878. if(Potree.settings.unableNavigate && !unableNavigate){
  71879. setTimeout(()=>{
  71880. Potree.settings.unableNavigate = this.activeViewName != 'mainView' || e.selection.length > 0;
  71881. },300);//延迟是因为点击时取消选择后可能立即就会触发flyToPano。 而且有的人喜欢点两下
  71882. }else Potree.settings.unableNavigate = unableNavigate;
  71883. },
  71884. onkeydown:(e)=>{
  71885. if(e.keyCode == 8 || e.keyCode == 46){// Backspace or Delete
  71886. viewer.inputHandler.selection[0] && viewer.scene.removeVolume(viewer.inputHandler.selection[0]);
  71887. }
  71888. }
  71889. };
  71890. /* this.history = new History({ //也可以写到全局,但需要加个判断物品是否存在的函数
  71891. applyData: (data)=>{
  71892. if(viewer.scene.volumes.includes(data.box)){
  71893. data.matrix.decompose( data.box.position, data.box.quaternion, data.box.scale );
  71894. }else{
  71895. this.history.undo()//找不到就回退下一个。(直接写这?)
  71896. }
  71897. }
  71898. }) */
  71899. }
  71900. initViews(){
  71901. this.splitScreenTool = new SplitScreen;
  71902. for(let i=0;i<1;i++){
  71903. let prop = cameraProps[i];
  71904. let view = new ExtendView();
  71905. this.views[prop.name] = view;
  71906. this.cameras[prop.name] = this.orthoCamera;
  71907. view.direction = prop.direction;
  71908. }
  71909. this.views.mainView = viewer.mainViewport.view;
  71910. this.cameras.mainView = viewer.mainViewport.camera;
  71911. }
  71912. switchView(name){//替换view和camera到mainViewport
  71913. if(this.activeViewName == name)return
  71914. let view = this.views[name];
  71915. let camera = this.cameras[name];
  71916. let prop = cameraProps.find(e=>e.name == name);
  71917. let {boundSize, center, boundingBox} = viewer.bound;
  71918. this.lastViewName = this.activeViewName;
  71919. this.activeViewName = name;
  71920. let lastView = this.views[this.lastViewName];
  71921. let lastCamera = this.cameras[this.lastViewName];
  71922. viewer.mainViewport.view = view;
  71923. viewer.mainViewport.camera = camera;
  71924. if(lastCamera)lastView.zoom = lastCamera.zoom;
  71925. /* if(lastView){//2d->3d
  71926. view.copy(lastView)
  71927. } */
  71928. if(name == 'mainView'){
  71929. Potree.settings.unableNavigate = false;
  71930. /* viewer.transformationTool.handles['scale.z+'].node.visible = true
  71931. viewer.transformationTool.handles['scale.z-'].node.visible = true */
  71932. }else {
  71933. Potree.settings.unableNavigate = true;
  71934. /* viewer.transformationTool.handles['scale.z+'].node.visible = false
  71935. viewer.transformationTool.handles['scale.z-'].node.visible = false */
  71936. if(prop.openCount == 0){//至多执行一次
  71937. //this.viewportFitBound(name, boundSize, center)
  71938. this.orthoMoveFit(center, {bound:boundingBox}, 0);
  71939. this.camHeightOutOfModel = view.position.z; //记录下此刻相机高度。
  71940. }
  71941. prop.openCount++;
  71942. this.adjustCamHeight();
  71943. /* this.targetPlane.setFromNormalAndCoplanarPoint( view.direction.clone(), center )
  71944. this.targetPlane.projectPoint(view.position, this.shiftTarget ) //target转换到过模型中心的平面,以保证镜头一定在模型外
  71945. view.position.copy(this.splitScreenTool.getPosOutOfModel(viewer.mainViewport)) */
  71946. if(view.zoom)camera.zoom = view.zoom;//恢复上次的zoom
  71947. }
  71948. viewer.updateScreenSize({forceUpdateSize:true});//更新camera aspect left等
  71949. if(viewer.inputHandler.selection.length){
  71950. this.focusOnObject(viewer.inputHandler.selection[0]);
  71951. }
  71952. }
  71953. focusOnObject(box, duration=0){
  71954. if(this.activeViewName == 'mainView'){
  71955. viewer.focusOnObject({boundingBox:box.boundingBox.clone().applyMatrix4(box.matrixWorld)}, 'boundingBox', duration);
  71956. }else {
  71957. this.orthoMoveFit(box.position, {bound:box.boundingBox.clone().applyMatrix4(box.matrixWorld)}, duration);
  71958. }
  71959. this.adjustCamHeight();
  71960. }
  71961. orthoMoveFit(pos, info, duration){
  71962. var margin = {x:viewer.mainViewport.resolution.x*0.4, y:viewer.mainViewport.resolution.y*0.4};
  71963. this.splitScreenTool.viewportFitBound(viewer.mainViewport, info.bound, pos, duration, margin );
  71964. }
  71965. adjustCamHeight(){
  71966. if(this.activeViewName != 'top')return
  71967. let view = this.views.top;
  71968. let height;
  71969. if(viewer.inputHandler.selection.length){ //相机高度位于选中的box的顶部
  71970. let box = viewer.inputHandler.selection[0];
  71971. height = box.boundingBox.clone().applyMatrix4(box.matrixWorld).max.z;
  71972. }else {
  71973. height = this.camHeightOutOfModel; //显示全部点云
  71974. }
  71975. view.position.z = height;
  71976. //console.log('adjustCamHeight',height)
  71977. //缺点:1 会导致缩放很小的时候,transformationTool的轴因放大到了相机背面。(只有scale轴做了处理)
  71978. //2 无法直接切换 看不到的box,但可以先取消选择
  71979. //3 但是俯视图中无法切换到被上层盖住的box(不过把俯视图作为辅助,只针对单个box调动的话,问题不大)
  71980. }
  71981. enter(){
  71982. this.init();
  71983. viewer.transformationTool.setModeEnable(['translation']);
  71984. //viewer.transformationTool.handles['rotation.x'].node.visible = false
  71985. viewer.transformationTool.frame.material.visible = false; //不盖住boxVolume的frame
  71986. this.targetPlane = viewer.mainViewport.targetPlane = new Plane();
  71987. this.shiftTarget = viewer.mainViewport.shiftTarget = new Vector3; //project在targetPlane上的位置
  71988. this.getAllBoxes().forEach(box=>{
  71989. Potree.Utils.updateVisible(box,'hidden',true); //显现
  71990. });
  71991. viewer.transformationTool.history.clear();
  71992. viewer.transformationTool.addEventListener('transformed', this.events.transfromCallback);
  71993. //viewer.transformationTool.addEventListener('stopDrag', this.events.onTransfromEnd)
  71994. viewer.inputHandler.addEventListener('selection_changed', this.events.selectCallback);
  71995. viewer.inputHandler.addEventListener('keydown', this.events.onkeydown);
  71996. this.setPointLevelAuto();
  71997. var initialPointcloud = viewer.scene.pointclouds.find(p => p.dataset_id == Potree.settings.originDatasetId);
  71998. //隐藏 初始数据集以外的数据集
  71999. viewer.scene.pointclouds.forEach(e=>{
  72000. if(e.dataset_id!=Potree.settings.originDatasetId){
  72001. Potree.Utils.updateVisible(e,'enterClipping',false);
  72002. //Potree.settings.floorplanEnables[e.dataset_id] = false
  72003. e.panos.forEach(pano=>pano.setEnable(false)); //禁止漫游
  72004. }else {
  72005. Potree.Utils.updateVisible(e,'enterClipping',true, 1, 'add');
  72006. //Potree.settings.floorplanEnables[e.dataset_id] = true
  72007. }
  72008. });
  72009. viewer.flyToDataset({ pointcloud : initialPointcloud, duration:0});
  72010. }
  72011. leave(){
  72012. viewer.transformationTool.setModeEnable(['scale', 'translation', 'rotation'] );
  72013. viewer.transformationTool.frame.material.visible = true; //恢复
  72014. this.switchView( 'mainView' );
  72015. this.getAllBoxes().forEach(box=>{
  72016. Potree.Utils.updateVisible(box,'hidden',false);//隐身
  72017. });
  72018. viewer.transformationTool.removeEventListener('transformed', this.events.transfromCallback);
  72019. //viewer.transformationTool.removeEventListener('stopDrag', this.events.onTransfromEnd)
  72020. viewer.inputHandler.removeEventListener('selection_changed', this.events.selectCallback);
  72021. //viewer.inputHandler.removeEventListener('keydown', this.events.onkeydown)
  72022. viewer.transformObject(null);
  72023. viewer.transformationTool.history.clear();
  72024. //恢复 初始数据集以外的数据集
  72025. viewer.scene.pointclouds.forEach(e=>{
  72026. if(e.dataset_id!=Potree.settings.originDatasetId){
  72027. Potree.Utils.updateVisible(e,'enterClipping',true);
  72028. e.panos.forEach(pano=>pano.setEnable(true));
  72029. }else {
  72030. Potree.Utils.updateVisible(e,'enterClipping',false, 0, 'cancel');
  72031. }
  72032. });
  72033. }
  72034. setTranMode(mode){//rotate or translate
  72035. this.tranMode = mode;
  72036. viewer.transformationTool.setModeEnable([mode]);
  72037. }
  72038. //问:是否要显示其他数据集
  72039. setPointLevelAuto(){
  72040. /*
  72041. let visiCount = viewer.images360.panos.length
  72042. let maxCount = 200, minCount = 20, minPer = 0.7, maxPer = 1
  72043. let percent = maxPer - ( maxPer - minPer) * THREE.Math.clamp((visiCount - minCount) / (maxCount - minCount),0,1)
  72044. Potree.settings.UserDensityPercent = percent ---还是不限制了,尤其是平面图希望更细致点,毕竟剪裁主要要看清剪裁的部位。
  72045. */
  72046. viewer.setPointBudget(5*1000*1000); //给个中等到高等之间的质量
  72047. Potree.settings.sizeFitToLevel = true;
  72048. viewer.setPointLevels();
  72049. }
  72050. getAllBoxes(){
  72051. return viewer.scene.volumes.filter(v=>v.clip && v instanceof Potree.BoxVolume )
  72052. }
  72053. getCalcData(){//给后台矩阵数据,以裁剪点云。
  72054. let Clip = viewer.modules.Clip; //裁剪下载模块
  72055. let data = {
  72056. transformation_matrix: viewer.scene.pointclouds.filter(p=>p.dataset_id == Potree.settings.originDatasetId).map((cloud)=>{
  72057. let data = {
  72058. id: cloud.dataset_id,
  72059. matrix : new Matrix4().elements, //参照downloadNoCrop,给默认值,表示没有最外层裁剪
  72060. VisiMatrixes: cloud.material.clipBoxes_in.filter(e=>!e.box.isNew).map(e=>Clip.getTransformationMatrix(cloud, e.inverse).elements),
  72061. UnVisiMatrixes: cloud.material.clipBoxes_out.filter(e=>!e.box.isNew).map(e=>Clip.getTransformationMatrix(cloud, e.inverse).elements),
  72062. modelMatrix:(new Matrix4).copy(cloud.transformMatrix).transpose().elements
  72063. };
  72064. return data
  72065. }) ,
  72066. aabb: "b-12742000 -12742000 -12742000 12742000 12742000 12742000" //剪裁空间
  72067. };
  72068. return data
  72069. }
  72070. saveClipData(){//输出所有的clip volumeBox
  72071. let oldState = !viewer.clipUnabled;
  72072. viewer.setClipState(true);
  72073. let data = this.getAllBoxes().filter(e=>!e.isNew).map(volume=>{
  72074. return {
  72075. clipTask: volume.clipTask,
  72076. position: Potree.Utils.datasetPosTransform({position:volume.position, toDataset: true, datasetId: Potree.settings.originDatasetId}).toArray(),
  72077. rotation: Potree.Utils.datasetRotTransform({rotation:volume.rotation, toDataset: true, datasetId: Potree.settings.originDatasetId, getRotation:true}).toArray().slice(0,3),
  72078. scale: volume.scale.toArray(),
  72079. }
  72080. });
  72081. console.log(data);
  72082. console.log(JSON.stringify(data));
  72083. viewer.setClipState(oldState);
  72084. return data
  72085. }
  72086. loadFromData(data=[]){
  72087. data.forEach(v=>{
  72088. let volume = new Potree.BoxVolume({clip:true, clipTask:v.clipTask});
  72089. volume.scale.fromArray(v.scale);
  72090. volume.position.fromArray(v.position);
  72091. volume.rotation.fromArray(v.rotation);
  72092. volume.position.copy(Potree.Utils.datasetPosTransform({position:volume.position, fromDataset: true, datasetId:Potree.settings.originDatasetId}));
  72093. volume.rotation.copy(Potree.Utils.datasetRotTransform({rotation:volume.rotation, fromDataset: true, datasetId:Potree.settings.originDatasetId, getRotation:true}));
  72094. viewer.scene.addVolume(volume);
  72095. viewer.volumeTool.scene.add(volume);
  72096. });
  72097. }
  72098. }
  72099. //注意:实时裁剪只对初始数据集有效
  72100. const texLoader$7 = new TextureLoader();
  72101. const circleGeo = new CircleGeometry(1.45,100);
  72102. const sphereGeo = new SphereBufferGeometry(0.018,10,10);
  72103. const magDisMin = 1;//相机离目标位置的距离的分界线,当离得远时要缩小fov以使看到的视野固定(望远镜效果)
  72104. const magDisMax = 20;
  72105. /* const radius_ = 0.2; //当相机离目标位置的距离>magDistance_时,希望看到的视野的半径
  72106. const maxFov = THREE.Math.radToDeg(Math.atan(radius_ / magDisMin )) * 2//提前计算出当相机离目标位置的距离<magDisMin时的fov,均使用=magDisMin时的fov。只要保证该fov大于主相机的fov就会有放大效果
  72107. */
  72108. let w = 250/1.43;
  72109. let maxPX = 1366*1024; //ipad pro. 大于这个分辨率的就直接用devicePixelRatio, 如macbook也是
  72110. const width2dPX = Math.round(window.devicePixelRatio >= 2 ? ( window.screen.width * window.screen.height >= maxPX ? window.devicePixelRatio/1.2 : window.devicePixelRatio/1.5)*w : w); //触屏或高分辨率的可能要放大些。但在手机上不能太大
  72111. //console.log('width2dPX', width2dPX)
  72112. const orthoView = new ExtendView();
  72113. class Magnifier extends Object3D {//放大镜or望远镜
  72114. constructor (viewer) {
  72115. super();
  72116. this.width = this.height = width2dPX/* * window.devicePixelRatio */;
  72117. this.camera = new PerspectiveCamera(50, 1, 0.01, 10000); //fov aspect near far
  72118. this.camera.up = new Vector3(0,0,1);
  72119. this.viewport = new Viewport( null, this.camera, {
  72120. left:0, bottom:0, width:1, height: 1, name:'magnifier' , cameraLayers:['magnifierContent'],
  72121. pixelRatio:1
  72122. });
  72123. this.viewport.setResolution(this.width, this.height,0,0);
  72124. //Common.watch(this, 'visible', true)//监听
  72125. {
  72126. let density;
  72127. let sizeType;
  72128. let colorType;
  72129. let opacityBefore = new Map();
  72130. let visiMap = new Map();
  72131. this.viewport.beforeRender = ()=>{
  72132. viewer.scene.pointclouds.forEach(e=>{//因为更改pointDensity时会自动变opacity,所以这项最先获取
  72133. visiMap.set(e,e.visible);
  72134. e.visible = Potree.Utils.getObjVisiByReason(e, 'datasetSelection'); //先将隐藏的点云显示
  72135. opacityBefore.set(e,e.temp.pointOpacity);
  72136. });
  72137. //使放大镜里的pointDensity是'magnifier' 最高质量。
  72138. density = Potree.settings.pointDensity;
  72139. Potree.settings.pointDensity = 'magnifier';
  72140. viewer.scene.pointclouds.forEach(e=>{//因为全景模式的pointSizeType是fixed所以要还原下
  72141. sizeType = e.material.pointSizeType;
  72142. e.material.pointSizeType = Potree.config.material.pointSizeType;
  72143. //材质
  72144. colorType = e.material.activeAttributeName;
  72145. e.material.activeAttributeName = 'rgba';
  72146. e.changePointOpacity(1);
  72147. });
  72148. };
  72149. this.viewport.afterRender = ()=>{
  72150. Potree.settings.pointDensity = density;
  72151. viewer.scene.pointclouds.forEach(e=>{
  72152. e.visible = visiMap.get(e);
  72153. e.material.pointSizeType = sizeType;
  72154. e.material.activeAttributeName = colorType;
  72155. e.changePointOpacity(opacityBefore.get(e));
  72156. });
  72157. };
  72158. }
  72159. this.renderTarget = new WebGLRenderTarget(this.width,this.height, {
  72160. minFilter: LinearFilter, magFilter: LinearFilter,
  72161. format: RGBAFormat ,
  72162. /* type: THREE.FloatType,
  72163. minFilter: THREE.NearestFilter,
  72164. magFilter: THREE.NearestFilter,
  72165. */
  72166. } );
  72167. this.rtEDL = new WebGLRenderTarget(this.width, this.height, { //好像没用到? 因为这里不绘制测量线
  72168. minFilter: NearestFilter,
  72169. magFilter: NearestFilter,
  72170. format: RGBAFormat,
  72171. type: FloatType,
  72172. depthTexture: new DepthTexture(undefined, undefined, UnsignedIntType)
  72173. });
  72174. this.mesh = new Mesh(circleGeo, new MeshBasicMaterial({
  72175. side: DoubleSide ,
  72176. map: this.renderTarget.texture ,
  72177. transparent:true,
  72178. depthTest: !1,
  72179. //depthWrite: !1,
  72180. }));
  72181. this.overlayMesh = new Mesh(circleGeo, new MeshBasicMaterial({
  72182. side: DoubleSide ,
  72183. map:texLoader$7.load(Potree.resourcePath+'/textures/crosshair.png') ,
  72184. transparent:true,
  72185. depthTest: !1,
  72186. //depthWrite: !1,
  72187. }));
  72188. this.targetPoint = new Object3D;
  72189. this.targetPoint.add(new Mesh(sphereGeo, new MeshBasicMaterial({
  72190. color:"#ff0000",
  72191. transparent:true,
  72192. opacity:0.5,
  72193. })));
  72194. this.targetPoint.add(new Mesh(sphereGeo, new MeshBasicMaterial({
  72195. color:"#ff0000",
  72196. transparent:true,
  72197. opacity:0.2,
  72198. depthTest:false //被遮挡层
  72199. })));
  72200. this.targetPoint.name = 'magnifierPointTarget';
  72201. viewer.scene.scene.add(this.targetPoint);
  72202. Potree.Utils.setObjectLayers(this.targetPoint, 'magnifierContent' );
  72203. this.add(this.mesh);
  72204. this.add(this.overlayMesh);
  72205. this.position.set(-1000,-1000,-100000);//令它看不见
  72206. this.mesh.renderOrder = 10;
  72207. this.overlayMesh.renderOrder = 11;
  72208. this.aimPos;
  72209. Potree.Utils.setObjectLayers(this, 'magnifier' );
  72210. //viewer.inputHandler.addInputListener(this)
  72211. viewer.addEventListener('camera_changed',(e)=>{ // 平移、滚轮时更新
  72212. if(e.viewport == viewer.mainViewport) this.update(); //不过intersectPoint没更新
  72213. });
  72214. this.mesh.layers.set(Potree.config.renderLayers.magnifier);
  72215. this.overlayMesh.layers.set(Potree.config.renderLayers.magnifier);
  72216. //this.layers.set(Potree.config.renderLayers.magnifier);//这句在外层写没用
  72217. this.dontRender = false;
  72218. viewer.addEventListener('global_drag', (e)=>{//拖拽时不渲染。主要是右键平移时渲染延迟了,会闪烁。
  72219. this.dontRender = true;
  72220. });
  72221. viewer.addEventListener('global_drop', (e)=>{
  72222. this.dontRender = false;
  72223. });
  72224. viewer.addEventListener('global_mouseup', (e)=>{//测量时拖拽场景再mouseup
  72225. this.dontRender = false;
  72226. });
  72227. viewer.addEventListener('global_touchstart', (e)=>{
  72228. this.update(e.intersect && e.intersect.location);
  72229. });
  72230. viewer.addEventListener('getIntersect', (e)=>{ //包括用sdk获取的,不会记录在inputHandler中的
  72231. if(e.intersect){
  72232. this.currentAim = e.intersect.location;
  72233. this.update(this.currentAim);
  72234. }
  72235. });
  72236. this.addEventListener("setEnable",(e)=>{
  72237. Potree.Utils.updateVisible(this, "enable", e.value, 1, e.value?'add':'cancel' ); //界面开关
  72238. });
  72239. //默认隐藏, 显示的条件:测量拖拽 或 外部消息setEnable
  72240. Potree.Utils.updateVisible(this, "default", false, 0); //默认隐藏
  72241. viewer.addEventListener("dragMarker",(e)=>{//测量drag
  72242. Potree.Utils.updateVisible(this, "measure", true, 1, 'add' );
  72243. });
  72244. viewer.addEventListener("dropMarker",(e)=>{//测量drag
  72245. Potree.Utils.updateVisible(this, "measure", false, 1, 'cancel' );
  72246. });
  72247. this.addEventListener('isVisible',(e)=>{
  72248. //console.warn('isVisible', e)
  72249. this.currentAim && this.update(this.currentAim);
  72250. viewer.dispatchEvent('content_changed');
  72251. });
  72252. viewer.scene.view.addEventListener('flyingDone',()=>{
  72253. if(!this.visible)return
  72254. let pickWindowSize = 100;
  72255. let intersect = viewer.inputHandler.getIntersect(viewer.mainViewport, viewer.mainViewport.camera, true, pickWindowSize );
  72256. this.update(intersect && intersect.location);
  72257. });
  72258. }
  72259. //注意:在鼠标没有移动的时候,无法获取到最新的intersect, 放大镜内的内容可能是错误的。全景模式下更奇怪,原因未知
  72260. update(aimPos){//相机靠近 navvis的做法
  72261. var dontRender = this.dontRender || !(aimPos instanceof Vector3) || Potree.settings.displayMode == 'showPanos' && viewer.images360.flying;
  72262. aimPos = aimPos instanceof Vector3 ? aimPos : this.aimPos;
  72263. if(!aimPos || !this.visible)return
  72264. //console.log('aimPos', aimPos)
  72265. var playerCamera = viewer.scene.getActiveCamera();
  72266. var playerPos = playerCamera.position;//viewer.scene.view.getPivot()
  72267. var dis = playerPos.distanceTo(aimPos);
  72268. var dirToCamera = new Vector3().subVectors(playerPos, aimPos ).normalize();
  72269. const fareast = 300;
  72270. //相机位置
  72271. if(playerCamera.type == 'OrthographicCamera'){
  72272. var finalDisToAim = 2;
  72273. }else {
  72274. var finalDisToAim = dis>magDisMin ? dis > fareast ? magDisMax : (dis-magDisMin) / (fareast-magDisMin) * (magDisMax-magDisMin) + magDisMin : dis / 2; //dis>magDistance_ ? magDistance_ : dis / 2;
  72275. }
  72276. this.camera.fov = playerCamera.type == 'OrthographicCamera' ? 30 : playerCamera.fov / 2;
  72277. this.camera.updateProjectionMatrix();
  72278. if(playerCamera.type == 'OrthographicCamera'){
  72279. orthoView.position.copy(aimPos).sub(viewer.mainViewport.view.direction.multiplyScalar(finalDisToAim));
  72280. orthoView.yaw = viewer.mainViewport.view.yaw;
  72281. orthoView.pitch = viewer.mainViewport.view.pitch;
  72282. orthoView.applyToCamera(this.camera);
  72283. }else {
  72284. this.camera.position.copy(aimPos).add(dirToCamera.multiplyScalar(finalDisToAim));
  72285. this.camera.lookAt(aimPos);
  72286. }
  72287. //自身位置
  72288. //let pos2d = viewer.inputHandler.pointer.clone(); //跟随鼠标
  72289. let pos2d = Potree.Utils.getPos2d(aimPos, playerCamera, viewer.renderArea, viewer.mainViewport).vector; //更新目标点的实时二维位置
  72290. let margin = 0.4, maxY = 0.4;
  72291. let screenPos = pos2d.clone().setY(pos2d.y + (pos2d.y>maxY ? -margin : margin ));
  72292. let newPos = new Vector3(screenPos.x,screenPos.y,0.8).unproject(playerCamera); //z:-1朝外
  72293. if(playerCamera.type != 'OrthographicCamera'){
  72294. let dir = newPos.clone().sub(playerPos).normalize().multiplyScalar(10);//这个数值要大于playerCamera.near
  72295. this.position.copy(playerPos.clone().add(dir));
  72296. }else {
  72297. viewer.splitScreen.setShiftTarget(viewer.mainViewport, viewer.bound.center);
  72298. viewer.mainViewport.targetPlane.setFromNormalAndCoplanarPoint( viewer.mainViewport.view.direction.clone(), viewer.bound.center );
  72299. viewer.mainViewport.targetPlane.projectPoint(newPos, viewer.mainViewport.shiftTarget );
  72300. this.position.copy(viewer.mainViewport.shiftTarget.clone() );
  72301. //this.position.copy(playerPos.clone().add(dir))
  72302. }
  72303. let s = finalDisToAim;
  72304. this.quaternion.copy(playerCamera.quaternion);
  72305. this.targetPoint.position.copy(aimPos);
  72306. this.targetPoint.scale.set(s,s,s);
  72307. this.aimPos = aimPos;
  72308. var scale = math.getScaleForConstantSize({//
  72309. width2d : width2dPX,
  72310. camera:viewer.scene.getActiveCamera(), position: this.getWorldPosition(new Vector3()),
  72311. resolution: viewer.mainViewport.resolution2
  72312. });
  72313. this.scale.set(scale, scale, scale);
  72314. if(!dontRender){
  72315. this.waitRender = true;
  72316. }
  72317. viewer.dispatchEvent('content_changed');
  72318. }
  72319. /* update(aimPos){ //仅改fov的版本
  72320. aimPos = aimPos instanceof THREE.Vector3 ? aimPos : this.aimPos
  72321. if(!aimPos || !this.visible)return
  72322. //相机位置
  72323. var playerCamera = viewer.scene.getActiveCamera()
  72324. var playerPos = playerCamera.position;//viewer.scene.view.getPivot()
  72325. var dis = playerPos.distanceTo(aimPos);
  72326. if(dis<magDisMin){
  72327. this.camera.fov = maxFov
  72328. }else{
  72329. this.camera.fov = THREE.Math.radToDeg(Math.atan(radius_ / dis )) * 2 //radius_是能看到的范围半径。当dis大于magDisMin时就放大,否则维持fov为maxFov
  72330. }
  72331. this.camera.updateProjectionMatrix()
  72332. this.camera.position.copy(playerPos)
  72333. this.camera.lookAt(aimPos)
  72334. this.quaternion.copy(playerCamera.quaternion);
  72335. let pointer = viewer.inputHandler.pointer.clone();
  72336. let margin = 0.4, maxY = 0.4
  72337. let screenPos = pointer.clone().setY(pointer.y + (pointer.y>maxY ? -margin : margin ))
  72338. let newPos = new THREE.Vector3(screenPos.x,screenPos.y,0.8).unproject(playerCamera); //z:-1朝外
  72339. let dir = newPos.clone().sub(playerPos).normalize().multiplyScalar(10);//这个数值要大于playerCamera.near
  72340. this.position.copy(playerPos.clone().add(dir))
  72341. this.aimPos = aimPos
  72342. this.targetPoint.position.copy(aimPos);
  72343. var scale = math.getScaleForConstantSize({//
  72344. width2d : width2dPX,
  72345. camera:viewer.scene.getActiveCamera(), position: this.getWorldPosition(new THREE.Vector3()),
  72346. resolution: viewer.mainViewport.resolution2
  72347. })
  72348. this.scale.set(scale, scale, scale);
  72349. if(!this.dontRender){
  72350. this.waitRender = true
  72351. }
  72352. }//位置需要计算,不仅仅是点云,所以需要深度图
  72353. */
  72354. render(){
  72355. if(!this.visible || !this.waitRender && !viewer.needRender)return //viewer.needRender为true要渲染是因为可能是点云node加载完
  72356. viewer.render({
  72357. target : this.renderTarget,
  72358. viewports : [this.viewport],
  72359. camera : this.camera,
  72360. magnifier : true,
  72361. rtEDL: this.rtEDL
  72362. /* width :this.renderTarget.width,
  72363. height: this.renderTarget.height, */
  72364. });
  72365. this.waitRender = false;
  72366. viewer.dispatchEvent('content_changed');
  72367. }
  72368. }
  72369. let texLoader$8 = new TextureLoader();
  72370. let defaultOpacity = 0.7;
  72371. let Buttons$1 = Potree.defines.Buttons;
  72372. //鼠标指示小圆片
  72373. class Reticule extends Mesh{
  72374. constructor(viewer){
  72375. var defaultTex = texLoader$8.load(Potree.resourcePath+'/textures/whiteCircle.png'/* reticule-256x256.png' */);
  72376. super(new PlaneBufferGeometry(0.11,0.11,1,1),new MeshBasicMaterial({
  72377. side: DoubleSide ,
  72378. map: defaultTex,
  72379. transparent:true,
  72380. depthTest: !1,
  72381. opacity: defaultOpacity,
  72382. //depthWrite: !1,
  72383. }));
  72384. this.name = 'reticule';
  72385. this.defaultTex = defaultTex;
  72386. this.crosshairTex = texLoader$8.load(Potree.resourcePath+'/textures/reticule_cross_hair.png');
  72387. this.forbitTex = texLoader$8.load(Potree.resourcePath+'/textures/pic-forbid.png');
  72388. this.defaultTex.anisotropy = 4;
  72389. this.crosshairTex.anisotropy = 4;
  72390. this.forbitTex.anisotropy = 4;
  72391. //this.layers.set(0/* RenderLayers.RETICULE */);
  72392. this.renderOrder = 100;
  72393. this.layers.set(Potree.config.renderLayers.marker);
  72394. this.direction = new Vector3;
  72395. this.mouseLastMoveTime = Date.now();
  72396. this.hoverViewport;
  72397. this.matrixMap = new Map;
  72398. this.matrixAutoUpdate = false;
  72399. this.hide(0);
  72400. //viewer.inputHandler.addInputListener(this);
  72401. Potree.settings.intersectWhenHover && viewer.addEventListener('global_mousemove',this.move.bind(this));
  72402. //viewer.addEventListener('global_click',this.move.bind(this))
  72403. viewer.addEventListener('global_mousedown',this.move.bind(this));//主要针对触屏
  72404. this.state = {};
  72405. let startCrossStyle = ()=>{
  72406. this.state.cross = true;
  72407. this.judgeTex();
  72408. };
  72409. let endCrossStyle = ()=>{
  72410. this.state.cross = false;
  72411. this.judgeTex();
  72412. };
  72413. viewer.addEventListener('measureMovePoint',startCrossStyle);
  72414. viewer.addEventListener('endMeasureMove',endCrossStyle);
  72415. viewer.addEventListener('start_inserting_tag',startCrossStyle);
  72416. viewer.addEventListener('endTagMove',endCrossStyle);
  72417. viewer.addEventListener('reticule_forbit',(e)=>{
  72418. /* if(this.state.forbit != e.v){
  72419. console.log('change forbit ',e.v)
  72420. } */
  72421. this.state.forbit = e.v;
  72422. this.judgeTex();
  72423. });
  72424. Potree.Utils.setObjectLayers(this, 'sceneObjects' );
  72425. }
  72426. judgeTex(){
  72427. if(this.state.forbit){
  72428. this.material.map = this.forbitTex;
  72429. }else if(this.state.cross){
  72430. this.material.map = this.crosshairTex;
  72431. }else {
  72432. this.material.map = this.defaultTex;
  72433. }
  72434. viewer.mapViewer && viewer.mapViewer.dispatchEvent({type:'content_changed'});
  72435. }
  72436. move(e){
  72437. if(e.type == "global_mousemove" && (e.isTouch || e.buttons != Buttons$1.NONE) && this.state != 'crosshair'){
  72438. return//按下时不更新,除非拖拽测量
  72439. }
  72440. this.mouseLastMoveTime = Date.now();
  72441. this.updatePosition(e.intersect, e.hoverViewport);
  72442. }
  72443. hide(duration = 500){
  72444. if(this.hidden)return
  72445. this.hidden = !0;
  72446. transitions.start(lerp.property(this.material , "opacity", 0, ()=>{//progress
  72447. viewer.dispatchEvent('content_changed');
  72448. }), duration,()=>{//done
  72449. this.dispatchEvent({type:'update', visible:false});
  72450. });
  72451. this.dispatchEvent({type:'update', visible:false});
  72452. setTimeout(()=>{
  72453. },duration);
  72454. }
  72455. show(duration = 300){
  72456. if(!Potree.Utils.getObjVisiByReason(this, 'force'))return
  72457. //console.log("show Reticule")
  72458. this.hidden = !1;
  72459. if(this.material.opacity <= 0){
  72460. transitions.start(lerp.property(this.material, "opacity", defaultOpacity, ()=>{//progress
  72461. viewer.dispatchEvent('content_changed');
  72462. }), duration,()=>{//done
  72463. this.dispatchEvent({type:'update', visible:false});
  72464. });
  72465. this.dispatchEvent({type:'update', visible:true});
  72466. }
  72467. }
  72468. //鼠标静止一段时间它就会消失
  72469. updateVisible(){
  72470. Date.now() - this.mouseLastMoveTime > 1500 && !this.hidden && this.hide();
  72471. }
  72472. updateScale(viewport){
  72473. let s, camera = viewport.camera;
  72474. if(camera.type == "OrthographicCamera"){
  72475. var sizeInfo = this.state.cross ? {width2d:500} : {minSize : 100, maxSize : 400, nearBound : 100 , farBound : 700};
  72476. s = math.getScaleForConstantSize($.extend( sizeInfo ,
  72477. {position:this.position, camera, resolution:viewport.resolution/* 2 */} ));
  72478. }else {
  72479. let n = camera.position.distanceTo(this.position);
  72480. s = 1 + .1 * n;
  72481. n < 1 && (s -= 1 - n);
  72482. }
  72483. this.scale.set(s, s, s);
  72484. }
  72485. updateAtViewports(viewport){//当多个viewports时更新。更新大小等
  72486. if(viewport.name == 'magnifier' )return
  72487. if(this.orthoPos && this.hoverViewport && this.hoverViewport.name == 'mapViewport' && viewport != this.hoverViewport){
  72488. //若是在地图上更新,在其他viewport要隐藏。因为在地图上无法得知高度。
  72489. Potree.Utils.updateVisible(this, 'hoverMap', false);
  72490. return;
  72491. }
  72492. Potree.Utils.updateVisible(this, 'hoverMap', true);
  72493. if(viewport.name == 'mapViewport'){
  72494. Potree.Utils.setObjectLayers(this, "bothMapAndScene");
  72495. }else {//通常地图不显示reticule,只有在特殊编辑时才显示
  72496. Potree.Utils.setObjectLayers(this, 'sceneObjects');
  72497. }
  72498. var matrix = this.matrixMap.get(viewport);
  72499. if(!matrix){
  72500. this.updateScale(viewport);
  72501. this.updateMatrix();
  72502. //this.updateMatrixWorld()
  72503. this.matrixMap.set(viewport, this.matrix.clone());
  72504. }else {
  72505. this.matrix.copy(matrix);
  72506. //this.updateMatrixWorld()
  72507. }
  72508. }
  72509. updatePosition(intersect, viewport ){ //在地图(当地图融合到viewer时)和场景里都显示且完全相同(大小可能不同)
  72510. if (Potree.Utils.getObjVisiByReason(this, 'force')) {//没有被强制隐藏,如进入某个页面后强制不显示
  72511. if (!intersect /* || !intersect.point.normal */){
  72512. return //this.hide();
  72513. }
  72514. let location = intersect.location; //|| intersect.orthoIntersect.clone()
  72515. let normal;
  72516. if(!location)return
  72517. this.show( 300);
  72518. normal = intersect.normal;
  72519. if(normal){
  72520. let ratio = /* Potree.settings.useDepthTex ? 1 : */ 0.2;
  72521. this.direction = this.direction.multiplyScalar(1-ratio);
  72522. this.direction.add(normal.clone().multiplyScalar(ratio));
  72523. }
  72524. this.position.copy(location);/* .add(normal.clone().multiplyScalar(.01)); */
  72525. this.updateMatrix(); //lookAt之前要保证得到matrix
  72526. this.lookAt(this.position.clone().add(this.direction));
  72527. this.hoverViewport = viewport; //记录下最近一次hover过的viewport
  72528. this.updateScale(viewport);
  72529. {//存储matrix,节省计算
  72530. this.updateMatrix();
  72531. //this.updateMatrixWorld()
  72532. this.matrixMap.clear();//重新计算
  72533. this.matrixMap.set(viewport, this.matrix.clone());
  72534. //别处会updateMatrixWorld
  72535. }
  72536. this.dispatchEvent({type:'update'});
  72537. //为什么navvis在校准数据集时每个viewport里reticule的朝向都刚好垂直于屏幕,似乎限定在了一定范围内,还是在pick时就只pick范围内的点?
  72538. }
  72539. }
  72540. //navvis在地图等地方看reticule是有厚度的
  72541. /* updateMatrixWorld(force){
  72542. console.log('updateMatrixWorld', force)
  72543. super.updateMatrixWorld(force)
  72544. } */
  72545. }
  72546. var OBJLoader = ( function () {
  72547. // o object_name | g group_name
  72548. var object_pattern = /^[og]\s*(.+)?/;
  72549. // mtllib file_reference
  72550. var material_library_pattern = /^mtllib /;
  72551. // usemtl material_name
  72552. var material_use_pattern = /^usemtl /;
  72553. // usemap map_name
  72554. var map_use_pattern = /^usemap /;
  72555. var vA = new Vector3();
  72556. var vB = new Vector3();
  72557. var vC = new Vector3();
  72558. var ab = new Vector3();
  72559. var cb = new Vector3();
  72560. function ParserState() {
  72561. var state = {
  72562. objects: [],
  72563. object: {},
  72564. vertices: [],
  72565. normals: [],
  72566. colors: [],
  72567. uvs: [],
  72568. materials: {},
  72569. materialLibraries: [],
  72570. startObject: function ( name, fromDeclaration ) {
  72571. // If the current object (initial from reset) is not from a g/o declaration in the parsed
  72572. // file. We need to use it for the first parsed g/o to keep things in sync.
  72573. if ( this.object && this.object.fromDeclaration === false ) {
  72574. this.object.name = name;
  72575. this.object.fromDeclaration = ( fromDeclaration !== false );
  72576. return;
  72577. }
  72578. var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );
  72579. if ( this.object && typeof this.object._finalize === 'function' ) {
  72580. this.object._finalize( true );
  72581. }
  72582. this.object = {
  72583. name: name || '',
  72584. fromDeclaration: ( fromDeclaration !== false ),
  72585. geometry: {
  72586. vertices: [],
  72587. normals: [],
  72588. colors: [],
  72589. uvs: [],
  72590. hasUVIndices: false
  72591. },
  72592. materials: [],
  72593. smooth: true,
  72594. startMaterial: function ( name, libraries ) {
  72595. var previous = this._finalize( false );
  72596. // New usemtl declaration overwrites an inherited material, except if faces were declared
  72597. // after the material, then it must be preserved for proper MultiMaterial continuation.
  72598. if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
  72599. this.materials.splice( previous.index, 1 );
  72600. }
  72601. var material = {
  72602. index: this.materials.length,
  72603. name: name || '',
  72604. mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),
  72605. smooth: ( previous !== undefined ? previous.smooth : this.smooth ),
  72606. groupStart: ( previous !== undefined ? previous.groupEnd : 0 ),
  72607. groupEnd: - 1,
  72608. groupCount: - 1,
  72609. inherited: false,
  72610. clone: function ( index ) {
  72611. var cloned = {
  72612. index: ( typeof index === 'number' ? index : this.index ),
  72613. name: this.name,
  72614. mtllib: this.mtllib,
  72615. smooth: this.smooth,
  72616. groupStart: 0,
  72617. groupEnd: - 1,
  72618. groupCount: - 1,
  72619. inherited: false
  72620. };
  72621. cloned.clone = this.clone.bind( cloned );
  72622. return cloned;
  72623. }
  72624. };
  72625. this.materials.push( material );
  72626. return material;
  72627. },
  72628. currentMaterial: function () {
  72629. if ( this.materials.length > 0 ) {
  72630. return this.materials[ this.materials.length - 1 ];
  72631. }
  72632. return undefined;
  72633. },
  72634. _finalize: function ( end ) {
  72635. var lastMultiMaterial = this.currentMaterial();
  72636. if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {
  72637. lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
  72638. lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
  72639. lastMultiMaterial.inherited = false;
  72640. }
  72641. // Ignore objects tail materials if no face declarations followed them before a new o/g started.
  72642. if ( end && this.materials.length > 1 ) {
  72643. for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) {
  72644. if ( this.materials[ mi ].groupCount <= 0 ) {
  72645. this.materials.splice( mi, 1 );
  72646. }
  72647. }
  72648. }
  72649. // Guarantee at least one empty material, this makes the creation later more straight forward.
  72650. if ( end && this.materials.length === 0 ) {
  72651. this.materials.push( {
  72652. name: '',
  72653. smooth: this.smooth
  72654. } );
  72655. }
  72656. return lastMultiMaterial;
  72657. }
  72658. };
  72659. // Inherit previous objects material.
  72660. // Spec tells us that a declared material must be set to all objects until a new material is declared.
  72661. // If a usemtl declaration is encountered while this new object is being parsed, it will
  72662. // overwrite the inherited material. Exception being that there was already face declarations
  72663. // to the inherited material, then it will be preserved for proper MultiMaterial continuation.
  72664. if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
  72665. var declared = previousMaterial.clone( 0 );
  72666. declared.inherited = true;
  72667. this.object.materials.push( declared );
  72668. }
  72669. this.objects.push( this.object );
  72670. },
  72671. finalize: function () {
  72672. if ( this.object && typeof this.object._finalize === 'function' ) {
  72673. this.object._finalize( true );
  72674. }
  72675. },
  72676. parseVertexIndex: function ( value, len ) {
  72677. var index = parseInt( value, 10 );
  72678. return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
  72679. },
  72680. parseNormalIndex: function ( value, len ) {
  72681. var index = parseInt( value, 10 );
  72682. return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
  72683. },
  72684. parseUVIndex: function ( value, len ) {
  72685. var index = parseInt( value, 10 );
  72686. return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
  72687. },
  72688. addVertex: function ( a, b, c ) {
  72689. var src = this.vertices;
  72690. var dst = this.object.geometry.vertices;
  72691. dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
  72692. dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
  72693. dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
  72694. },
  72695. addVertexPoint: function ( a ) {
  72696. var src = this.vertices;
  72697. var dst = this.object.geometry.vertices;
  72698. dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
  72699. },
  72700. addVertexLine: function ( a ) {
  72701. var src = this.vertices;
  72702. var dst = this.object.geometry.vertices;
  72703. dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
  72704. },
  72705. addNormal: function ( a, b, c ) {
  72706. var src = this.normals;
  72707. var dst = this.object.geometry.normals;
  72708. dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
  72709. dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
  72710. dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
  72711. },
  72712. addFaceNormal: function ( a, b, c ) {
  72713. var src = this.vertices;
  72714. var dst = this.object.geometry.normals;
  72715. vA.fromArray( src, a );
  72716. vB.fromArray( src, b );
  72717. vC.fromArray( src, c );
  72718. cb.subVectors( vC, vB );
  72719. ab.subVectors( vA, vB );
  72720. cb.cross( ab );
  72721. cb.normalize();
  72722. dst.push( cb.x, cb.y, cb.z );
  72723. dst.push( cb.x, cb.y, cb.z );
  72724. dst.push( cb.x, cb.y, cb.z );
  72725. },
  72726. addColor: function ( a, b, c ) {
  72727. var src = this.colors;
  72728. var dst = this.object.geometry.colors;
  72729. if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
  72730. if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
  72731. if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
  72732. },
  72733. addUV: function ( a, b, c ) {
  72734. var src = this.uvs;
  72735. var dst = this.object.geometry.uvs;
  72736. dst.push( src[ a + 0 ], src[ a + 1 ] );
  72737. dst.push( src[ b + 0 ], src[ b + 1 ] );
  72738. dst.push( src[ c + 0 ], src[ c + 1 ] );
  72739. },
  72740. addDefaultUV: function () {
  72741. var dst = this.object.geometry.uvs;
  72742. dst.push( 0, 0 );
  72743. dst.push( 0, 0 );
  72744. dst.push( 0, 0 );
  72745. },
  72746. addUVLine: function ( a ) {
  72747. var src = this.uvs;
  72748. var dst = this.object.geometry.uvs;
  72749. dst.push( src[ a + 0 ], src[ a + 1 ] );
  72750. },
  72751. addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
  72752. var vLen = this.vertices.length;
  72753. var ia = this.parseVertexIndex( a, vLen );
  72754. var ib = this.parseVertexIndex( b, vLen );
  72755. var ic = this.parseVertexIndex( c, vLen );
  72756. this.addVertex( ia, ib, ic );
  72757. this.addColor( ia, ib, ic );
  72758. // normals
  72759. if ( na !== undefined && na !== '' ) {
  72760. var nLen = this.normals.length;
  72761. ia = this.parseNormalIndex( na, nLen );
  72762. ib = this.parseNormalIndex( nb, nLen );
  72763. ic = this.parseNormalIndex( nc, nLen );
  72764. this.addNormal( ia, ib, ic );
  72765. } else {
  72766. this.addFaceNormal( ia, ib, ic );
  72767. }
  72768. // uvs
  72769. if ( ua !== undefined && ua !== '' ) {
  72770. var uvLen = this.uvs.length;
  72771. ia = this.parseUVIndex( ua, uvLen );
  72772. ib = this.parseUVIndex( ub, uvLen );
  72773. ic = this.parseUVIndex( uc, uvLen );
  72774. this.addUV( ia, ib, ic );
  72775. this.object.geometry.hasUVIndices = true;
  72776. } else {
  72777. // add placeholder values (for inconsistent face definitions)
  72778. this.addDefaultUV();
  72779. }
  72780. },
  72781. addPointGeometry: function ( vertices ) {
  72782. this.object.geometry.type = 'Points';
  72783. var vLen = this.vertices.length;
  72784. for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {
  72785. var index = this.parseVertexIndex( vertices[ vi ], vLen );
  72786. this.addVertexPoint( index );
  72787. this.addColor( index );
  72788. }
  72789. },
  72790. addLineGeometry: function ( vertices, uvs ) {
  72791. this.object.geometry.type = 'Line';
  72792. var vLen = this.vertices.length;
  72793. var uvLen = this.uvs.length;
  72794. for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {
  72795. this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
  72796. }
  72797. for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
  72798. this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
  72799. }
  72800. }
  72801. };
  72802. state.startObject( '', false );
  72803. return state;
  72804. }
  72805. //
  72806. function OBJLoader( manager ) {
  72807. Loader.call( this, manager );
  72808. this.materials = null;
  72809. }
  72810. OBJLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  72811. constructor: OBJLoader,
  72812. load: function ( url, onLoad, onProgress, onError ) {
  72813. var scope = this;
  72814. var loader = new FileLoader( this.manager );
  72815. loader.setPath( this.path );
  72816. loader.setRequestHeader( this.requestHeader );
  72817. loader.setWithCredentials( this.withCredentials );
  72818. loader.load( url, function ( text , total ) {// xzw add total
  72819. try {
  72820. onLoad( scope.parse( text ) , total );
  72821. } catch ( e ) {
  72822. if ( onError ) {
  72823. onError( e );
  72824. } else {
  72825. console.error( e );
  72826. }
  72827. scope.manager.itemError( url );
  72828. }
  72829. }, onProgress, onError );
  72830. },
  72831. setMaterials: function ( materials ) {
  72832. this.materials = materials;
  72833. return this;
  72834. },
  72835. parse: function ( text ) {
  72836. var state = new ParserState();
  72837. if ( text.indexOf( '\r\n' ) !== - 1 ) {
  72838. // This is faster than String.split with regex that splits on both
  72839. text = text.replace( /\r\n/g, '\n' );
  72840. }
  72841. if ( text.indexOf( '\\\n' ) !== - 1 ) {
  72842. // join lines separated by a line continuation character (\)
  72843. text = text.replace( /\\\n/g, '' );
  72844. }
  72845. var lines = text.split( '\n' );
  72846. var line = '', lineFirstChar = '';
  72847. var lineLength = 0;
  72848. var result = [];
  72849. // Faster to just trim left side of the line. Use if available.
  72850. var trimLeft = ( typeof ''.trimLeft === 'function' );
  72851. for ( var i = 0, l = lines.length; i < l; i ++ ) {
  72852. line = lines[ i ];
  72853. line = trimLeft ? line.trimLeft() : line.trim();
  72854. lineLength = line.length;
  72855. if ( lineLength === 0 ) continue;
  72856. lineFirstChar = line.charAt( 0 );
  72857. // @todo invoke passed in handler if any
  72858. if ( lineFirstChar === '#' ) continue;
  72859. if ( lineFirstChar === 'v' ) {
  72860. var data = line.split( /\s+/ );
  72861. switch ( data[ 0 ] ) {
  72862. case 'v':
  72863. state.vertices.push(
  72864. parseFloat( data[ 1 ] ),
  72865. parseFloat( data[ 2 ] ),
  72866. parseFloat( data[ 3 ] )
  72867. );
  72868. if ( data.length >= 7 ) {
  72869. state.colors.push(
  72870. parseFloat( data[ 4 ] ),
  72871. parseFloat( data[ 5 ] ),
  72872. parseFloat( data[ 6 ] )
  72873. );
  72874. } else {
  72875. // if no colors are defined, add placeholders so color and vertex indices match
  72876. state.colors.push( undefined, undefined, undefined );
  72877. }
  72878. break;
  72879. case 'vn':
  72880. state.normals.push(
  72881. parseFloat( data[ 1 ] ),
  72882. parseFloat( data[ 2 ] ),
  72883. parseFloat( data[ 3 ] )
  72884. );
  72885. break;
  72886. case 'vt':
  72887. state.uvs.push(
  72888. parseFloat( data[ 1 ] ),
  72889. parseFloat( data[ 2 ] )
  72890. );
  72891. break;
  72892. }
  72893. } else if ( lineFirstChar === 'f' ) {
  72894. var lineData = line.substr( 1 ).trim();
  72895. var vertexData = lineData.split( /\s+/ );
  72896. var faceVertices = [];
  72897. // Parse the face vertex data into an easy to work with format
  72898. for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) {
  72899. var vertex = vertexData[ j ];
  72900. if ( vertex.length > 0 ) {
  72901. var vertexParts = vertex.split( '/' );
  72902. faceVertices.push( vertexParts );
  72903. }
  72904. }
  72905. // Draw an edge between the first vertex and all subsequent vertices to form an n-gon
  72906. var v1 = faceVertices[ 0 ];
  72907. for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
  72908. var v2 = faceVertices[ j ];
  72909. var v3 = faceVertices[ j + 1 ];
  72910. state.addFace(
  72911. v1[ 0 ], v2[ 0 ], v3[ 0 ],
  72912. v1[ 1 ], v2[ 1 ], v3[ 1 ],
  72913. v1[ 2 ], v2[ 2 ], v3[ 2 ]
  72914. );
  72915. }
  72916. } else if ( lineFirstChar === 'l' ) {
  72917. var lineParts = line.substring( 1 ).trim().split( ' ' );
  72918. var lineVertices = [], lineUVs = [];
  72919. if ( line.indexOf( '/' ) === - 1 ) {
  72920. lineVertices = lineParts;
  72921. } else {
  72922. for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) {
  72923. var parts = lineParts[ li ].split( '/' );
  72924. if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );
  72925. if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );
  72926. }
  72927. }
  72928. state.addLineGeometry( lineVertices, lineUVs );
  72929. } else if ( lineFirstChar === 'p' ) {
  72930. var lineData = line.substr( 1 ).trim();
  72931. var pointData = lineData.split( ' ' );
  72932. state.addPointGeometry( pointData );
  72933. } else if ( ( result = object_pattern.exec( line ) ) !== null ) {
  72934. // o object_name
  72935. // or
  72936. // g group_name
  72937. // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
  72938. // var name = result[ 0 ].substr( 1 ).trim();
  72939. var name = ( ' ' + result[ 0 ].substr( 1 ).trim() ).substr( 1 );
  72940. state.startObject( name );
  72941. } else if ( material_use_pattern.test( line ) ) {
  72942. // material
  72943. state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
  72944. } else if ( material_library_pattern.test( line ) ) {
  72945. // mtl file
  72946. state.materialLibraries.push( line.substring( 7 ).trim() );
  72947. } else if ( map_use_pattern.test( line ) ) {
  72948. // the line is parsed but ignored since the loader assumes textures are defined MTL files
  72949. // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
  72950. console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' );
  72951. } else if ( lineFirstChar === 's' ) {
  72952. result = line.split( ' ' );
  72953. // smooth shading
  72954. // @todo Handle files that have varying smooth values for a set of faces inside one geometry,
  72955. // but does not define a usemtl for each face set.
  72956. // This should be detected and a dummy material created (later MultiMaterial and geometry groups).
  72957. // This requires some care to not create extra material on each smooth value for "normal" obj files.
  72958. // where explicit usemtl defines geometry groups.
  72959. // Example asset: examples/models/obj/cerberus/Cerberus.obj
  72960. /*
  72961. * http://paulbourke.net/dataformats/obj/
  72962. * or
  72963. * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
  72964. *
  72965. * From chapter "Grouping" Syntax explanation "s group_number":
  72966. * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.
  72967. * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form
  72968. * surfaces, smoothing groups are either turned on or off; there is no difference between values greater
  72969. * than 0."
  72970. */
  72971. if ( result.length > 1 ) {
  72972. var value = result[ 1 ].trim().toLowerCase();
  72973. state.object.smooth = ( value !== '0' && value !== 'off' );
  72974. } else {
  72975. // ZBrush can produce "s" lines #11707
  72976. state.object.smooth = true;
  72977. }
  72978. var material = state.object.currentMaterial();
  72979. if ( material ) material.smooth = state.object.smooth;
  72980. } else {
  72981. // Handle null terminated files without exception
  72982. if ( line === '\0' ) continue;
  72983. console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' );
  72984. }
  72985. }
  72986. state.finalize();
  72987. var container = new Group();
  72988. container.materialLibraries = [].concat( state.materialLibraries );
  72989. var hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );
  72990. if ( hasPrimitives === true ) {
  72991. for ( var i = 0, l = state.objects.length; i < l; i ++ ) {
  72992. var object = state.objects[ i ];
  72993. var geometry = object.geometry;
  72994. var materials = object.materials;
  72995. var isLine = ( geometry.type === 'Line' );
  72996. var isPoints = ( geometry.type === 'Points' );
  72997. var hasVertexColors = false;
  72998. // Skip o/g line declarations that did not follow with any faces
  72999. if ( geometry.vertices.length === 0 ) continue;
  73000. var buffergeometry = new BufferGeometry();
  73001. buffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) );
  73002. if ( geometry.normals.length > 0 ) {
  73003. buffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) );
  73004. }
  73005. if ( geometry.colors.length > 0 ) {
  73006. hasVertexColors = true;
  73007. buffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) );
  73008. }
  73009. if ( geometry.hasUVIndices === true ) {
  73010. buffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) );
  73011. }
  73012. // Create materials
  73013. var createdMaterials = [];
  73014. for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
  73015. var sourceMaterial = materials[ mi ];
  73016. var materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;
  73017. var material = state.materials[ materialHash ];
  73018. if ( this.materials !== null ) {
  73019. material = this.materials.create( sourceMaterial.name );
  73020. // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
  73021. if ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) {
  73022. var materialLine = new LineBasicMaterial();
  73023. Material.prototype.copy.call( materialLine, material );
  73024. materialLine.color.copy( material.color );
  73025. material = materialLine;
  73026. } else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) {
  73027. var materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } );
  73028. Material.prototype.copy.call( materialPoints, material );
  73029. materialPoints.color.copy( material.color );
  73030. materialPoints.map = material.map;
  73031. material = materialPoints;
  73032. }
  73033. }
  73034. if ( material === undefined ) {
  73035. if ( isLine ) {
  73036. material = new LineBasicMaterial();
  73037. } else if ( isPoints ) {
  73038. material = new PointsMaterial( { size: 1, sizeAttenuation: false } );
  73039. } else {
  73040. material = new MeshPhongMaterial();
  73041. }
  73042. material.name = sourceMaterial.name;
  73043. material.flatShading = sourceMaterial.smooth ? false : true;
  73044. material.vertexColors = hasVertexColors;
  73045. state.materials[ materialHash ] = material;
  73046. }
  73047. createdMaterials.push( material );
  73048. }
  73049. // Create mesh
  73050. var mesh;
  73051. if ( createdMaterials.length > 1 ) {
  73052. for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
  73053. var sourceMaterial = materials[ mi ];
  73054. buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
  73055. }
  73056. if ( isLine ) {
  73057. mesh = new LineSegments( buffergeometry, createdMaterials );
  73058. } else if ( isPoints ) {
  73059. mesh = new Points( buffergeometry, createdMaterials );
  73060. } else {
  73061. mesh = new Mesh( buffergeometry, createdMaterials );
  73062. }
  73063. } else {
  73064. if ( isLine ) {
  73065. mesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] );
  73066. } else if ( isPoints ) {
  73067. mesh = new Points( buffergeometry, createdMaterials[ 0 ] );
  73068. } else {
  73069. mesh = new Mesh( buffergeometry, createdMaterials[ 0 ] );
  73070. }
  73071. }
  73072. mesh.name = object.name;
  73073. container.add( mesh );
  73074. }
  73075. } else {
  73076. // if there is only the default parser state object with no geometry data, interpret data as point cloud
  73077. if ( state.vertices.length > 0 ) {
  73078. var material = new PointsMaterial( { size: 1, sizeAttenuation: false } );
  73079. var buffergeometry = new BufferGeometry();
  73080. buffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) );
  73081. if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {
  73082. buffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) );
  73083. material.vertexColors = true;
  73084. }
  73085. var points = new Points( buffergeometry, material );
  73086. container.add( points );
  73087. }
  73088. }
  73089. return container;
  73090. }
  73091. } );
  73092. return OBJLoader;
  73093. } )();
  73094. /**
  73095. * Loads a Wavefront .mtl file specifying materials
  73096. */
  73097. var MTLLoader = function ( manager ) {
  73098. Loader.call( this, manager );
  73099. };
  73100. MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  73101. constructor: MTLLoader,
  73102. /**
  73103. * Loads and parses a MTL asset from a URL.
  73104. *
  73105. * @param {String} url - URL to the MTL file.
  73106. * @param {Function} [onLoad] - Callback invoked with the loaded object.
  73107. * @param {Function} [onProgress] - Callback for download progress.
  73108. * @param {Function} [onError] - Callback for download errors.
  73109. *
  73110. * @see setPath setResourcePath
  73111. *
  73112. * @note In order for relative texture references to resolve correctly
  73113. * you must call setResourcePath() explicitly prior to load.
  73114. */
  73115. load: function ( url, onLoad, onProgress, onError ) {
  73116. var scope = this;
  73117. var path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
  73118. var loader = new FileLoader( this.manager );
  73119. loader.setPath( this.path );
  73120. loader.setRequestHeader( this.requestHeader );
  73121. loader.setWithCredentials( this.withCredentials );
  73122. loader.load( url, function ( text ) {
  73123. try {
  73124. onLoad( scope.parse( text, path ) );
  73125. } catch ( e ) {
  73126. if ( onError ) {
  73127. onError( e );
  73128. } else {
  73129. console.error( e );
  73130. }
  73131. scope.manager.itemError( url );
  73132. }
  73133. }, onProgress, onError );
  73134. },
  73135. setMaterialOptions: function ( value ) {
  73136. this.materialOptions = value;
  73137. return this;
  73138. },
  73139. /**
  73140. * Parses a MTL file.
  73141. *
  73142. * @param {String} text - Content of MTL file
  73143. * @return {MTLLoader.MaterialCreator}
  73144. *
  73145. * @see setPath setResourcePath
  73146. *
  73147. * @note In order for relative texture references to resolve correctly
  73148. * you must call setResourcePath() explicitly prior to parse.
  73149. */
  73150. parse: function ( text, path ) {
  73151. var lines = text.split( '\n' );
  73152. var info = {};
  73153. var delimiter_pattern = /\s+/;
  73154. var materialsInfo = {};
  73155. for ( var i = 0; i < lines.length; i ++ ) {
  73156. var line = lines[ i ];
  73157. line = line.trim();
  73158. if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
  73159. // Blank line or comment ignore
  73160. continue;
  73161. }
  73162. var pos = line.indexOf( ' ' );
  73163. var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
  73164. key = key.toLowerCase();
  73165. var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
  73166. value = value.trim();
  73167. if ( key === 'newmtl' ) {
  73168. // New material
  73169. info = { name: value };
  73170. materialsInfo[ value ] = info;
  73171. } else {
  73172. if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) {
  73173. var ss = value.split( delimiter_pattern, 3 );
  73174. info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
  73175. } else {
  73176. info[ key ] = value;
  73177. }
  73178. }
  73179. }
  73180. var materialCreator = new MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions );
  73181. materialCreator.setCrossOrigin( this.crossOrigin );
  73182. materialCreator.setManager( this.manager );
  73183. materialCreator.setMaterials( materialsInfo );
  73184. return materialCreator;
  73185. }
  73186. } );
  73187. /**
  73188. * Create a new MTLLoader.MaterialCreator
  73189. * @param baseUrl - Url relative to which textures are loaded
  73190. * @param options - Set of options on how to construct the materials
  73191. * side: Which side to apply the material
  73192. * FrontSide (default), THREE.BackSide, THREE.DoubleSide
  73193. * wrap: What type of wrapping to apply for textures
  73194. * RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
  73195. * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
  73196. * Default: false, assumed to be already normalized
  73197. * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
  73198. * Default: false
  73199. * @constructor
  73200. */
  73201. MTLLoader.MaterialCreator = function ( baseUrl, options ) {
  73202. this.baseUrl = baseUrl || '';
  73203. this.options = options;
  73204. this.materialsInfo = {};
  73205. this.materials = {};
  73206. this.materialsArray = [];
  73207. this.nameLookup = {};
  73208. this.side = ( this.options && this.options.side ) ? this.options.side : FrontSide;
  73209. this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : RepeatWrapping;
  73210. };
  73211. MTLLoader.MaterialCreator.prototype = {
  73212. constructor: MTLLoader.MaterialCreator,
  73213. crossOrigin: 'anonymous',
  73214. setCrossOrigin: function ( value ) {
  73215. this.crossOrigin = value;
  73216. return this;
  73217. },
  73218. setManager: function ( value ) {
  73219. this.manager = value;
  73220. },
  73221. setMaterials: function ( materialsInfo ) {
  73222. this.materialsInfo = this.convert( materialsInfo );
  73223. this.materials = {};
  73224. this.materialsArray = [];
  73225. this.nameLookup = {};
  73226. },
  73227. convert: function ( materialsInfo ) {
  73228. if ( ! this.options ) return materialsInfo;
  73229. var converted = {};
  73230. for ( var mn in materialsInfo ) {
  73231. // Convert materials info into normalized form based on options
  73232. var mat = materialsInfo[ mn ];
  73233. var covmat = {};
  73234. converted[ mn ] = covmat;
  73235. for ( var prop in mat ) {
  73236. var save = true;
  73237. var value = mat[ prop ];
  73238. var lprop = prop.toLowerCase();
  73239. switch ( lprop ) {
  73240. case 'kd':
  73241. case 'ka':
  73242. case 'ks':
  73243. // Diffuse color (color under white light) using RGB values
  73244. if ( this.options && this.options.normalizeRGB ) {
  73245. value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];
  73246. }
  73247. if ( this.options && this.options.ignoreZeroRGBs ) {
  73248. if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {
  73249. // ignore
  73250. save = false;
  73251. }
  73252. }
  73253. break;
  73254. default:
  73255. break;
  73256. }
  73257. if ( save ) {
  73258. covmat[ lprop ] = value;
  73259. }
  73260. }
  73261. }
  73262. return converted;
  73263. },
  73264. preload: function () {
  73265. for ( var mn in this.materialsInfo ) {
  73266. this.create( mn );
  73267. }
  73268. },
  73269. getIndex: function ( materialName ) {
  73270. return this.nameLookup[ materialName ];
  73271. },
  73272. getAsArray: function () {
  73273. var index = 0;
  73274. for ( var mn in this.materialsInfo ) {
  73275. this.materialsArray[ index ] = this.create( mn );
  73276. this.nameLookup[ mn ] = index;
  73277. index ++;
  73278. }
  73279. return this.materialsArray;
  73280. },
  73281. create: function ( materialName ) {
  73282. if ( this.materials[ materialName ] === undefined ) {
  73283. this.createMaterial_( materialName );
  73284. }
  73285. return this.materials[ materialName ];
  73286. },
  73287. createMaterial_: function ( materialName ) {
  73288. // Create material
  73289. var scope = this;
  73290. var mat = this.materialsInfo[ materialName ];
  73291. var params = {
  73292. name: materialName,
  73293. side: this.side
  73294. };
  73295. function resolveURL( baseUrl, url ) {
  73296. if ( typeof url !== 'string' || url === '' )
  73297. return '';
  73298. // Absolute URL
  73299. if ( /^https?:\/\//i.test( url ) ) return url;
  73300. return baseUrl + url;
  73301. }
  73302. function setMapForType( mapType, value ) {
  73303. if ( params[ mapType ] ) return; // Keep the first encountered texture
  73304. var texParams = scope.getTextureParams( value, params );
  73305. var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );
  73306. map.repeat.copy( texParams.scale );
  73307. map.offset.copy( texParams.offset );
  73308. map.wrapS = scope.wrap;
  73309. map.wrapT = scope.wrap;
  73310. params[ mapType ] = map;
  73311. }
  73312. for ( var prop in mat ) {
  73313. var value = mat[ prop ];
  73314. var n;
  73315. if ( value === '' ) continue;
  73316. switch ( prop.toLowerCase() ) {
  73317. // Ns is material specular exponent
  73318. case 'kd':
  73319. // Diffuse color (color under white light) using RGB values
  73320. params.color = new Color().fromArray( value );
  73321. break;
  73322. case 'ks':
  73323. // Specular color (color when light is reflected from shiny surface) using RGB values
  73324. //params.specular = new Color().fromArray( value );
  73325. //console.log('specular',value)
  73326. break;
  73327. case 'ke':
  73328. // Emissive using RGB values
  73329. params.emissive = new Color().fromArray( value );
  73330. break;
  73331. case 'map_kd':
  73332. // Diffuse texture map
  73333. setMapForType( 'map', value );
  73334. break;
  73335. case 'map_ks':
  73336. // Specular map
  73337. setMapForType( 'specularMap', value );
  73338. break;
  73339. case 'map_ke':
  73340. // Emissive map
  73341. setMapForType( 'emissiveMap', value );
  73342. break;
  73343. case 'norm':
  73344. setMapForType( 'normalMap', value );
  73345. break;
  73346. case 'map_bump':
  73347. case 'bump':
  73348. // Bump texture map
  73349. setMapForType( 'bumpMap', value );
  73350. break;
  73351. case 'map_d':
  73352. // Alpha map
  73353. setMapForType( 'alphaMap', value );
  73354. params.transparent = true;
  73355. break;
  73356. case 'ns':
  73357. // The specular exponent (defines the focus of the specular highlight)
  73358. // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
  73359. //params.shininess = parseFloat( value );
  73360. //console.log('shininess',value)
  73361. break;
  73362. case 'd':
  73363. n = parseFloat( value );
  73364. if ( n < 1 ) {
  73365. params.opacity = n;
  73366. params.transparent = true;
  73367. }
  73368. break;
  73369. case 'tr':
  73370. n = parseFloat( value );
  73371. if ( this.options && this.options.invertTrProperty ) n = 1 - n;
  73372. if ( n > 0 ) {
  73373. params.opacity = 1 - n;
  73374. params.transparent = true;
  73375. }
  73376. break;
  73377. default:
  73378. break;
  73379. }
  73380. }
  73381. this.materials[ materialName ] = new MeshStandardMaterial( params );//MeshPhongMaterial( params );
  73382. return this.materials[ materialName ];
  73383. },
  73384. getTextureParams: function ( value, matParams ) {
  73385. var texParams = {
  73386. scale: new Vector2( 1, 1 ),
  73387. offset: new Vector2( 0, 0 )
  73388. };
  73389. var items = value.split( /\s+/ );
  73390. var pos;
  73391. pos = items.indexOf( '-bm' );
  73392. if ( pos >= 0 ) {
  73393. matParams.bumpScale = parseFloat( items[ pos + 1 ] );
  73394. items.splice( pos, 2 );
  73395. }
  73396. pos = items.indexOf( '-s' );
  73397. if ( pos >= 0 ) {
  73398. texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
  73399. items.splice( pos, 4 ); // we expect 3 parameters here!
  73400. }
  73401. pos = items.indexOf( '-o' );
  73402. if ( pos >= 0 ) {
  73403. texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
  73404. items.splice( pos, 4 ); // we expect 3 parameters here!
  73405. }
  73406. texParams.url = items.join( ' ' ).trim();
  73407. return texParams;
  73408. },
  73409. loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
  73410. var texture;
  73411. var manager = ( this.manager !== undefined ) ? this.manager : DefaultLoadingManager;
  73412. var loader = manager.getHandler( url );
  73413. if ( loader === null ) {
  73414. loader = new TextureLoader( manager );
  73415. }
  73416. if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
  73417. texture = loader.load( url, onLoad, onProgress, onError );
  73418. if ( mapping !== undefined ) texture.mapping = mapping;
  73419. return texture;
  73420. }
  73421. };
  73422. //2022.11.11 copyfrom : https://unpkg.com/three@0.146.0/examples/jsm/loaders/DRACOLoader.js
  73423. const _taskCache = new WeakMap();
  73424. class DRACOLoader extends Loader {
  73425. constructor( manager ) {
  73426. super( manager );
  73427. this.decoderPath = '';
  73428. this.decoderConfig = {};
  73429. this.decoderBinary = null;
  73430. this.decoderPending = null;
  73431. this.workerLimit = 4;
  73432. this.workerPool = [];
  73433. this.workerNextTaskID = 1;
  73434. this.workerSourceURL = '';
  73435. this.defaultAttributeIDs = {
  73436. position: 'POSITION',
  73437. normal: 'NORMAL',
  73438. color: 'COLOR',
  73439. uv: 'TEX_COORD'
  73440. };
  73441. this.defaultAttributeTypes = {
  73442. position: 'Float32Array',
  73443. normal: 'Float32Array',
  73444. color: 'Float32Array',
  73445. uv: 'Float32Array'
  73446. };
  73447. }
  73448. setDecoderPath( path ) {
  73449. this.decoderPath = path;
  73450. return this;
  73451. }
  73452. setDecoderConfig( config ) {
  73453. this.decoderConfig = config;
  73454. return this;
  73455. }
  73456. setWorkerLimit( workerLimit ) {
  73457. this.workerLimit = workerLimit;
  73458. return this;
  73459. }
  73460. load( url, onLoad, onProgress, onError ) {
  73461. const loader = new FileLoader( this.manager );
  73462. loader.setPath( this.path );
  73463. loader.setResponseType( 'arraybuffer' );
  73464. loader.setRequestHeader( this.requestHeader );
  73465. loader.setWithCredentials( this.withCredentials );
  73466. loader.load( url, ( buffer ) => {
  73467. this.decodeDracoFile( buffer, onLoad ).catch( onError );
  73468. }, onProgress, onError );
  73469. }
  73470. decodeDracoFile( buffer, callback, attributeIDs, attributeTypes ) {
  73471. const taskConfig = {
  73472. attributeIDs: attributeIDs || this.defaultAttributeIDs,
  73473. attributeTypes: attributeTypes || this.defaultAttributeTypes,
  73474. useUniqueIDs: !! attributeIDs
  73475. };
  73476. return this.decodeGeometry( buffer, taskConfig ).then( callback );
  73477. }
  73478. decodeGeometry( buffer, taskConfig ) {
  73479. const taskKey = JSON.stringify( taskConfig );
  73480. // Check for an existing task using this buffer. A transferred buffer cannot be transferred
  73481. // again from this thread.
  73482. if ( _taskCache.has( buffer ) ) {
  73483. const cachedTask = _taskCache.get( buffer );
  73484. if ( cachedTask.key === taskKey ) {
  73485. return cachedTask.promise;
  73486. } else if ( buffer.byteLength === 0 ) {
  73487. // Technically, it would be possible to wait for the previous task to complete,
  73488. // transfer the buffer back, and decode again with the second configuration. That
  73489. // is complex, and I don't know of any reason to decode a Draco buffer twice in
  73490. // different ways, so this is left unimplemented.
  73491. throw new Error(
  73492. 'THREE.DRACOLoader: Unable to re-decode a buffer with different ' +
  73493. 'settings. Buffer has already been transferred.'
  73494. );
  73495. }
  73496. }
  73497. //
  73498. let worker;
  73499. const taskID = this.workerNextTaskID ++;
  73500. const taskCost = buffer.byteLength;
  73501. // Obtain a worker and assign a task, and construct a geometry instance
  73502. // when the task completes.
  73503. const geometryPending = this._getWorker( taskID, taskCost )
  73504. .then( ( _worker ) => {
  73505. worker = _worker;
  73506. return new Promise( ( resolve, reject ) => {
  73507. worker._callbacks[ taskID ] = { resolve, reject };
  73508. worker.postMessage( { type: 'decode', id: taskID, taskConfig, buffer }, [ buffer ] );
  73509. // this.debug();
  73510. } );
  73511. } )
  73512. .then( ( message ) => this._createGeometry( message.geometry ) );
  73513. // Remove task from the task list.
  73514. // Note: replaced '.finally()' with '.catch().then()' block - iOS 11 support (#19416)
  73515. geometryPending
  73516. .catch( () => true )
  73517. .then( () => {
  73518. if ( worker && taskID ) {
  73519. this._releaseTask( worker, taskID );
  73520. // this.debug();
  73521. }
  73522. } );
  73523. // Cache the task result.
  73524. _taskCache.set( buffer, {
  73525. key: taskKey,
  73526. promise: geometryPending
  73527. } );
  73528. return geometryPending;
  73529. }
  73530. _createGeometry( geometryData ) {
  73531. const geometry = new BufferGeometry();
  73532. if ( geometryData.index ) {
  73533. geometry.setIndex( new BufferAttribute( geometryData.index.array, 1 ) );
  73534. }
  73535. for ( let i = 0; i < geometryData.attributes.length; i ++ ) {
  73536. const attribute = geometryData.attributes[ i ];
  73537. const name = attribute.name;
  73538. const array = attribute.array;
  73539. const itemSize = attribute.itemSize;
  73540. geometry.setAttribute( name, new BufferAttribute( array, itemSize ) );
  73541. }
  73542. return geometry;
  73543. }
  73544. _loadLibrary( url, responseType ) {
  73545. const loader = new FileLoader( this.manager );
  73546. loader.setPath( this.decoderPath );
  73547. loader.setResponseType( responseType );
  73548. loader.setWithCredentials( this.withCredentials );
  73549. return new Promise( ( resolve, reject ) => {
  73550. loader.load( url, resolve, undefined, reject );
  73551. } );
  73552. }
  73553. preload() {
  73554. this._initDecoder();
  73555. return this;
  73556. }
  73557. _initDecoder() {
  73558. if ( this.decoderPending ) return this.decoderPending;
  73559. const useJS = typeof WebAssembly !== 'object' || this.decoderConfig.type === 'js';
  73560. const librariesPending = [];
  73561. if ( useJS ) {
  73562. librariesPending.push( this._loadLibrary( 'draco_decoder.js', 'text' ) );
  73563. } else {
  73564. librariesPending.push( this._loadLibrary( 'draco_wasm_wrapper.js', 'text' ) );
  73565. librariesPending.push( this._loadLibrary( 'draco_decoder.wasm', 'arraybuffer' ) );
  73566. }
  73567. this.decoderPending = Promise.all( librariesPending )
  73568. .then( ( libraries ) => {
  73569. const jsContent = libraries[ 0 ];
  73570. if ( ! useJS ) {
  73571. this.decoderConfig.wasmBinary = libraries[ 1 ];
  73572. }
  73573. const fn = DRACOWorker.toString();
  73574. const body = [
  73575. '/* draco decoder */',
  73576. jsContent,
  73577. '',
  73578. '/* worker */',
  73579. fn.substring( fn.indexOf( '{' ) + 1, fn.lastIndexOf( '}' ) )
  73580. ].join( '\n' );
  73581. this.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) );
  73582. } );
  73583. return this.decoderPending;
  73584. }
  73585. _getWorker( taskID, taskCost ) {
  73586. return this._initDecoder().then( () => {
  73587. if ( this.workerPool.length < this.workerLimit ) {
  73588. const worker = new Worker( this.workerSourceURL );
  73589. worker._callbacks = {};
  73590. worker._taskCosts = {};
  73591. worker._taskLoad = 0;
  73592. worker.postMessage( { type: 'init', decoderConfig: this.decoderConfig } );
  73593. worker.onmessage = function ( e ) {
  73594. const message = e.data;
  73595. switch ( message.type ) {
  73596. case 'decode':
  73597. worker._callbacks[ message.id ].resolve( message );
  73598. break;
  73599. case 'error':
  73600. worker._callbacks[ message.id ].reject( message );
  73601. break;
  73602. default:
  73603. console.error( 'THREE.DRACOLoader: Unexpected message, "' + message.type + '"' );
  73604. }
  73605. };
  73606. this.workerPool.push( worker );
  73607. } else {
  73608. this.workerPool.sort( function ( a, b ) {
  73609. return a._taskLoad > b._taskLoad ? - 1 : 1;
  73610. } );
  73611. }
  73612. const worker = this.workerPool[ this.workerPool.length - 1 ];
  73613. worker._taskCosts[ taskID ] = taskCost;
  73614. worker._taskLoad += taskCost;
  73615. return worker;
  73616. } );
  73617. }
  73618. _releaseTask( worker, taskID ) {
  73619. worker._taskLoad -= worker._taskCosts[ taskID ];
  73620. delete worker._callbacks[ taskID ];
  73621. delete worker._taskCosts[ taskID ];
  73622. }
  73623. debug() {
  73624. console.log( 'Task load: ', this.workerPool.map( ( worker ) => worker._taskLoad ) );
  73625. }
  73626. dispose() {
  73627. for ( let i = 0; i < this.workerPool.length; ++ i ) {
  73628. this.workerPool[ i ].terminate();
  73629. }
  73630. this.workerPool.length = 0;
  73631. return this;
  73632. }
  73633. }
  73634. /* WEB WORKER */
  73635. function DRACOWorker() {
  73636. let decoderConfig;
  73637. let decoderPending;
  73638. onmessage = function ( e ) {
  73639. const message = e.data;
  73640. switch ( message.type ) {
  73641. case 'init':
  73642. decoderConfig = message.decoderConfig;
  73643. decoderPending = new Promise( function ( resolve/*, reject*/ ) {
  73644. decoderConfig.onModuleLoaded = function ( draco ) {
  73645. // Module is Promise-like. Wrap before resolving to avoid loop.
  73646. resolve( { draco: draco } );
  73647. };
  73648. DracoDecoderModule( decoderConfig ); // eslint-disable-line no-undef
  73649. } );
  73650. break;
  73651. case 'decode':
  73652. const buffer = message.buffer;
  73653. const taskConfig = message.taskConfig;
  73654. decoderPending.then( ( module ) => {
  73655. const draco = module.draco;
  73656. const decoder = new draco.Decoder();
  73657. const decoderBuffer = new draco.DecoderBuffer();
  73658. decoderBuffer.Init( new Int8Array( buffer ), buffer.byteLength );
  73659. try {
  73660. const geometry = decodeGeometry( draco, decoder, decoderBuffer, taskConfig );
  73661. const buffers = geometry.attributes.map( ( attr ) => attr.array.buffer );
  73662. if ( geometry.index ) buffers.push( geometry.index.array.buffer );
  73663. self.postMessage( { type: 'decode', id: message.id, geometry }, buffers );
  73664. } catch ( error ) {
  73665. console.error( error );
  73666. self.postMessage( { type: 'error', id: message.id, error: error.message } );
  73667. } finally {
  73668. draco.destroy( decoderBuffer );
  73669. draco.destroy( decoder );
  73670. }
  73671. } );
  73672. break;
  73673. }
  73674. };
  73675. function decodeGeometry( draco, decoder, decoderBuffer, taskConfig ) {
  73676. const attributeIDs = taskConfig.attributeIDs;
  73677. const attributeTypes = taskConfig.attributeTypes;
  73678. let dracoGeometry;
  73679. let decodingStatus;
  73680. const geometryType = decoder.GetEncodedGeometryType( decoderBuffer );
  73681. if ( geometryType === draco.TRIANGULAR_MESH ) {
  73682. dracoGeometry = new draco.Mesh();
  73683. decodingStatus = decoder.DecodeBufferToMesh( decoderBuffer, dracoGeometry );
  73684. } else if ( geometryType === draco.POINT_CLOUD ) {
  73685. dracoGeometry = new draco.PointCloud();
  73686. decodingStatus = decoder.DecodeBufferToPointCloud( decoderBuffer, dracoGeometry );
  73687. } else {
  73688. throw new Error( 'THREE.DRACOLoader: Unexpected geometry type.' );
  73689. }
  73690. if ( ! decodingStatus.ok() || dracoGeometry.ptr === 0 ) {
  73691. throw new Error( 'THREE.DRACOLoader: Decoding failed: ' + decodingStatus.error_msg() );
  73692. }
  73693. const geometry = { index: null, attributes: [] };
  73694. // Gather all vertex attributes.
  73695. for ( const attributeName in attributeIDs ) {
  73696. const attributeType = self[ attributeTypes[ attributeName ] ];
  73697. let attribute;
  73698. let attributeID;
  73699. // A Draco file may be created with default vertex attributes, whose attribute IDs
  73700. // are mapped 1:1 from their semantic name (POSITION, NORMAL, ...). Alternatively,
  73701. // a Draco file may contain a custom set of attributes, identified by known unique
  73702. // IDs. glTF files always do the latter, and `.drc` files typically do the former.
  73703. if ( taskConfig.useUniqueIDs ) {
  73704. attributeID = attributeIDs[ attributeName ];
  73705. attribute = decoder.GetAttributeByUniqueId( dracoGeometry, attributeID );
  73706. } else {
  73707. attributeID = decoder.GetAttributeId( dracoGeometry, draco[ attributeIDs[ attributeName ] ] );
  73708. if ( attributeID === - 1 ) continue;
  73709. attribute = decoder.GetAttribute( dracoGeometry, attributeID );
  73710. }
  73711. geometry.attributes.push( decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) );
  73712. }
  73713. // Add index.
  73714. if ( geometryType === draco.TRIANGULAR_MESH ) {
  73715. geometry.index = decodeIndex( draco, decoder, dracoGeometry );
  73716. }
  73717. draco.destroy( dracoGeometry );
  73718. return geometry;
  73719. }
  73720. function decodeIndex( draco, decoder, dracoGeometry ) {
  73721. const numFaces = dracoGeometry.num_faces();
  73722. const numIndices = numFaces * 3;
  73723. const byteLength = numIndices * 4;
  73724. const ptr = draco._malloc( byteLength );
  73725. decoder.GetTrianglesUInt32Array( dracoGeometry, byteLength, ptr );
  73726. const index = new Uint32Array( draco.HEAPF32.buffer, ptr, numIndices ).slice();
  73727. draco._free( ptr );
  73728. return { array: index, itemSize: 1 };
  73729. }
  73730. function decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) {
  73731. const numComponents = attribute.num_components();
  73732. const numPoints = dracoGeometry.num_points();
  73733. const numValues = numPoints * numComponents;
  73734. const byteLength = numValues * attributeType.BYTES_PER_ELEMENT;
  73735. const dataType = getDracoDataType( draco, attributeType );
  73736. const ptr = draco._malloc( byteLength );
  73737. decoder.GetAttributeDataArrayForAllPoints( dracoGeometry, attribute, dataType, byteLength, ptr );
  73738. const array = new attributeType( draco.HEAPF32.buffer, ptr, numValues ).slice();
  73739. draco._free( ptr );
  73740. return {
  73741. name: attributeName,
  73742. array: array,
  73743. itemSize: numComponents
  73744. };
  73745. }
  73746. function getDracoDataType( draco, attributeType ) {
  73747. switch ( attributeType ) {
  73748. case Float32Array: return draco.DT_FLOAT32;
  73749. case Int8Array: return draco.DT_INT8;
  73750. case Int16Array: return draco.DT_INT16;
  73751. case Int32Array: return draco.DT_INT32;
  73752. case Uint8Array: return draco.DT_UINT8;
  73753. case Uint16Array: return draco.DT_UINT16;
  73754. case Uint32Array: return draco.DT_UINT32;
  73755. }
  73756. }
  73757. }
  73758. /**
  73759. * @author Deepkolos / https://github.com/deepkolos
  73760. */
  73761. //用于KTX2Loader
  73762. class WorkerPool$1 {
  73763. constructor( pool = 4 ) {
  73764. this.pool = pool;
  73765. this.queue = [];
  73766. this.workers = [];
  73767. this.workersResolve = [];
  73768. this.workerStatus = 0;
  73769. }
  73770. _initWorker( workerId ) {
  73771. if ( ! this.workers[ workerId ] ) {
  73772. const worker = this.workerCreator();
  73773. worker.addEventListener( 'message', this._onMessage.bind( this, workerId ) );
  73774. this.workers[ workerId ] = worker;
  73775. }
  73776. }
  73777. _getIdleWorker() {
  73778. for ( let i = 0; i < this.pool; i ++ )
  73779. if ( ! ( this.workerStatus & ( 1 << i ) ) ) return i;
  73780. return - 1;
  73781. }
  73782. _onMessage( workerId, msg ) {
  73783. const resolve = this.workersResolve[ workerId ];
  73784. resolve && resolve( msg );
  73785. if ( this.queue.length ) {
  73786. const { resolve, msg, transfer } = this.queue.shift();
  73787. this.workersResolve[ workerId ] = resolve;
  73788. this.workers[ workerId ].postMessage( msg, transfer );
  73789. } else {
  73790. this.workerStatus ^= 1 << workerId;
  73791. }
  73792. }
  73793. setWorkerCreator( workerCreator ) {
  73794. this.workerCreator = workerCreator;
  73795. }
  73796. setWorkerLimit( pool ) {
  73797. this.pool = pool;
  73798. }
  73799. postMessage( msg, transfer ) {
  73800. return new Promise( ( resolve ) => {
  73801. const workerId = this._getIdleWorker();
  73802. if ( workerId !== - 1 ) {
  73803. this._initWorker( workerId );
  73804. this.workerStatus |= 1 << workerId;
  73805. this.workersResolve[ workerId ] = resolve;
  73806. this.workers[ workerId ].postMessage( msg, transfer );
  73807. } else {
  73808. this.queue.push( { resolve, msg, transfer } );
  73809. }
  73810. } );
  73811. }
  73812. dispose() {
  73813. this.workers.forEach( ( worker ) => worker.terminate() );
  73814. this.workersResolve.length = 0;
  73815. this.workers.length = 0;
  73816. this.queue.length = 0;
  73817. this.workerStatus = 0;
  73818. }
  73819. }
  73820. const t=0,e=1,n$1=2,i$1=3,s=0,a$1=0,r=2,o=0,l=1,f=160,U$1=161,c$1=162,h=163,_=0,p=1,g=0,y=1,x$1=2,u=3,b=4,d=5,m=6,w$1=7,D=8,B=9,L=10,A=11,k=12,v=13,S=14,I=15,O=16,T=17,V=18,E=0,F=1,P=2,C=3,z=4,M=5,W=6,N=7,H=8,K=9,X=10,j=11,R=0,Y=1,q=2,G=13,J=14,Q=15,Z=128,$$1=64,tt=32,et=16,nt=0,it=1,st=2,at=3,rt=4,ot=5,lt=6,ft=7,Ut=8,ct=9,ht=10,_t=13,pt=14,gt=15,yt=16,xt=17,ut=20,bt=21,dt=22,mt=23,wt=24,Dt=27,Bt=28,Lt=29,At=30,kt=31,vt=34,St=35,It=36,Ot=37,Tt=38,Vt=41,Et=42,Ft=43,Pt=44,Ct=45,zt=48,Mt=49,Wt=50,Nt=58,Ht=59,Kt=62,Xt=63,jt=64,Rt=65,Yt=68,qt=69,Gt=70,Jt=71,Qt=74,Zt=75,$t=76,te=77,ee=78,ne=81,ie=82,se=83,ae=84,re=85,oe=88,le=89,fe=90,Ue=91,ce=92,he=95,_e=96,pe=97,ge=98,ye=99,xe=100,ue=101,be=102,de=103,me=104,we=105,De=106,Be=107,Le=108,Ae=109,ke=110,ve=111,Se=112,Ie=113,Oe=114,Te=115,Ve=116,Ee=117,Fe=118,Pe=119,Ce=120,ze=121,Me=122,We=123,Ne=124,He=125,Ke=126,Xe=127,je=128,Re=129,Ye=130,qe=131,Ge=132,Je=133,Qe=134,Ze=135,$e=136,tn=137,en=138,nn=139,sn=140,an=141,rn=142,on=143,ln=144,fn=145,Un=146,cn=147,hn=148,_n=149,pn=150,gn=151,yn=152,xn=153,un=154,bn=155,dn=156,mn=157,wn=158,Dn=159,Bn=160,Ln=161,An=162,kn=163,vn=164,Sn=165,In=166,On=167,Tn=168,Vn=169,En=170,Fn=171,Pn=172,Cn=173,zn=174,Mn=175,Wn=176,Nn=177,Hn=178,Kn=179,Xn=180,jn=181,Rn=182,Yn=183,qn=184,Gn=1000156007,Jn=1000156008,Qn=1000156009,Zn=1000156010,$n=1000156011,ti=1000156017,ei=1000156018,ni=1000156019,ii=1000156020,si=1000156021,ai=1000054e3,ri=1000054001,oi=1000054002,li=1000054003,fi=1000054004,Ui=1000054005,ci=1000054006,hi=1000054007,_i=1000066e3,pi=1000066001,gi=1000066002,yi=1000066003,xi=1000066004,ui=1000066005,bi=1000066006,di=1000066007,mi=1000066008,wi=1000066009,Di=1000066010,Bi=1000066011,Li=1000066012,Ai=1000066013,ki=100034e4,vi=1000340001;class Si{constructor(){this.vkFormat=0,this.typeSize=1,this.pixelWidth=0,this.pixelHeight=0,this.pixelDepth=0,this.layerCount=0,this.faceCount=1,this.supercompressionScheme=0,this.levels=[],this.dataFormatDescriptor=[{vendorId:0,descriptorType:0,descriptorBlockSize:0,versionNumber:2,colorModel:0,colorPrimaries:1,transferFunction:2,flags:0,texelBlockDimension:[0,0,0,0],bytesPlane:[0,0,0,0,0,0,0,0],samples:[]}],this.keyValue={},this.globalData=null;}}class Ii{constructor(t,e,n,i){this._dataView=new DataView(t.buffer,t.byteOffset+e,n),this._littleEndian=i,this._offset=0;}_nextUint8(){const t=this._dataView.getUint8(this._offset);return this._offset+=1,t}_nextUint16(){const t=this._dataView.getUint16(this._offset,this._littleEndian);return this._offset+=2,t}_nextUint32(){const t=this._dataView.getUint32(this._offset,this._littleEndian);return this._offset+=4,t}_nextUint64(){const t=this._dataView.getUint32(this._offset,this._littleEndian)+2**32*this._dataView.getUint32(this._offset+4,this._littleEndian);return this._offset+=8,t}_nextInt32(){const t=this._dataView.getInt32(this._offset,this._littleEndian);return this._offset+=4,t}_skip(t){return this._offset+=t,this}_scan(t,e=0){const n=this._offset;let i=0;for(;this._dataView.getUint8(this._offset)!==e&&i<t;)i++,this._offset++;return i<t&&this._offset++,new Uint8Array(this._dataView.buffer,this._dataView.byteOffset+n,i)}}const Oi=new Uint8Array([0]),Ti=[171,75,84,88,32,50,48,187,13,10,26,10];function Vi(t){return "undefined"!=typeof TextEncoder?(new TextEncoder).encode(t):Buffer.from(t)}function Ei(t){return "undefined"!=typeof TextDecoder?(new TextDecoder).decode(t):Buffer.from(t).toString("utf8")}function Fi(t){let e=0;for(const n of t)e+=n.byteLength;const n=new Uint8Array(e);let i=0;for(const e of t)n.set(new Uint8Array(e),i),i+=e.byteLength;return n}function Pi(t){const e=new Uint8Array(t.buffer,t.byteOffset,Ti.length);if(e[0]!==Ti[0]||e[1]!==Ti[1]||e[2]!==Ti[2]||e[3]!==Ti[3]||e[4]!==Ti[4]||e[5]!==Ti[5]||e[6]!==Ti[6]||e[7]!==Ti[7]||e[8]!==Ti[8]||e[9]!==Ti[9]||e[10]!==Ti[10]||e[11]!==Ti[11])throw new Error("Missing KTX 2.0 identifier.");const n=new Si,i=17*Uint32Array.BYTES_PER_ELEMENT,s=new Ii(t,Ti.length,i,!0);n.vkFormat=s._nextUint32(),n.typeSize=s._nextUint32(),n.pixelWidth=s._nextUint32(),n.pixelHeight=s._nextUint32(),n.pixelDepth=s._nextUint32(),n.layerCount=s._nextUint32(),n.faceCount=s._nextUint32();const a=s._nextUint32();n.supercompressionScheme=s._nextUint32();const r=s._nextUint32(),o=s._nextUint32(),l=s._nextUint32(),f=s._nextUint32(),U=s._nextUint64(),c=s._nextUint64(),h=new Ii(t,Ti.length+i,3*a*8,!0);for(let e=0;e<a;e++)n.levels.push({levelData:new Uint8Array(t.buffer,t.byteOffset+h._nextUint64(),h._nextUint64()),uncompressedByteLength:h._nextUint64()});const _=new Ii(t,r,o,!0),p={vendorId:_._skip(4)._nextUint16(),descriptorType:_._nextUint16(),versionNumber:_._nextUint16(),descriptorBlockSize:_._nextUint16(),colorModel:_._nextUint8(),colorPrimaries:_._nextUint8(),transferFunction:_._nextUint8(),flags:_._nextUint8(),texelBlockDimension:[_._nextUint8(),_._nextUint8(),_._nextUint8(),_._nextUint8()],bytesPlane:[_._nextUint8(),_._nextUint8(),_._nextUint8(),_._nextUint8(),_._nextUint8(),_._nextUint8(),_._nextUint8(),_._nextUint8()],samples:[]},g=(p.descriptorBlockSize/4-6)/4;for(let t=0;t<g;t++){const e={bitOffset:_._nextUint16(),bitLength:_._nextUint8(),channelType:_._nextUint8(),samplePosition:[_._nextUint8(),_._nextUint8(),_._nextUint8(),_._nextUint8()],sampleLower:-Infinity,sampleUpper:Infinity};64&e.channelType?(e.sampleLower=_._nextInt32(),e.sampleUpper=_._nextInt32()):(e.sampleLower=_._nextUint32(),e.sampleUpper=_._nextUint32()),p.samples[t]=e;}n.dataFormatDescriptor.length=0,n.dataFormatDescriptor.push(p);const y=new Ii(t,l,f,!0);for(;y._offset<f;){const t=y._nextUint32(),e=y._scan(t),i=Ei(e),s=y._scan(t-e.byteLength);n.keyValue[i]=i.match(/^ktx/i)?Ei(s):s,y._offset%4&&y._skip(4-y._offset%4);}if(c<=0)return n;const x=new Ii(t,U,c,!0),u=x._nextUint16(),b=x._nextUint16(),d=x._nextUint32(),m=x._nextUint32(),w=x._nextUint32(),D=x._nextUint32(),B=[];for(let t=0;t<a;t++)B.push({imageFlags:x._nextUint32(),rgbSliceByteOffset:x._nextUint32(),rgbSliceByteLength:x._nextUint32(),alphaSliceByteOffset:x._nextUint32(),alphaSliceByteLength:x._nextUint32()});const L=U+x._offset,A=L+d,k=A+m,v=k+w,S=new Uint8Array(t.buffer,t.byteOffset+L,d),I=new Uint8Array(t.buffer,t.byteOffset+A,m),O=new Uint8Array(t.buffer,t.byteOffset+k,w),T=new Uint8Array(t.buffer,t.byteOffset+v,D);return n.globalData={endpointCount:u,selectorCount:b,imageDescs:B,endpointsData:S,selectorsData:I,tablesData:O,extendedData:T},n}function Ci(){return (Ci=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i]);}return t}).apply(this,arguments)}const zi={keepWriter:!1};function Mi(t,e={}){e=Ci({},zi,e);let n=new ArrayBuffer(0);if(t.globalData){const e=new ArrayBuffer(20+5*t.globalData.imageDescs.length*4),i=new DataView(e);i.setUint16(0,t.globalData.endpointCount,!0),i.setUint16(2,t.globalData.selectorCount,!0),i.setUint32(4,t.globalData.endpointsData.byteLength,!0),i.setUint32(8,t.globalData.selectorsData.byteLength,!0),i.setUint32(12,t.globalData.tablesData.byteLength,!0),i.setUint32(16,t.globalData.extendedData.byteLength,!0);for(let e=0;e<t.globalData.imageDescs.length;e++){const n=t.globalData.imageDescs[e];i.setUint32(20+5*e*4+0,n.imageFlags,!0),i.setUint32(20+5*e*4+4,n.rgbSliceByteOffset,!0),i.setUint32(20+5*e*4+8,n.rgbSliceByteLength,!0),i.setUint32(20+5*e*4+12,n.alphaSliceByteOffset,!0),i.setUint32(20+5*e*4+16,n.alphaSliceByteLength,!0);}n=Fi([e,t.globalData.endpointsData,t.globalData.selectorsData,t.globalData.tablesData,t.globalData.extendedData]);}const i=[];let s=t.keyValue;e.keepWriter||(s=Ci({},t.keyValue,{KTXwriter:"KTX-Parse v0.3.1"}));for(const t in s){const e=s[t],n=Vi(t),a="string"==typeof e?Vi(e):e,r=n.byteLength+1+a.byteLength+1,o=r%4?4-r%4:0;i.push(Fi([new Uint32Array([r]),n,Oi,a,Oi,new Uint8Array(o).fill(0)]));}const a=Fi(i);if(1!==t.dataFormatDescriptor.length||0!==t.dataFormatDescriptor[0].descriptorType)throw new Error("Only BASICFORMAT Data Format Descriptor output supported.");const r=t.dataFormatDescriptor[0],o=new ArrayBuffer(28+16*r.samples.length),l=new DataView(o),f=24+16*r.samples.length;if(l.setUint32(0,o.byteLength,!0),l.setUint16(4,r.vendorId,!0),l.setUint16(6,r.descriptorType,!0),l.setUint16(8,r.versionNumber,!0),l.setUint16(10,f,!0),l.setUint8(12,r.colorModel),l.setUint8(13,r.colorPrimaries),l.setUint8(14,r.transferFunction),l.setUint8(15,r.flags),!Array.isArray(r.texelBlockDimension))throw new Error("texelBlockDimension is now an array. For dimensionality `d`, set `d - 1`.");l.setUint8(16,r.texelBlockDimension[0]),l.setUint8(17,r.texelBlockDimension[1]),l.setUint8(18,r.texelBlockDimension[2]),l.setUint8(19,r.texelBlockDimension[3]);for(let t=0;t<8;t++)l.setUint8(20+t,r.bytesPlane[t]);for(let t=0;t<r.samples.length;t++){const e=r.samples[t],n=28+16*t;if(e.channelID)throw new Error("channelID has been renamed to channelType.");l.setUint16(n+0,e.bitOffset,!0),l.setUint8(n+2,e.bitLength),l.setUint8(n+3,e.channelType),l.setUint8(n+4,e.samplePosition[0]),l.setUint8(n+5,e.samplePosition[1]),l.setUint8(n+6,e.samplePosition[2]),l.setUint8(n+7,e.samplePosition[3]),64&e.channelType?(l.setInt32(n+8,e.sampleLower,!0),l.setInt32(n+12,e.sampleUpper,!0)):(l.setUint32(n+8,e.sampleLower,!0),l.setUint32(n+12,e.sampleUpper,!0));}const U=Ti.length+68+3*t.levels.length*8,c=U+o.byteLength;let h=n.byteLength>0?c+a.byteLength:0;h%8&&(h+=8-h%8);const _=[],p=new DataView(new ArrayBuffer(3*t.levels.length*8));let g=(h||c+a.byteLength)+n.byteLength;for(let e=0;e<t.levels.length;e++){const n=t.levels[e];_.push(n.levelData),p.setBigUint64(24*e+0,BigInt(g),!0),p.setBigUint64(24*e+8,BigInt(n.levelData.byteLength),!0),p.setBigUint64(24*e+16,BigInt(n.uncompressedByteLength),!0),g+=n.levelData.byteLength;}const y=new ArrayBuffer(68),x=new DataView(y);return x.setUint32(0,t.vkFormat,!0),x.setUint32(4,t.typeSize,!0),x.setUint32(8,t.pixelWidth,!0),x.setUint32(12,t.pixelHeight,!0),x.setUint32(16,t.pixelDepth,!0),x.setUint32(20,t.layerCount,!0),x.setUint32(24,t.faceCount,!0),x.setUint32(28,t.levels.length,!0),x.setUint32(32,t.supercompressionScheme,!0),x.setUint32(36,U,!0),x.setUint32(40,o.byteLength,!0),x.setUint32(44,c,!0),x.setUint32(48,a.byteLength,!0),x.setBigUint64(52,BigInt(n.byteLength>0?h:0),!0),x.setBigUint64(60,BigInt(n.byteLength),!0),new Uint8Array(Fi([new Uint8Array(Ti).buffer,y,p.buffer,o,a,h>0?new ArrayBuffer(h-(c+a.byteLength)):new ArrayBuffer(0),n,..._]))}
  73821. /**
  73822. * @author Don McCurdy / https://www.donmccurdy.com
  73823. */
  73824. let init, instance, heap;
  73825. const importObject = {
  73826. env: {
  73827. emscripten_notify_memory_growth: function ( index ) {
  73828. heap = new Uint8Array( instance.exports.memory.buffer );
  73829. }
  73830. }
  73831. };
  73832. /**
  73833. * ZSTD (Zstandard) decoder.
  73834. *
  73835. * Compiled from https://github.com/facebook/zstd/tree/dev/contrib/single_file_libs, with the
  73836. * following steps:
  73837. *
  73838. * ```
  73839. * ./combine.sh -r ../../lib -o zstddeclib.c zstddeclib-in.c
  73840. * emcc zstddeclib.c -Oz -s EXPORTED_FUNCTIONS="['_ZSTD_decompress', '_ZSTD_findDecompressedSize', '_ZSTD_isError', '_malloc', '_free']" -s ALLOW_MEMORY_GROWTH=1 -s MALLOC=emmalloc -o zstddec.wasm
  73841. * base64 zstddec.wasm > zstddec.txt
  73842. * ```
  73843. *
  73844. * The base64 string written to `zstddec.txt` is embedded as the `wasm` variable at the bottom
  73845. * of this file. The rest of this file is written by hand, in order to avoid an additional JS
  73846. * wrapper generated by Emscripten.
  73847. */
  73848. class ZSTDDecoder {
  73849. init () {
  73850. if ( ! init ) {
  73851. init = fetch( 'data:application/wasm;base64,' + wasm )
  73852. .then( ( response ) => response.arrayBuffer() )
  73853. .then( ( arrayBuffer ) => WebAssembly.instantiate( arrayBuffer, importObject ) )
  73854. .then( ( result ) => {
  73855. instance = result.instance;
  73856. importObject.env.emscripten_notify_memory_growth( 0 ); // initialize heap.
  73857. });
  73858. }
  73859. return init;
  73860. }
  73861. decode ( array, uncompressedSize = 0 ) {
  73862. // Write compressed data into WASM memory.
  73863. const compressedSize = array.byteLength;
  73864. const compressedPtr = instance.exports.malloc( compressedSize );
  73865. heap.set( array, compressedPtr );
  73866. // Decompress into WASM memory.
  73867. uncompressedSize = uncompressedSize || Number( instance.exports.ZSTD_findDecompressedSize( compressedPtr, compressedSize ) );
  73868. const uncompressedPtr = instance.exports.malloc( uncompressedSize );
  73869. const actualSize = instance.exports.ZSTD_decompress( uncompressedPtr, uncompressedSize, compressedPtr, compressedSize );
  73870. // Read decompressed data and free WASM memory.
  73871. const dec = heap.slice( uncompressedPtr, uncompressedPtr + actualSize );
  73872. instance.exports.free( compressedPtr );
  73873. instance.exports.free( uncompressedPtr );
  73874. return dec;
  73875. }
  73876. }
  73877. /**
  73878. * BSD License
  73879. *
  73880. * For Zstandard software
  73881. *
  73882. * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. All rights reserved.
  73883. *
  73884. * Redistribution and use in source and binary forms, with or without modification,
  73885. * are permitted provided that the following conditions are met:
  73886. *
  73887. * * Redistributions of source code must retain the above copyright notice, this
  73888. * list of conditions and the following disclaimer.
  73889. *
  73890. * * Redistributions in binary form must reproduce the above copyright notice,
  73891. * this list of conditions and the following disclaimer in the documentation
  73892. * and/or other materials provided with the distribution.
  73893. *
  73894. * * Neither the name Facebook nor the names of its contributors may be used to
  73895. * endorse or promote products derived from this software without specific
  73896. * prior written permission.
  73897. *
  73898. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  73899. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  73900. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  73901. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  73902. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  73903. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  73904. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  73905. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  73906. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  73907. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  73908. */
  73909. const wasm = 'AGFzbQEAAAABpQEVYAF/AX9gAn9/AGADf39/AX9gBX9/f39/AX9gAX8AYAJ/fwF/YAR/f39/AX9gA39/fwBgBn9/f39/fwF/YAd/f39/f39/AX9gAn9/AX5gAn5+AX5gAABgBX9/f39/AGAGf39/f39/AGAIf39/f39/f38AYAl/f39/f39/f38AYAABf2AIf39/f39/f38Bf2ANf39/f39/f39/f39/fwF/YAF/AX4CJwEDZW52H2Vtc2NyaXB0ZW5fbm90aWZ5X21lbW9yeV9ncm93dGgABANpaAEFAAAFAgEFCwACAQABAgIFBQcAAwABDgsBAQcAEhMHAAUBDAQEAAANBwQCAgYCBAgDAwMDBgEACQkHBgICAAYGAgQUBwYGAwIGAAMCAQgBBwUGCgoEEQAEBAEIAwgDBQgDEA8IAAcABAUBcAECAgUEAQCAAgYJAX8BQaCgwAILB2AHBm1lbW9yeQIABm1hbGxvYwAoBGZyZWUAJgxaU1REX2lzRXJyb3IAaBlaU1REX2ZpbmREZWNvbXByZXNzZWRTaXplAFQPWlNURF9kZWNvbXByZXNzAEoGX3N0YXJ0ACQJBwEAQQELASQKussBaA8AIAAgACgCBCABajYCBAsZACAAKAIAIAAoAgRBH3F0QQAgAWtBH3F2CwgAIABBiH9LC34BBH9BAyEBIAAoAgQiA0EgTQRAIAAoAggiASAAKAIQTwRAIAAQDQ8LIAAoAgwiAiABRgRAQQFBAiADQSBJGw8LIAAgASABIAJrIANBA3YiBCABIARrIAJJIgEbIgJrIgQ2AgggACADIAJBA3RrNgIEIAAgBCgAADYCAAsgAQsUAQF/IAAgARACIQIgACABEAEgAgv3AQECfyACRQRAIABCADcCACAAQQA2AhAgAEIANwIIQbh/DwsgACABNgIMIAAgAUEEajYCECACQQRPBEAgACABIAJqIgFBfGoiAzYCCCAAIAMoAAA2AgAgAUF/ai0AACIBBEAgAEEIIAEQFGs2AgQgAg8LIABBADYCBEF/DwsgACABNgIIIAAgAS0AACIDNgIAIAJBfmoiBEEBTQRAIARBAWtFBEAgACABLQACQRB0IANyIgM2AgALIAAgAS0AAUEIdCADajYCAAsgASACakF/ai0AACIBRQRAIABBADYCBEFsDwsgAEEoIAEQFCACQQN0ams2AgQgAgsWACAAIAEpAAA3AAAgACABKQAINwAICy8BAX8gAUECdEGgHWooAgAgACgCAEEgIAEgACgCBGprQR9xdnEhAiAAIAEQASACCyEAIAFCz9bTvtLHq9lCfiAAfEIfiUKHla+vmLbem55/fgsdAQF/IAAoAgggACgCDEYEfyAAKAIEQSBGBUEACwuCBAEDfyACQYDAAE8EQCAAIAEgAhBnIAAPCyAAIAJqIQMCQCAAIAFzQQNxRQRAAkAgAkEBSARAIAAhAgwBCyAAQQNxRQRAIAAhAgwBCyAAIQIDQCACIAEtAAA6AAAgAUEBaiEBIAJBAWoiAiADTw0BIAJBA3ENAAsLAkAgA0F8cSIEQcAASQ0AIAIgBEFAaiIFSw0AA0AgAiABKAIANgIAIAIgASgCBDYCBCACIAEoAgg2AgggAiABKAIMNgIMIAIgASgCEDYCECACIAEoAhQ2AhQgAiABKAIYNgIYIAIgASgCHDYCHCACIAEoAiA2AiAgAiABKAIkNgIkIAIgASgCKDYCKCACIAEoAiw2AiwgAiABKAIwNgIwIAIgASgCNDYCNCACIAEoAjg2AjggAiABKAI8NgI8IAFBQGshASACQUBrIgIgBU0NAAsLIAIgBE8NAQNAIAIgASgCADYCACABQQRqIQEgAkEEaiICIARJDQALDAELIANBBEkEQCAAIQIMAQsgA0F8aiIEIABJBEAgACECDAELIAAhAgNAIAIgAS0AADoAACACIAEtAAE6AAEgAiABLQACOgACIAIgAS0AAzoAAyABQQRqIQEgAkEEaiICIARNDQALCyACIANJBEADQCACIAEtAAA6AAAgAUEBaiEBIAJBAWoiAiADRw0ACwsgAAsMACAAIAEpAAA3AAALQQECfyAAKAIIIgEgACgCEEkEQEEDDwsgACAAKAIEIgJBB3E2AgQgACABIAJBA3ZrIgE2AgggACABKAAANgIAQQALDAAgACABKAIANgAAC/cCAQJ/AkAgACABRg0AAkAgASACaiAASwRAIAAgAmoiBCABSw0BCyAAIAEgAhALDwsgACABc0EDcSEDAkACQCAAIAFJBEAgAwRAIAAhAwwDCyAAQQNxRQRAIAAhAwwCCyAAIQMDQCACRQ0EIAMgAS0AADoAACABQQFqIQEgAkF/aiECIANBAWoiA0EDcQ0ACwwBCwJAIAMNACAEQQNxBEADQCACRQ0FIAAgAkF/aiICaiIDIAEgAmotAAA6AAAgA0EDcQ0ACwsgAkEDTQ0AA0AgACACQXxqIgJqIAEgAmooAgA2AgAgAkEDSw0ACwsgAkUNAgNAIAAgAkF/aiICaiABIAJqLQAAOgAAIAINAAsMAgsgAkEDTQ0AIAIhBANAIAMgASgCADYCACABQQRqIQEgA0EEaiEDIARBfGoiBEEDSw0ACyACQQNxIQILIAJFDQADQCADIAEtAAA6AAAgA0EBaiEDIAFBAWohASACQX9qIgINAAsLIAAL8wICAn8BfgJAIAJFDQAgACACaiIDQX9qIAE6AAAgACABOgAAIAJBA0kNACADQX5qIAE6AAAgACABOgABIANBfWogAToAACAAIAE6AAIgAkEHSQ0AIANBfGogAToAACAAIAE6AAMgAkEJSQ0AIABBACAAa0EDcSIEaiIDIAFB/wFxQYGChAhsIgE2AgAgAyACIARrQXxxIgRqIgJBfGogATYCACAEQQlJDQAgAyABNgIIIAMgATYCBCACQXhqIAE2AgAgAkF0aiABNgIAIARBGUkNACADIAE2AhggAyABNgIUIAMgATYCECADIAE2AgwgAkFwaiABNgIAIAJBbGogATYCACACQWhqIAE2AgAgAkFkaiABNgIAIAQgA0EEcUEYciIEayICQSBJDQAgAa0iBUIghiAFhCEFIAMgBGohAQNAIAEgBTcDGCABIAU3AxAgASAFNwMIIAEgBTcDACABQSBqIQEgAkFgaiICQR9LDQALCyAACy8BAn8gACgCBCAAKAIAQQJ0aiICLQACIQMgACACLwEAIAEgAi0AAxAIajYCACADCy8BAn8gACgCBCAAKAIAQQJ0aiICLQACIQMgACACLwEAIAEgAi0AAxAFajYCACADCx8AIAAgASACKAIEEAg2AgAgARAEGiAAIAJBCGo2AgQLCAAgAGdBH3MLugUBDX8jAEEQayIKJAACfyAEQQNNBEAgCkEANgIMIApBDGogAyAEEAsaIAAgASACIApBDGpBBBAVIgBBbCAAEAMbIAAgACAESxsMAQsgAEEAIAEoAgBBAXRBAmoQECENQVQgAygAACIGQQ9xIgBBCksNABogAiAAQQVqNgIAIAMgBGoiAkF8aiEMIAJBeWohDiACQXtqIRAgAEEGaiELQQQhBSAGQQR2IQRBICAAdCIAQQFyIQkgASgCACEPQQAhAiADIQYCQANAIAlBAkggAiAPS3JFBEAgAiEHAkAgCARAA0AgBEH//wNxQf//A0YEQCAHQRhqIQcgBiAQSQR/IAZBAmoiBigAACAFdgUgBUEQaiEFIARBEHYLIQQMAQsLA0AgBEEDcSIIQQNGBEAgBUECaiEFIARBAnYhBCAHQQNqIQcMAQsLIAcgCGoiByAPSw0EIAVBAmohBQNAIAIgB0kEQCANIAJBAXRqQQA7AQAgAkEBaiECDAELCyAGIA5LQQAgBiAFQQN1aiIHIAxLG0UEQCAHKAAAIAVBB3EiBXYhBAwCCyAEQQJ2IQQLIAYhBwsCfyALQX9qIAQgAEF/anEiBiAAQQF0QX9qIgggCWsiEUkNABogBCAIcSIEQQAgESAEIABIG2shBiALCyEIIA0gAkEBdGogBkF/aiIEOwEAIAlBASAGayAEIAZBAUgbayEJA0AgCSAASARAIABBAXUhACALQX9qIQsMAQsLAn8gByAOS0EAIAcgBSAIaiIFQQN1aiIGIAxLG0UEQCAFQQdxDAELIAUgDCIGIAdrQQN0awshBSACQQFqIQIgBEUhCCAGKAAAIAVBH3F2IQQMAQsLQWwgCUEBRyAFQSBKcg0BGiABIAJBf2o2AgAgBiAFQQdqQQN1aiADawwBC0FQCyEAIApBEGokACAACwkAQQFBBSAAGwsMACAAIAEoAAA2AAALqgMBCn8jAEHwAGsiCiQAIAJBAWohDiAAQQhqIQtBgIAEIAVBf2p0QRB1IQxBACECQQEhBkEBIAV0IglBf2oiDyEIA0AgAiAORkUEQAJAIAEgAkEBdCINai8BACIHQf//A0YEQCALIAhBA3RqIAI2AgQgCEF/aiEIQQEhBwwBCyAGQQAgDCAHQRB0QRB1ShshBgsgCiANaiAHOwEAIAJBAWohAgwBCwsgACAFNgIEIAAgBjYCACAJQQN2IAlBAXZqQQNqIQxBACEAQQAhBkEAIQIDQCAGIA5GBEADQAJAIAAgCUYNACAKIAsgAEEDdGoiASgCBCIGQQF0aiICIAIvAQAiAkEBajsBACABIAUgAhAUayIIOgADIAEgAiAIQf8BcXQgCWs7AQAgASAEIAZBAnQiAmooAgA6AAIgASACIANqKAIANgIEIABBAWohAAwBCwsFIAEgBkEBdGouAQAhDUEAIQcDQCAHIA1ORQRAIAsgAkEDdGogBjYCBANAIAIgDGogD3EiAiAISw0ACyAHQQFqIQcMAQsLIAZBAWohBgwBCwsgCkHwAGokAAsjAEIAIAEQCSAAhUKHla+vmLbem55/fkLj3MqV/M7y9YV/fAsQACAAQn43AwggACABNgIACyQBAX8gAARAIAEoAgQiAgRAIAEoAgggACACEQEADwsgABAmCwsfACAAIAEgAi8BABAINgIAIAEQBBogACACQQRqNgIEC0oBAX9BoCAoAgAiASAAaiIAQX9MBEBBiCBBMDYCAEF/DwsCQCAAPwBBEHRNDQAgABBmDQBBiCBBMDYCAEF/DwtBoCAgADYCACABC9cBAQh/Qbp/IQoCQCACKAIEIgggAigCACIJaiIOIAEgAGtLDQBBbCEKIAkgBCADKAIAIgtrSw0AIAAgCWoiBCACKAIIIgxrIQ0gACABQWBqIg8gCyAJQQAQKSADIAkgC2o2AgACQAJAIAwgBCAFa00EQCANIQUMAQsgDCAEIAZrSw0CIAcgDSAFayIAaiIBIAhqIAdNBEAgBCABIAgQDxoMAgsgBCABQQAgAGsQDyEBIAIgACAIaiIINgIEIAEgAGshBAsgBCAPIAUgCEEBECkLIA4hCgsgCgubAgEBfyMAQYABayINJAAgDSADNgJ8AkAgAkEDSwRAQX8hCQwBCwJAAkACQAJAIAJBAWsOAwADAgELIAZFBEBBuH8hCQwEC0FsIQkgBS0AACICIANLDQMgACAHIAJBAnQiAmooAgAgAiAIaigCABA7IAEgADYCAEEBIQkMAwsgASAJNgIAQQAhCQwCCyAKRQRAQWwhCQwCC0EAIQkgC0UgDEEZSHINAUEIIAR0QQhqIQBBACECA0AgAiAATw0CIAJBQGshAgwAAAsAC0FsIQkgDSANQfwAaiANQfgAaiAFIAYQFSICEAMNACANKAJ4IgMgBEsNACAAIA0gDSgCfCAHIAggAxAYIAEgADYCACACIQkLIA1BgAFqJAAgCQsLACAAIAEgAhALGgsQACAALwAAIAAtAAJBEHRyCy8AAn9BuH8gAUEISQ0AGkFyIAAoAAQiAEF3Sw0AGkG4fyAAQQhqIgAgACABSxsLCwkAIAAgATsAAAsDAAELigYBBX8gACAAKAIAIgVBfnE2AgBBACAAIAVBAXZqQYQgKAIAIgQgAEYbIQECQAJAIAAoAgQiAkUNACACKAIAIgNBAXENACACQQhqIgUgA0EBdkF4aiIDQQggA0EISxtnQR9zQQJ0QYAfaiIDKAIARgRAIAMgAigCDDYCAAsgAigCCCIDBEAgAyACKAIMNgIECyACKAIMIgMEQCADIAIoAgg2AgALIAIgAigCACAAKAIAQX5xajYCAEGEICEAAkACQCABRQ0AIAEgAjYCBCABKAIAIgNBAXENASADQQF2QXhqIgNBCCADQQhLG2dBH3NBAnRBgB9qIgMoAgAgAUEIakYEQCADIAEoAgw2AgALIAEoAggiAwRAIAMgASgCDDYCBAsgASgCDCIDBEAgAyABKAIINgIAQYQgKAIAIQQLIAIgAigCACABKAIAQX5xajYCACABIARGDQAgASABKAIAQQF2akEEaiEACyAAIAI2AgALIAIoAgBBAXZBeGoiAEEIIABBCEsbZ0Efc0ECdEGAH2oiASgCACEAIAEgBTYCACACIAA2AgwgAkEANgIIIABFDQEgACAFNgIADwsCQCABRQ0AIAEoAgAiAkEBcQ0AIAJBAXZBeGoiAkEIIAJBCEsbZ0Efc0ECdEGAH2oiAigCACABQQhqRgRAIAIgASgCDDYCAAsgASgCCCICBEAgAiABKAIMNgIECyABKAIMIgIEQCACIAEoAgg2AgBBhCAoAgAhBAsgACAAKAIAIAEoAgBBfnFqIgI2AgACQCABIARHBEAgASABKAIAQQF2aiAANgIEIAAoAgAhAgwBC0GEICAANgIACyACQQF2QXhqIgFBCCABQQhLG2dBH3NBAnRBgB9qIgIoAgAhASACIABBCGoiAjYCACAAIAE2AgwgAEEANgIIIAFFDQEgASACNgIADwsgBUEBdkF4aiIBQQggAUEISxtnQR9zQQJ0QYAfaiICKAIAIQEgAiAAQQhqIgI2AgAgACABNgIMIABBADYCCCABRQ0AIAEgAjYCAAsLDgAgAARAIABBeGoQJQsLgAIBA38CQCAAQQ9qQXhxQYQgKAIAKAIAQQF2ayICEB1Bf0YNAAJAQYQgKAIAIgAoAgAiAUEBcQ0AIAFBAXZBeGoiAUEIIAFBCEsbZ0Efc0ECdEGAH2oiASgCACAAQQhqRgRAIAEgACgCDDYCAAsgACgCCCIBBEAgASAAKAIMNgIECyAAKAIMIgFFDQAgASAAKAIINgIAC0EBIQEgACAAKAIAIAJBAXRqIgI2AgAgAkEBcQ0AIAJBAXZBeGoiAkEIIAJBCEsbZ0Efc0ECdEGAH2oiAygCACECIAMgAEEIaiIDNgIAIAAgAjYCDCAAQQA2AgggAkUNACACIAM2AgALIAELtwIBA38CQAJAIABBASAAGyICEDgiAA0AAkACQEGEICgCACIARQ0AIAAoAgAiA0EBcQ0AIAAgA0EBcjYCACADQQF2QXhqIgFBCCABQQhLG2dBH3NBAnRBgB9qIgEoAgAgAEEIakYEQCABIAAoAgw2AgALIAAoAggiAQRAIAEgACgCDDYCBAsgACgCDCIBBEAgASAAKAIINgIACyACECchAkEAIQFBhCAoAgAhACACDQEgACAAKAIAQX5xNgIAQQAPCyACQQ9qQXhxIgMQHSICQX9GDQIgAkEHakF4cSIAIAJHBEAgACACaxAdQX9GDQMLAkBBhCAoAgAiAUUEQEGAICAANgIADAELIAAgATYCBAtBhCAgADYCACAAIANBAXRBAXI2AgAMAQsgAEUNAQsgAEEIaiEBCyABC7kDAQJ/IAAgA2ohBQJAIANBB0wEQANAIAAgBU8NAiAAIAItAAA6AAAgAEEBaiEAIAJBAWohAgwAAAsACyAEQQFGBEACQCAAIAJrIgZBB00EQCAAIAItAAA6AAAgACACLQABOgABIAAgAi0AAjoAAiAAIAItAAM6AAMgAEEEaiACIAZBAnQiBkHAHmooAgBqIgIQFyACIAZB4B5qKAIAayECDAELIAAgAhAMCyACQQhqIQIgAEEIaiEACwJAAkACQAJAIAUgAU0EQCAAIANqIQEgBEEBRyAAIAJrQQ9Kcg0BA0AgACACEAwgAkEIaiECIABBCGoiACABSQ0ACwwFCyAAIAFLBEAgACEBDAQLIARBAUcgACACa0EPSnINASAAIQMgAiEEA0AgAyAEEAwgBEEIaiEEIANBCGoiAyABSQ0ACwwCCwNAIAAgAhAHIAJBEGohAiAAQRBqIgAgAUkNAAsMAwsgACEDIAIhBANAIAMgBBAHIARBEGohBCADQRBqIgMgAUkNAAsLIAIgASAAa2ohAgsDQCABIAVPDQEgASACLQAAOgAAIAFBAWohASACQQFqIQIMAAALAAsLQQECfyAAIAAoArjgASIDNgLE4AEgACgCvOABIQQgACABNgK84AEgACABIAJqNgK44AEgACABIAQgA2tqNgLA4AELpgEBAX8gACAAKALs4QEQFjYCyOABIABCADcD+OABIABCADcDuOABIABBwOABakIANwMAIABBqNAAaiIBQYyAgOAANgIAIABBADYCmOIBIABCADcDiOEBIABCAzcDgOEBIABBrNABakHgEikCADcCACAAQbTQAWpB6BIoAgA2AgAgACABNgIMIAAgAEGYIGo2AgggACAAQaAwajYCBCAAIABBEGo2AgALYQEBf0G4fyEDAkAgAUEDSQ0AIAIgABAhIgFBA3YiADYCCCACIAFBAXE2AgQgAiABQQF2QQNxIgM2AgACQCADQX9qIgFBAksNAAJAIAFBAWsOAgEAAgtBbA8LIAAhAwsgAwsMACAAIAEgAkEAEC4LiAQCA38CfiADEBYhBCAAQQBBKBAQIQAgBCACSwRAIAQPCyABRQRAQX8PCwJAAkAgA0EBRg0AIAEoAAAiBkGo6r5pRg0AQXYhAyAGQXBxQdDUtMIBRw0BQQghAyACQQhJDQEgAEEAQSgQECEAIAEoAAQhASAAQQE2AhQgACABrTcDAEEADwsgASACIAMQLyIDIAJLDQAgACADNgIYQXIhAyABIARqIgVBf2otAAAiAkEIcQ0AIAJBIHEiBkUEQEFwIQMgBS0AACIFQacBSw0BIAVBB3GtQgEgBUEDdkEKaq2GIgdCA4h+IAd8IQggBEEBaiEECyACQQZ2IQMgAkECdiEFAkAgAkEDcUF/aiICQQJLBEBBACECDAELAkACQAJAIAJBAWsOAgECAAsgASAEai0AACECIARBAWohBAwCCyABIARqLwAAIQIgBEECaiEEDAELIAEgBGooAAAhAiAEQQRqIQQLIAVBAXEhBQJ+AkACQAJAIANBf2oiA0ECTQRAIANBAWsOAgIDAQtCfyAGRQ0DGiABIARqMQAADAMLIAEgBGovAACtQoACfAwCCyABIARqKAAArQwBCyABIARqKQAACyEHIAAgBTYCICAAIAI2AhwgACAHNwMAQQAhAyAAQQA2AhQgACAHIAggBhsiBzcDCCAAIAdCgIAIIAdCgIAIVBs+AhALIAMLWwEBf0G4fyEDIAIQFiICIAFNBH8gACACakF/ai0AACIAQQNxQQJ0QaAeaigCACACaiAAQQZ2IgFBAnRBsB5qKAIAaiAAQSBxIgBFaiABRSAAQQV2cWoFQbh/CwsdACAAKAKQ4gEQWiAAQQA2AqDiASAAQgA3A5DiAQu1AwEFfyMAQZACayIKJABBuH8hBgJAIAVFDQAgBCwAACIIQf8BcSEHAkAgCEF/TARAIAdBgn9qQQF2IgggBU8NAkFsIQYgB0GBf2oiBUGAAk8NAiAEQQFqIQdBACEGA0AgBiAFTwRAIAUhBiAIIQcMAwUgACAGaiAHIAZBAXZqIgQtAABBBHY6AAAgACAGQQFyaiAELQAAQQ9xOgAAIAZBAmohBgwBCwAACwALIAcgBU8NASAAIARBAWogByAKEFMiBhADDQELIAYhBEEAIQYgAUEAQTQQECEJQQAhBQNAIAQgBkcEQCAAIAZqIggtAAAiAUELSwRAQWwhBgwDBSAJIAFBAnRqIgEgASgCAEEBajYCACAGQQFqIQZBASAILQAAdEEBdSAFaiEFDAILAAsLQWwhBiAFRQ0AIAUQFEEBaiIBQQxLDQAgAyABNgIAQQFBASABdCAFayIDEBQiAXQgA0cNACAAIARqIAFBAWoiADoAACAJIABBAnRqIgAgACgCAEEBajYCACAJKAIEIgBBAkkgAEEBcXINACACIARBAWo2AgAgB0EBaiEGCyAKQZACaiQAIAYLxhEBDH8jAEHwAGsiBSQAQWwhCwJAIANBCkkNACACLwAAIQogAi8AAiEJIAIvAAQhByAFQQhqIAQQDgJAIAMgByAJIApqakEGaiIMSQ0AIAUtAAohCCAFQdgAaiACQQZqIgIgChAGIgsQAw0BIAVBQGsgAiAKaiICIAkQBiILEAMNASAFQShqIAIgCWoiAiAHEAYiCxADDQEgBUEQaiACIAdqIAMgDGsQBiILEAMNASAAIAFqIg9BfWohECAEQQRqIQZBASELIAAgAUEDakECdiIDaiIMIANqIgIgA2oiDiEDIAIhBCAMIQcDQCALIAMgEElxBEAgACAGIAVB2ABqIAgQAkECdGoiCS8BADsAACAFQdgAaiAJLQACEAEgCS0AAyELIAcgBiAFQUBrIAgQAkECdGoiCS8BADsAACAFQUBrIAktAAIQASAJLQADIQogBCAGIAVBKGogCBACQQJ0aiIJLwEAOwAAIAVBKGogCS0AAhABIAktAAMhCSADIAYgBUEQaiAIEAJBAnRqIg0vAQA7AAAgBUEQaiANLQACEAEgDS0AAyENIAAgC2oiCyAGIAVB2ABqIAgQAkECdGoiAC8BADsAACAFQdgAaiAALQACEAEgAC0AAyEAIAcgCmoiCiAGIAVBQGsgCBACQQJ0aiIHLwEAOwAAIAVBQGsgBy0AAhABIActAAMhByAEIAlqIgkgBiAFQShqIAgQAkECdGoiBC8BADsAACAFQShqIAQtAAIQASAELQADIQQgAyANaiIDIAYgBUEQaiAIEAJBAnRqIg0vAQA7AAAgBUEQaiANLQACEAEgACALaiEAIAcgCmohByAEIAlqIQQgAyANLQADaiEDIAVB2ABqEA0gBUFAaxANciAFQShqEA1yIAVBEGoQDXJFIQsMAQsLIAQgDksgByACS3INAEFsIQsgACAMSw0BIAxBfWohCQNAQQAgACAJSSAFQdgAahAEGwRAIAAgBiAFQdgAaiAIEAJBAnRqIgovAQA7AAAgBUHYAGogCi0AAhABIAAgCi0AA2oiACAGIAVB2ABqIAgQAkECdGoiCi8BADsAACAFQdgAaiAKLQACEAEgACAKLQADaiEADAEFIAxBfmohCgNAIAVB2ABqEAQgACAKS3JFBEAgACAGIAVB2ABqIAgQAkECdGoiCS8BADsAACAFQdgAaiAJLQACEAEgACAJLQADaiEADAELCwNAIAAgCk0EQCAAIAYgBUHYAGogCBACQQJ0aiIJLwEAOwAAIAVB2ABqIAktAAIQASAAIAktAANqIQAMAQsLAkAgACAMTw0AIAAgBiAFQdgAaiAIEAIiAEECdGoiDC0AADoAACAMLQADQQFGBEAgBUHYAGogDC0AAhABDAELIAUoAlxBH0sNACAFQdgAaiAGIABBAnRqLQACEAEgBSgCXEEhSQ0AIAVBIDYCXAsgAkF9aiEMA0BBACAHIAxJIAVBQGsQBBsEQCAHIAYgBUFAayAIEAJBAnRqIgAvAQA7AAAgBUFAayAALQACEAEgByAALQADaiIAIAYgBUFAayAIEAJBAnRqIgcvAQA7AAAgBUFAayAHLQACEAEgACAHLQADaiEHDAEFIAJBfmohDANAIAVBQGsQBCAHIAxLckUEQCAHIAYgBUFAayAIEAJBAnRqIgAvAQA7AAAgBUFAayAALQACEAEgByAALQADaiEHDAELCwNAIAcgDE0EQCAHIAYgBUFAayAIEAJBAnRqIgAvAQA7AAAgBUFAayAALQACEAEgByAALQADaiEHDAELCwJAIAcgAk8NACAHIAYgBUFAayAIEAIiAEECdGoiAi0AADoAACACLQADQQFGBEAgBUFAayACLQACEAEMAQsgBSgCREEfSw0AIAVBQGsgBiAAQQJ0ai0AAhABIAUoAkRBIUkNACAFQSA2AkQLIA5BfWohAgNAQQAgBCACSSAFQShqEAQbBEAgBCAGIAVBKGogCBACQQJ0aiIALwEAOwAAIAVBKGogAC0AAhABIAQgAC0AA2oiACAGIAVBKGogCBACQQJ0aiIELwEAOwAAIAVBKGogBC0AAhABIAAgBC0AA2ohBAwBBSAOQX5qIQIDQCAFQShqEAQgBCACS3JFBEAgBCAGIAVBKGogCBACQQJ0aiIALwEAOwAAIAVBKGogAC0AAhABIAQgAC0AA2ohBAwBCwsDQCAEIAJNBEAgBCAGIAVBKGogCBACQQJ0aiIALwEAOwAAIAVBKGogAC0AAhABIAQgAC0AA2ohBAwBCwsCQCAEIA5PDQAgBCAGIAVBKGogCBACIgBBAnRqIgItAAA6AAAgAi0AA0EBRgRAIAVBKGogAi0AAhABDAELIAUoAixBH0sNACAFQShqIAYgAEECdGotAAIQASAFKAIsQSFJDQAgBUEgNgIsCwNAQQAgAyAQSSAFQRBqEAQbBEAgAyAGIAVBEGogCBACQQJ0aiIALwEAOwAAIAVBEGogAC0AAhABIAMgAC0AA2oiACAGIAVBEGogCBACQQJ0aiICLwEAOwAAIAVBEGogAi0AAhABIAAgAi0AA2ohAwwBBSAPQX5qIQIDQCAFQRBqEAQgAyACS3JFBEAgAyAGIAVBEGogCBACQQJ0aiIALwEAOwAAIAVBEGogAC0AAhABIAMgAC0AA2ohAwwBCwsDQCADIAJNBEAgAyAGIAVBEGogCBACQQJ0aiIALwEAOwAAIAVBEGogAC0AAhABIAMgAC0AA2ohAwwBCwsCQCADIA9PDQAgAyAGIAVBEGogCBACIgBBAnRqIgItAAA6AAAgAi0AA0EBRgRAIAVBEGogAi0AAhABDAELIAUoAhRBH0sNACAFQRBqIAYgAEECdGotAAIQASAFKAIUQSFJDQAgBUEgNgIUCyABQWwgBUHYAGoQCiAFQUBrEApxIAVBKGoQCnEgBUEQahAKcRshCwwJCwAACwALAAALAAsAAAsACwAACwALQWwhCwsgBUHwAGokACALC7UEAQ5/IwBBEGsiBiQAIAZBBGogABAOQVQhBQJAIARB3AtJDQAgBi0ABCEHIANB8ARqQQBB7AAQECEIIAdBDEsNACADQdwJaiIJIAggBkEIaiAGQQxqIAEgAhAxIhAQA0UEQCAGKAIMIgQgB0sNASADQdwFaiEPIANBpAVqIREgAEEEaiESIANBqAVqIQEgBCEFA0AgBSICQX9qIQUgCCACQQJ0aigCAEUNAAsgAkEBaiEOQQEhBQNAIAUgDk9FBEAgCCAFQQJ0IgtqKAIAIQwgASALaiAKNgIAIAVBAWohBSAKIAxqIQoMAQsLIAEgCjYCAEEAIQUgBigCCCELA0AgBSALRkUEQCABIAUgCWotAAAiDEECdGoiDSANKAIAIg1BAWo2AgAgDyANQQF0aiINIAw6AAEgDSAFOgAAIAVBAWohBQwBCwtBACEBIANBADYCqAUgBEF/cyAHaiEJQQEhBQNAIAUgDk9FBEAgCCAFQQJ0IgtqKAIAIQwgAyALaiABNgIAIAwgBSAJanQgAWohASAFQQFqIQUMAQsLIAcgBEEBaiIBIAJrIgRrQQFqIQgDQEEBIQUgBCAIT0UEQANAIAUgDk9FBEAgBUECdCIJIAMgBEE0bGpqIAMgCWooAgAgBHY2AgAgBUEBaiEFDAELCyAEQQFqIQQMAQsLIBIgByAPIAogESADIAIgARBkIAZBAToABSAGIAc6AAYgACAGKAIENgIACyAQIQULIAZBEGokACAFC8ENAQt/IwBB8ABrIgUkAEFsIQkCQCADQQpJDQAgAi8AACEKIAIvAAIhDCACLwAEIQYgBUEIaiAEEA4CQCADIAYgCiAMampBBmoiDUkNACAFLQAKIQcgBUHYAGogAkEGaiICIAoQBiIJEAMNASAFQUBrIAIgCmoiAiAMEAYiCRADDQEgBUEoaiACIAxqIgIgBhAGIgkQAw0BIAVBEGogAiAGaiADIA1rEAYiCRADDQEgACABaiIOQX1qIQ8gBEEEaiEGQQEhCSAAIAFBA2pBAnYiAmoiCiACaiIMIAJqIg0hAyAMIQQgCiECA0AgCSADIA9JcQRAIAYgBUHYAGogBxACQQF0aiIILQAAIQsgBUHYAGogCC0AARABIAAgCzoAACAGIAVBQGsgBxACQQF0aiIILQAAIQsgBUFAayAILQABEAEgAiALOgAAIAYgBUEoaiAHEAJBAXRqIggtAAAhCyAFQShqIAgtAAEQASAEIAs6AAAgBiAFQRBqIAcQAkEBdGoiCC0AACELIAVBEGogCC0AARABIAMgCzoAACAGIAVB2ABqIAcQAkEBdGoiCC0AACELIAVB2ABqIAgtAAEQASAAIAs6AAEgBiAFQUBrIAcQAkEBdGoiCC0AACELIAVBQGsgCC0AARABIAIgCzoAASAGIAVBKGogBxACQQF0aiIILQAAIQsgBUEoaiAILQABEAEgBCALOgABIAYgBUEQaiAHEAJBAXRqIggtAAAhCyAFQRBqIAgtAAEQASADIAs6AAEgA0ECaiEDIARBAmohBCACQQJqIQIgAEECaiEAIAkgBUHYAGoQDUVxIAVBQGsQDUVxIAVBKGoQDUVxIAVBEGoQDUVxIQkMAQsLIAQgDUsgAiAMS3INAEFsIQkgACAKSw0BIApBfWohCQNAIAVB2ABqEAQgACAJT3JFBEAgBiAFQdgAaiAHEAJBAXRqIggtAAAhCyAFQdgAaiAILQABEAEgACALOgAAIAYgBUHYAGogBxACQQF0aiIILQAAIQsgBUHYAGogCC0AARABIAAgCzoAASAAQQJqIQAMAQsLA0AgBUHYAGoQBCAAIApPckUEQCAGIAVB2ABqIAcQAkEBdGoiCS0AACEIIAVB2ABqIAktAAEQASAAIAg6AAAgAEEBaiEADAELCwNAIAAgCkkEQCAGIAVB2ABqIAcQAkEBdGoiCS0AACEIIAVB2ABqIAktAAEQASAAIAg6AAAgAEEBaiEADAELCyAMQX1qIQADQCAFQUBrEAQgAiAAT3JFBEAgBiAFQUBrIAcQAkEBdGoiCi0AACEJIAVBQGsgCi0AARABIAIgCToAACAGIAVBQGsgBxACQQF0aiIKLQAAIQkgBUFAayAKLQABEAEgAiAJOgABIAJBAmohAgwBCwsDQCAFQUBrEAQgAiAMT3JFBEAgBiAFQUBrIAcQAkEBdGoiAC0AACEKIAVBQGsgAC0AARABIAIgCjoAACACQQFqIQIMAQsLA0AgAiAMSQRAIAYgBUFAayAHEAJBAXRqIgAtAAAhCiAFQUBrIAAtAAEQASACIAo6AAAgAkEBaiECDAELCyANQX1qIQADQCAFQShqEAQgBCAAT3JFBEAgBiAFQShqIAcQAkEBdGoiAi0AACEKIAVBKGogAi0AARABIAQgCjoAACAGIAVBKGogBxACQQF0aiICLQAAIQogBUEoaiACLQABEAEgBCAKOgABIARBAmohBAwBCwsDQCAFQShqEAQgBCANT3JFBEAgBiAFQShqIAcQAkEBdGoiAC0AACECIAVBKGogAC0AARABIAQgAjoAACAEQQFqIQQMAQsLA0AgBCANSQRAIAYgBUEoaiAHEAJBAXRqIgAtAAAhAiAFQShqIAAtAAEQASAEIAI6AAAgBEEBaiEEDAELCwNAIAVBEGoQBCADIA9PckUEQCAGIAVBEGogBxACQQF0aiIALQAAIQIgBUEQaiAALQABEAEgAyACOgAAIAYgBUEQaiAHEAJBAXRqIgAtAAAhAiAFQRBqIAAtAAEQASADIAI6AAEgA0ECaiEDDAELCwNAIAVBEGoQBCADIA5PckUEQCAGIAVBEGogBxACQQF0aiIALQAAIQIgBUEQaiAALQABEAEgAyACOgAAIANBAWohAwwBCwsDQCADIA5JBEAgBiAFQRBqIAcQAkEBdGoiAC0AACECIAVBEGogAC0AARABIAMgAjoAACADQQFqIQMMAQsLIAFBbCAFQdgAahAKIAVBQGsQCnEgBUEoahAKcSAFQRBqEApxGyEJDAELQWwhCQsgBUHwAGokACAJC8oCAQR/IwBBIGsiBSQAIAUgBBAOIAUtAAIhByAFQQhqIAIgAxAGIgIQA0UEQCAEQQRqIQIgACABaiIDQX1qIQQDQCAFQQhqEAQgACAET3JFBEAgAiAFQQhqIAcQAkEBdGoiBi0AACEIIAVBCGogBi0AARABIAAgCDoAACACIAVBCGogBxACQQF0aiIGLQAAIQggBUEIaiAGLQABEAEgACAIOgABIABBAmohAAwBCwsDQCAFQQhqEAQgACADT3JFBEAgAiAFQQhqIAcQAkEBdGoiBC0AACEGIAVBCGogBC0AARABIAAgBjoAACAAQQFqIQAMAQsLA0AgACADT0UEQCACIAVBCGogBxACQQF0aiIELQAAIQYgBUEIaiAELQABEAEgACAGOgAAIABBAWohAAwBCwsgAUFsIAVBCGoQChshAgsgBUEgaiQAIAILtgMBCX8jAEEQayIGJAAgBkEANgIMIAZBADYCCEFUIQQCQAJAIANBQGsiDCADIAZBCGogBkEMaiABIAIQMSICEAMNACAGQQRqIAAQDiAGKAIMIgcgBi0ABEEBaksNASAAQQRqIQogBkEAOgAFIAYgBzoABiAAIAYoAgQ2AgAgB0EBaiEJQQEhBANAIAQgCUkEQCADIARBAnRqIgEoAgAhACABIAU2AgAgACAEQX9qdCAFaiEFIARBAWohBAwBCwsgB0EBaiEHQQAhBSAGKAIIIQkDQCAFIAlGDQEgAyAFIAxqLQAAIgRBAnRqIgBBASAEdEEBdSILIAAoAgAiAWoiADYCACAHIARrIQhBACEEAkAgC0EDTQRAA0AgBCALRg0CIAogASAEakEBdGoiACAIOgABIAAgBToAACAEQQFqIQQMAAALAAsDQCABIABPDQEgCiABQQF0aiIEIAg6AAEgBCAFOgAAIAQgCDoAAyAEIAU6AAIgBCAIOgAFIAQgBToABCAEIAg6AAcgBCAFOgAGIAFBBGohAQwAAAsACyAFQQFqIQUMAAALAAsgAiEECyAGQRBqJAAgBAutAQECfwJAQYQgKAIAIABHIAAoAgBBAXYiAyABa0F4aiICQXhxQQhHcgR/IAIFIAMQJ0UNASACQQhqC0EQSQ0AIAAgACgCACICQQFxIAAgAWpBD2pBeHEiASAAa0EBdHI2AgAgASAANgIEIAEgASgCAEEBcSAAIAJBAXZqIAFrIgJBAXRyNgIAQYQgIAEgAkH/////B3FqQQRqQYQgKAIAIABGGyABNgIAIAEQJQsLygIBBX8CQAJAAkAgAEEIIABBCEsbZ0EfcyAAaUEBR2oiAUEESSAAIAF2cg0AIAFBAnRB/B5qKAIAIgJFDQADQCACQXhqIgMoAgBBAXZBeGoiBSAATwRAIAIgBUEIIAVBCEsbZ0Efc0ECdEGAH2oiASgCAEYEQCABIAIoAgQ2AgALDAMLIARBHksNASAEQQFqIQQgAigCBCICDQALC0EAIQMgAUEgTw0BA0AgAUECdEGAH2ooAgAiAkUEQCABQR5LIQIgAUEBaiEBIAJFDQEMAwsLIAIgAkF4aiIDKAIAQQF2QXhqIgFBCCABQQhLG2dBH3NBAnRBgB9qIgEoAgBGBEAgASACKAIENgIACwsgAigCACIBBEAgASACKAIENgIECyACKAIEIgEEQCABIAIoAgA2AgALIAMgAygCAEEBcjYCACADIAAQNwsgAwvhCwINfwV+IwBB8ABrIgckACAHIAAoAvDhASIINgJcIAEgAmohDSAIIAAoAoDiAWohDwJAAkAgBUUEQCABIQQMAQsgACgCxOABIRAgACgCwOABIREgACgCvOABIQ4gAEEBNgKM4QFBACEIA0AgCEEDRwRAIAcgCEECdCICaiAAIAJqQazQAWooAgA2AkQgCEEBaiEIDAELC0FsIQwgB0EYaiADIAQQBhADDQEgB0EsaiAHQRhqIAAoAgAQEyAHQTRqIAdBGGogACgCCBATIAdBPGogB0EYaiAAKAIEEBMgDUFgaiESIAEhBEEAIQwDQCAHKAIwIAcoAixBA3RqKQIAIhRCEIinQf8BcSEIIAcoAkAgBygCPEEDdGopAgAiFUIQiKdB/wFxIQsgBygCOCAHKAI0QQN0aikCACIWQiCIpyEJIBVCIIghFyAUQiCIpyECAkAgFkIQiKdB/wFxIgNBAk8EQAJAIAZFIANBGUlyRQRAIAkgB0EYaiADQSAgBygCHGsiCiAKIANLGyIKEAUgAyAKayIDdGohCSAHQRhqEAQaIANFDQEgB0EYaiADEAUgCWohCQwBCyAHQRhqIAMQBSAJaiEJIAdBGGoQBBoLIAcpAkQhGCAHIAk2AkQgByAYNwNIDAELAkAgA0UEQCACBEAgBygCRCEJDAMLIAcoAkghCQwBCwJAAkAgB0EYakEBEAUgCSACRWpqIgNBA0YEQCAHKAJEQX9qIgMgA0VqIQkMAQsgA0ECdCAHaigCRCIJIAlFaiEJIANBAUYNAQsgByAHKAJINgJMCwsgByAHKAJENgJIIAcgCTYCRAsgF6chAyALBEAgB0EYaiALEAUgA2ohAwsgCCALakEUTwRAIAdBGGoQBBoLIAgEQCAHQRhqIAgQBSACaiECCyAHQRhqEAQaIAcgB0EYaiAUQhiIp0H/AXEQCCAUp0H//wNxajYCLCAHIAdBGGogFUIYiKdB/wFxEAggFadB//8DcWo2AjwgB0EYahAEGiAHIAdBGGogFkIYiKdB/wFxEAggFqdB//8DcWo2AjQgByACNgJgIAcoAlwhCiAHIAk2AmggByADNgJkAkACQAJAIAQgAiADaiILaiASSw0AIAIgCmoiEyAPSw0AIA0gBGsgC0Egak8NAQsgByAHKQNoNwMQIAcgBykDYDcDCCAEIA0gB0EIaiAHQdwAaiAPIA4gESAQEB4hCwwBCyACIARqIQggBCAKEAcgAkERTwRAIARBEGohAgNAIAIgCkEQaiIKEAcgAkEQaiICIAhJDQALCyAIIAlrIQIgByATNgJcIAkgCCAOa0sEQCAJIAggEWtLBEBBbCELDAILIBAgAiAOayICaiIKIANqIBBNBEAgCCAKIAMQDxoMAgsgCCAKQQAgAmsQDyEIIAcgAiADaiIDNgJkIAggAmshCCAOIQILIAlBEE8EQCADIAhqIQMDQCAIIAIQByACQRBqIQIgCEEQaiIIIANJDQALDAELAkAgCUEHTQRAIAggAi0AADoAACAIIAItAAE6AAEgCCACLQACOgACIAggAi0AAzoAAyAIQQRqIAIgCUECdCIDQcAeaigCAGoiAhAXIAIgA0HgHmooAgBrIQIgBygCZCEDDAELIAggAhAMCyADQQlJDQAgAyAIaiEDIAhBCGoiCCACQQhqIgJrQQ9MBEADQCAIIAIQDCACQQhqIQIgCEEIaiIIIANJDQAMAgALAAsDQCAIIAIQByACQRBqIQIgCEEQaiIIIANJDQALCyAHQRhqEAQaIAsgDCALEAMiAhshDCAEIAQgC2ogAhshBCAFQX9qIgUNAAsgDBADDQFBbCEMIAdBGGoQBEECSQ0BQQAhCANAIAhBA0cEQCAAIAhBAnQiAmpBrNABaiACIAdqKAJENgIAIAhBAWohCAwBCwsgBygCXCEIC0G6fyEMIA8gCGsiACANIARrSw0AIAQEfyAEIAggABALIABqBUEACyABayEMCyAHQfAAaiQAIAwLkRcCFn8FfiMAQdABayIHJAAgByAAKALw4QEiCDYCvAEgASACaiESIAggACgCgOIBaiETAkACQCAFRQRAIAEhAwwBCyAAKALE4AEhESAAKALA4AEhFSAAKAK84AEhDyAAQQE2AozhAUEAIQgDQCAIQQNHBEAgByAIQQJ0IgJqIAAgAmpBrNABaigCADYCVCAIQQFqIQgMAQsLIAcgETYCZCAHIA82AmAgByABIA9rNgJoQWwhECAHQShqIAMgBBAGEAMNASAFQQQgBUEESBshFyAHQTxqIAdBKGogACgCABATIAdBxABqIAdBKGogACgCCBATIAdBzABqIAdBKGogACgCBBATQQAhBCAHQeAAaiEMIAdB5ABqIQoDQCAHQShqEARBAksgBCAXTnJFBEAgBygCQCAHKAI8QQN0aikCACIdQhCIp0H/AXEhCyAHKAJQIAcoAkxBA3RqKQIAIh5CEIinQf8BcSEJIAcoAkggBygCREEDdGopAgAiH0IgiKchCCAeQiCIISAgHUIgiKchAgJAIB9CEIinQf8BcSIDQQJPBEACQCAGRSADQRlJckUEQCAIIAdBKGogA0EgIAcoAixrIg0gDSADSxsiDRAFIAMgDWsiA3RqIQggB0EoahAEGiADRQ0BIAdBKGogAxAFIAhqIQgMAQsgB0EoaiADEAUgCGohCCAHQShqEAQaCyAHKQJUISEgByAINgJUIAcgITcDWAwBCwJAIANFBEAgAgRAIAcoAlQhCAwDCyAHKAJYIQgMAQsCQAJAIAdBKGpBARAFIAggAkVqaiIDQQNGBEAgBygCVEF/aiIDIANFaiEIDAELIANBAnQgB2ooAlQiCCAIRWohCCADQQFGDQELIAcgBygCWDYCXAsLIAcgBygCVDYCWCAHIAg2AlQLICCnIQMgCQRAIAdBKGogCRAFIANqIQMLIAkgC2pBFE8EQCAHQShqEAQaCyALBEAgB0EoaiALEAUgAmohAgsgB0EoahAEGiAHIAcoAmggAmoiCSADajYCaCAKIAwgCCAJSxsoAgAhDSAHIAdBKGogHUIYiKdB/wFxEAggHadB//8DcWo2AjwgByAHQShqIB5CGIinQf8BcRAIIB6nQf//A3FqNgJMIAdBKGoQBBogB0EoaiAfQhiIp0H/AXEQCCEOIAdB8ABqIARBBHRqIgsgCSANaiAIazYCDCALIAg2AgggCyADNgIEIAsgAjYCACAHIA4gH6dB//8DcWo2AkQgBEEBaiEEDAELCyAEIBdIDQEgEkFgaiEYIAdB4ABqIRogB0HkAGohGyABIQMDQCAHQShqEARBAksgBCAFTnJFBEAgBygCQCAHKAI8QQN0aikCACIdQhCIp0H/AXEhCyAHKAJQIAcoAkxBA3RqKQIAIh5CEIinQf8BcSEIIAcoAkggBygCREEDdGopAgAiH0IgiKchCSAeQiCIISAgHUIgiKchDAJAIB9CEIinQf8BcSICQQJPBEACQCAGRSACQRlJckUEQCAJIAdBKGogAkEgIAcoAixrIgogCiACSxsiChAFIAIgCmsiAnRqIQkgB0EoahAEGiACRQ0BIAdBKGogAhAFIAlqIQkMAQsgB0EoaiACEAUgCWohCSAHQShqEAQaCyAHKQJUISEgByAJNgJUIAcgITcDWAwBCwJAIAJFBEAgDARAIAcoAlQhCQwDCyAHKAJYIQkMAQsCQAJAIAdBKGpBARAFIAkgDEVqaiICQQNGBEAgBygCVEF/aiICIAJFaiEJDAELIAJBAnQgB2ooAlQiCSAJRWohCSACQQFGDQELIAcgBygCWDYCXAsLIAcgBygCVDYCWCAHIAk2AlQLICCnIRQgCARAIAdBKGogCBAFIBRqIRQLIAggC2pBFE8EQCAHQShqEAQaCyALBEAgB0EoaiALEAUgDGohDAsgB0EoahAEGiAHIAcoAmggDGoiGSAUajYCaCAbIBogCSAZSxsoAgAhHCAHIAdBKGogHUIYiKdB/wFxEAggHadB//8DcWo2AjwgByAHQShqIB5CGIinQf8BcRAIIB6nQf//A3FqNgJMIAdBKGoQBBogByAHQShqIB9CGIinQf8BcRAIIB+nQf//A3FqNgJEIAcgB0HwAGogBEEDcUEEdGoiDSkDCCIdNwPIASAHIA0pAwAiHjcDwAECQAJAAkAgBygCvAEiDiAepyICaiIWIBNLDQAgAyAHKALEASIKIAJqIgtqIBhLDQAgEiADayALQSBqTw0BCyAHIAcpA8gBNwMQIAcgBykDwAE3AwggAyASIAdBCGogB0G8AWogEyAPIBUgERAeIQsMAQsgAiADaiEIIAMgDhAHIAJBEU8EQCADQRBqIQIDQCACIA5BEGoiDhAHIAJBEGoiAiAISQ0ACwsgCCAdpyIOayECIAcgFjYCvAEgDiAIIA9rSwRAIA4gCCAVa0sEQEFsIQsMAgsgESACIA9rIgJqIhYgCmogEU0EQCAIIBYgChAPGgwCCyAIIBZBACACaxAPIQggByACIApqIgo2AsQBIAggAmshCCAPIQILIA5BEE8EQCAIIApqIQoDQCAIIAIQByACQRBqIQIgCEEQaiIIIApJDQALDAELAkAgDkEHTQRAIAggAi0AADoAACAIIAItAAE6AAEgCCACLQACOgACIAggAi0AAzoAAyAIQQRqIAIgDkECdCIKQcAeaigCAGoiAhAXIAIgCkHgHmooAgBrIQIgBygCxAEhCgwBCyAIIAIQDAsgCkEJSQ0AIAggCmohCiAIQQhqIgggAkEIaiICa0EPTARAA0AgCCACEAwgAkEIaiECIAhBCGoiCCAKSQ0ADAIACwALA0AgCCACEAcgAkEQaiECIAhBEGoiCCAKSQ0ACwsgCxADBEAgCyEQDAQFIA0gDDYCACANIBkgHGogCWs2AgwgDSAJNgIIIA0gFDYCBCAEQQFqIQQgAyALaiEDDAILAAsLIAQgBUgNASAEIBdrIQtBACEEA0AgCyAFSARAIAcgB0HwAGogC0EDcUEEdGoiAikDCCIdNwPIASAHIAIpAwAiHjcDwAECQAJAAkAgBygCvAEiDCAepyICaiIKIBNLDQAgAyAHKALEASIJIAJqIhBqIBhLDQAgEiADayAQQSBqTw0BCyAHIAcpA8gBNwMgIAcgBykDwAE3AxggAyASIAdBGGogB0G8AWogEyAPIBUgERAeIRAMAQsgAiADaiEIIAMgDBAHIAJBEU8EQCADQRBqIQIDQCACIAxBEGoiDBAHIAJBEGoiAiAISQ0ACwsgCCAdpyIGayECIAcgCjYCvAEgBiAIIA9rSwRAIAYgCCAVa0sEQEFsIRAMAgsgESACIA9rIgJqIgwgCWogEU0EQCAIIAwgCRAPGgwCCyAIIAxBACACaxAPIQggByACIAlqIgk2AsQBIAggAmshCCAPIQILIAZBEE8EQCAIIAlqIQYDQCAIIAIQByACQRBqIQIgCEEQaiIIIAZJDQALDAELAkAgBkEHTQRAIAggAi0AADoAACAIIAItAAE6AAEgCCACLQACOgACIAggAi0AAzoAAyAIQQRqIAIgBkECdCIGQcAeaigCAGoiAhAXIAIgBkHgHmooAgBrIQIgBygCxAEhCQwBCyAIIAIQDAsgCUEJSQ0AIAggCWohBiAIQQhqIgggAkEIaiICa0EPTARAA0AgCCACEAwgAkEIaiECIAhBCGoiCCAGSQ0ADAIACwALA0AgCCACEAcgAkEQaiECIAhBEGoiCCAGSQ0ACwsgEBADDQMgC0EBaiELIAMgEGohAwwBCwsDQCAEQQNHBEAgACAEQQJ0IgJqQazQAWogAiAHaigCVDYCACAEQQFqIQQMAQsLIAcoArwBIQgLQbp/IRAgEyAIayIAIBIgA2tLDQAgAwR/IAMgCCAAEAsgAGoFQQALIAFrIRALIAdB0AFqJAAgEAslACAAQgA3AgAgAEEAOwEIIABBADoACyAAIAE2AgwgACACOgAKC7QFAQN/IwBBMGsiBCQAIABB/wFqIgVBfWohBgJAIAMvAQIEQCAEQRhqIAEgAhAGIgIQAw0BIARBEGogBEEYaiADEBwgBEEIaiAEQRhqIAMQHCAAIQMDQAJAIARBGGoQBCADIAZPckUEQCADIARBEGogBEEYahASOgAAIAMgBEEIaiAEQRhqEBI6AAEgBEEYahAERQ0BIANBAmohAwsgBUF+aiEFAn8DQEG6fyECIAMiASAFSw0FIAEgBEEQaiAEQRhqEBI6AAAgAUEBaiEDIARBGGoQBEEDRgRAQQIhAiAEQQhqDAILIAMgBUsNBSABIARBCGogBEEYahASOgABIAFBAmohA0EDIQIgBEEYahAEQQNHDQALIARBEGoLIQUgAyAFIARBGGoQEjoAACABIAJqIABrIQIMAwsgAyAEQRBqIARBGGoQEjoAAiADIARBCGogBEEYahASOgADIANBBGohAwwAAAsACyAEQRhqIAEgAhAGIgIQAw0AIARBEGogBEEYaiADEBwgBEEIaiAEQRhqIAMQHCAAIQMDQAJAIARBGGoQBCADIAZPckUEQCADIARBEGogBEEYahAROgAAIAMgBEEIaiAEQRhqEBE6AAEgBEEYahAERQ0BIANBAmohAwsgBUF+aiEFAn8DQEG6fyECIAMiASAFSw0EIAEgBEEQaiAEQRhqEBE6AAAgAUEBaiEDIARBGGoQBEEDRgRAQQIhAiAEQQhqDAILIAMgBUsNBCABIARBCGogBEEYahAROgABIAFBAmohA0EDIQIgBEEYahAEQQNHDQALIARBEGoLIQUgAyAFIARBGGoQEToAACABIAJqIABrIQIMAgsgAyAEQRBqIARBGGoQEToAAiADIARBCGogBEEYahAROgADIANBBGohAwwAAAsACyAEQTBqJAAgAgtpAQF/An8CQAJAIAJBB00NACABKAAAQbfIwuF+Rw0AIAAgASgABDYCmOIBQWIgAEEQaiABIAIQPiIDEAMNAhogAEKBgICAEDcDiOEBIAAgASADaiACIANrECoMAQsgACABIAIQKgtBAAsLrQMBBn8jAEGAAWsiAyQAQWIhCAJAIAJBCUkNACAAQZjQAGogAUEIaiIEIAJBeGogAEGY0AAQMyIFEAMiBg0AIANBHzYCfCADIANB/ABqIANB+ABqIAQgBCAFaiAGGyIEIAEgAmoiAiAEaxAVIgUQAw0AIAMoAnwiBkEfSw0AIAMoAngiB0EJTw0AIABBiCBqIAMgBkGAC0GADCAHEBggA0E0NgJ8IAMgA0H8AGogA0H4AGogBCAFaiIEIAIgBGsQFSIFEAMNACADKAJ8IgZBNEsNACADKAJ4IgdBCk8NACAAQZAwaiADIAZBgA1B4A4gBxAYIANBIzYCfCADIANB/ABqIANB+ABqIAQgBWoiBCACIARrEBUiBRADDQAgAygCfCIGQSNLDQAgAygCeCIHQQpPDQAgACADIAZBwBBB0BEgBxAYIAQgBWoiBEEMaiIFIAJLDQAgAiAFayEFQQAhAgNAIAJBA0cEQCAEKAAAIgZBf2ogBU8NAiAAIAJBAnRqQZzQAWogBjYCACACQQFqIQIgBEEEaiEEDAELCyAEIAFrIQgLIANBgAFqJAAgCAtGAQN/IABBCGohAyAAKAIEIQJBACEAA0AgACACdkUEQCABIAMgAEEDdGotAAJBFktqIQEgAEEBaiEADAELCyABQQggAmt0C4YDAQV/Qbh/IQcCQCADRQ0AIAItAAAiBEUEQCABQQA2AgBBAUG4fyADQQFGGw8LAn8gAkEBaiIFIARBGHRBGHUiBkF/Sg0AGiAGQX9GBEAgA0EDSA0CIAUvAABBgP4BaiEEIAJBA2oMAQsgA0ECSA0BIAItAAEgBEEIdHJBgIB+aiEEIAJBAmoLIQUgASAENgIAIAVBAWoiASACIANqIgNLDQBBbCEHIABBEGogACAFLQAAIgVBBnZBI0EJIAEgAyABa0HAEEHQEUHwEiAAKAKM4QEgACgCnOIBIAQQHyIGEAMiCA0AIABBmCBqIABBCGogBUEEdkEDcUEfQQggASABIAZqIAgbIgEgAyABa0GAC0GADEGAFyAAKAKM4QEgACgCnOIBIAQQHyIGEAMiCA0AIABBoDBqIABBBGogBUECdkEDcUE0QQkgASABIAZqIAgbIgEgAyABa0GADUHgDkGQGSAAKAKM4QEgACgCnOIBIAQQHyIAEAMNACAAIAFqIAJrIQcLIAcLrQMBCn8jAEGABGsiCCQAAn9BUiACQf8BSw0AGkFUIANBDEsNABogAkEBaiELIABBBGohCUGAgAQgA0F/anRBEHUhCkEAIQJBASEEQQEgA3QiB0F/aiIMIQUDQCACIAtGRQRAAkAgASACQQF0Ig1qLwEAIgZB//8DRgRAIAkgBUECdGogAjoAAiAFQX9qIQVBASEGDAELIARBACAKIAZBEHRBEHVKGyEECyAIIA1qIAY7AQAgAkEBaiECDAELCyAAIAQ7AQIgACADOwEAIAdBA3YgB0EBdmpBA2ohBkEAIQRBACECA0AgBCALRkUEQCABIARBAXRqLgEAIQpBACEAA0AgACAKTkUEQCAJIAJBAnRqIAQ6AAIDQCACIAZqIAxxIgIgBUsNAAsgAEEBaiEADAELCyAEQQFqIQQMAQsLQX8gAg0AGkEAIQIDfyACIAdGBH9BAAUgCCAJIAJBAnRqIgAtAAJBAXRqIgEgAS8BACIBQQFqOwEAIAAgAyABEBRrIgU6AAMgACABIAVB/wFxdCAHazsBACACQQFqIQIMAQsLCyEFIAhBgARqJAAgBQvjBgEIf0FsIQcCQCACQQNJDQACQAJAAkACQCABLQAAIgNBA3EiCUEBaw4DAwEAAgsgACgCiOEBDQBBYg8LIAJBBUkNAkEDIQYgASgAACEFAn8CQAJAIANBAnZBA3EiCEF+aiIEQQFNBEAgBEEBaw0BDAILIAVBDnZB/wdxIQQgBUEEdkH/B3EhAyAIRQwCCyAFQRJ2IQRBBCEGIAVBBHZB//8AcSEDQQAMAQsgBUEEdkH//w9xIgNBgIAISw0DIAEtAARBCnQgBUEWdnIhBEEFIQZBAAshBSAEIAZqIgogAksNAgJAIANBgQZJDQAgACgCnOIBRQ0AQQAhAgNAIAJBg4ABSw0BIAJBQGshAgwAAAsACwJ/IAlBA0YEQCABIAZqIQEgAEHw4gFqIQIgACgCDCEGIAUEQCACIAMgASAEIAYQXwwCCyACIAMgASAEIAYQXQwBCyAAQbjQAWohAiABIAZqIQEgAEHw4gFqIQYgAEGo0ABqIQggBQRAIAggBiADIAEgBCACEF4MAQsgCCAGIAMgASAEIAIQXAsQAw0CIAAgAzYCgOIBIABBATYCiOEBIAAgAEHw4gFqNgLw4QEgCUECRgRAIAAgAEGo0ABqNgIMCyAAIANqIgBBiOMBakIANwAAIABBgOMBakIANwAAIABB+OIBakIANwAAIABB8OIBakIANwAAIAoPCwJ/AkACQAJAIANBAnZBA3FBf2oiBEECSw0AIARBAWsOAgACAQtBASEEIANBA3YMAgtBAiEEIAEvAABBBHYMAQtBAyEEIAEQIUEEdgsiAyAEaiIFQSBqIAJLBEAgBSACSw0CIABB8OIBaiABIARqIAMQCyEBIAAgAzYCgOIBIAAgATYC8OEBIAEgA2oiAEIANwAYIABCADcAECAAQgA3AAggAEIANwAAIAUPCyAAIAM2AoDiASAAIAEgBGo2AvDhASAFDwsCfwJAAkACQCADQQJ2QQNxQX9qIgRBAksNACAEQQFrDgIAAgELQQEhByADQQN2DAILQQIhByABLwAAQQR2DAELIAJBBEkgARAhIgJBj4CAAUtyDQFBAyEHIAJBBHYLIQIgAEHw4gFqIAEgB2otAAAgAkEgahAQIQEgACACNgKA4gEgACABNgLw4QEgB0EBaiEHCyAHC0sAIABC+erQ0OfJoeThADcDICAAQgA3AxggAELP1tO+0ser2UI3AxAgAELW64Lu6v2J9eAANwMIIABCADcDACAAQShqQQBBKBAQGgviAgICfwV+IABBKGoiASAAKAJIaiECAn4gACkDACIDQiBaBEAgACkDECIEQgeJIAApAwgiBUIBiXwgACkDGCIGQgyJfCAAKQMgIgdCEol8IAUQGSAEEBkgBhAZIAcQGQwBCyAAKQMYQsXP2bLx5brqJ3wLIAN8IQMDQCABQQhqIgAgAk0EQEIAIAEpAAAQCSADhUIbiUKHla+vmLbem55/fkLj3MqV/M7y9YV/fCEDIAAhAQwBCwsCQCABQQRqIgAgAksEQCABIQAMAQsgASgAAK1Ch5Wvr5i23puef34gA4VCF4lCz9bTvtLHq9lCfkL5893xmfaZqxZ8IQMLA0AgACACSQRAIAAxAABCxc/ZsvHluuonfiADhUILiUKHla+vmLbem55/fiEDIABBAWohAAwBCwsgA0IhiCADhULP1tO+0ser2UJ+IgNCHYggA4VC+fPd8Zn2masWfiIDQiCIIAOFC+8CAgJ/BH4gACAAKQMAIAKtfDcDAAJAAkAgACgCSCIDIAJqIgRBH00EQCABRQ0BIAAgA2pBKGogASACECAgACgCSCACaiEEDAELIAEgAmohAgJ/IAMEQCAAQShqIgQgA2ogAUEgIANrECAgACAAKQMIIAQpAAAQCTcDCCAAIAApAxAgACkAMBAJNwMQIAAgACkDGCAAKQA4EAk3AxggACAAKQMgIABBQGspAAAQCTcDICAAKAJIIQMgAEEANgJIIAEgA2tBIGohAQsgAUEgaiACTQsEQCACQWBqIQMgACkDICEFIAApAxghBiAAKQMQIQcgACkDCCEIA0AgCCABKQAAEAkhCCAHIAEpAAgQCSEHIAYgASkAEBAJIQYgBSABKQAYEAkhBSABQSBqIgEgA00NAAsgACAFNwMgIAAgBjcDGCAAIAc3AxAgACAINwMICyABIAJPDQEgAEEoaiABIAIgAWsiBBAgCyAAIAQ2AkgLCy8BAX8gAEUEQEG2f0EAIAMbDwtBun8hBCADIAFNBH8gACACIAMQEBogAwVBun8LCy8BAX8gAEUEQEG2f0EAIAMbDwtBun8hBCADIAFNBH8gACACIAMQCxogAwVBun8LC6gCAQZ/IwBBEGsiByQAIABB2OABaikDAEKAgIAQViEIQbh/IQUCQCAEQf//B0sNACAAIAMgBBBCIgUQAyIGDQAgACgCnOIBIQkgACAHQQxqIAMgAyAFaiAGGyIKIARBACAFIAYbayIGEEAiAxADBEAgAyEFDAELIAcoAgwhBCABRQRAQbp/IQUgBEEASg0BCyAGIANrIQUgAyAKaiEDAkAgCQRAIABBADYCnOIBDAELAkACQAJAIARBBUgNACAAQdjgAWopAwBCgICACFgNAAwBCyAAQQA2ApziAQwBCyAAKAIIED8hBiAAQQA2ApziASAGQRRPDQELIAAgASACIAMgBSAEIAgQOSEFDAELIAAgASACIAMgBSAEIAgQOiEFCyAHQRBqJAAgBQtnACAAQdDgAWogASACIAAoAuzhARAuIgEQAwRAIAEPC0G4fyECAkAgAQ0AIABB7OABaigCACIBBEBBYCECIAAoApjiASABRw0BC0EAIQIgAEHw4AFqKAIARQ0AIABBkOEBahBDCyACCycBAX8QVyIERQRAQUAPCyAEIAAgASACIAMgBBBLEE8hACAEEFYgAAs/AQF/AkACQAJAIAAoAqDiAUEBaiIBQQJLDQAgAUEBaw4CAAECCyAAEDBBAA8LIABBADYCoOIBCyAAKAKU4gELvAMCB38BfiMAQRBrIgkkAEG4fyEGAkAgBCgCACIIQQVBCSAAKALs4QEiBRtJDQAgAygCACIHQQFBBSAFGyAFEC8iBRADBEAgBSEGDAELIAggBUEDakkNACAAIAcgBRBJIgYQAw0AIAEgAmohCiAAQZDhAWohCyAIIAVrIQIgBSAHaiEHIAEhBQNAIAcgAiAJECwiBhADDQEgAkF9aiICIAZJBEBBuH8hBgwCCyAJKAIAIghBAksEQEFsIQYMAgsgB0EDaiEHAn8CQAJAAkAgCEEBaw4CAgABCyAAIAUgCiAFayAHIAYQSAwCCyAFIAogBWsgByAGEEcMAQsgBSAKIAVrIActAAAgCSgCCBBGCyIIEAMEQCAIIQYMAgsgACgC8OABBEAgCyAFIAgQRQsgAiAGayECIAYgB2ohByAFIAhqIQUgCSgCBEUNAAsgACkD0OABIgxCf1IEQEFsIQYgDCAFIAFrrFINAQsgACgC8OABBEBBaiEGIAJBBEkNASALEEQhDCAHKAAAIAynRw0BIAdBBGohByACQXxqIQILIAMgBzYCACAEIAI2AgAgBSABayEGCyAJQRBqJAAgBgsuACAAECsCf0EAQQAQAw0AGiABRSACRXJFBEBBYiAAIAEgAhA9EAMNARoLQQALCzcAIAEEQCAAIAAoAsTgASABKAIEIAEoAghqRzYCnOIBCyAAECtBABADIAFFckUEQCAAIAEQWwsL0QIBB38jAEEQayIGJAAgBiAENgIIIAYgAzYCDCAFBEAgBSgCBCEKIAUoAgghCQsgASEIAkACQANAIAAoAuzhARAWIQsCQANAIAQgC0kNASADKAAAQXBxQdDUtMIBRgRAIAMgBBAiIgcQAw0EIAQgB2shBCADIAdqIQMMAQsLIAYgAzYCDCAGIAQ2AggCQCAFBEAgACAFEE5BACEHQQAQA0UNAQwFCyAAIAogCRBNIgcQAw0ECyAAIAgQUCAMQQFHQQAgACAIIAIgBkEMaiAGQQhqEEwiByIDa0EAIAMQAxtBCkdyRQRAQbh/IQcMBAsgBxADDQMgAiAHayECIAcgCGohCEEBIQwgBigCDCEDIAYoAgghBAwBCwsgBiADNgIMIAYgBDYCCEG4fyEHIAQNASAIIAFrIQcMAQsgBiADNgIMIAYgBDYCCAsgBkEQaiQAIAcLRgECfyABIAAoArjgASICRwRAIAAgAjYCxOABIAAgATYCuOABIAAoArzgASEDIAAgATYCvOABIAAgASADIAJrajYCwOABCwutAgIEfwF+IwBBQGoiBCQAAkACQCACQQhJDQAgASgAAEFwcUHQ1LTCAUcNACABIAIQIiEBIABCADcDCCAAQQA2AgQgACABNgIADAELIARBGGogASACEC0iAxADBEAgACADEBoMAQsgAwRAIABBuH8QGgwBCyACIAQoAjAiA2shAiABIANqIQMDQAJAIAAgAyACIARBCGoQLCIFEAMEfyAFBSACIAVBA2oiBU8NAUG4fwsQGgwCCyAGQQFqIQYgAiAFayECIAMgBWohAyAEKAIMRQ0ACyAEKAI4BEAgAkEDTQRAIABBuH8QGgwCCyADQQRqIQMLIAQoAighAiAEKQMYIQcgAEEANgIEIAAgAyABazYCACAAIAIgBmytIAcgB0J/URs3AwgLIARBQGskAAslAQF/IwBBEGsiAiQAIAIgACABEFEgAigCACEAIAJBEGokACAAC30BBH8jAEGQBGsiBCQAIARB/wE2AggCQCAEQRBqIARBCGogBEEMaiABIAIQFSIGEAMEQCAGIQUMAQtBVCEFIAQoAgwiB0EGSw0AIAMgBEEQaiAEKAIIIAcQQSIFEAMNACAAIAEgBmogAiAGayADEDwhBQsgBEGQBGokACAFC4cBAgJ/An5BABAWIQMCQANAIAEgA08EQAJAIAAoAABBcHFB0NS0wgFGBEAgACABECIiAhADRQ0BQn4PCyAAIAEQVSIEQn1WDQMgBCAFfCIFIARUIQJCfiEEIAINAyAAIAEQUiICEAMNAwsgASACayEBIAAgAmohAAwBCwtCfiAFIAEbIQQLIAQLPwIBfwF+IwBBMGsiAiQAAn5CfiACQQhqIAAgARAtDQAaQgAgAigCHEEBRg0AGiACKQMICyEDIAJBMGokACADC40BAQJ/IwBBMGsiASQAAkAgAEUNACAAKAKI4gENACABIABB/OEBaigCADYCKCABIAApAvThATcDICAAEDAgACgCqOIBIQIgASABKAIoNgIYIAEgASkDIDcDECACIAFBEGoQGyAAQQA2AqjiASABIAEoAig2AgggASABKQMgNwMAIAAgARAbCyABQTBqJAALKgECfyMAQRBrIgAkACAAQQA2AgggAEIANwMAIAAQWCEBIABBEGokACABC4cBAQN/IwBBEGsiAiQAAkAgACgCAEUgACgCBEVzDQAgAiAAKAIINgIIIAIgACkCADcDAAJ/IAIoAgAiAQRAIAIoAghBqOMJIAERBQAMAQtBqOMJECgLIgFFDQAgASAAKQIANwL04QEgAUH84QFqIAAoAgg2AgAgARBZIAEhAwsgAkEQaiQAIAMLywEBAn8jAEEgayIBJAAgAEGBgIDAADYCtOIBIABBADYCiOIBIABBADYC7OEBIABCADcDkOIBIABBADYCpOMJIABBADYC3OIBIABCADcCzOIBIABBADYCvOIBIABBADYCxOABIABCADcCnOIBIABBpOIBakIANwIAIABBrOIBakEANgIAIAFCADcCECABQgA3AhggASABKQMYNwMIIAEgASkDEDcDACABKAIIQQh2QQFxIQIgAEEANgLg4gEgACACNgKM4gEgAUEgaiQAC3YBA38jAEEwayIBJAAgAARAIAEgAEHE0AFqIgIoAgA2AiggASAAKQK80AE3AyAgACgCACEDIAEgAigCADYCGCABIAApArzQATcDECADIAFBEGoQGyABIAEoAig2AgggASABKQMgNwMAIAAgARAbCyABQTBqJAALzAEBAX8gACABKAK00AE2ApjiASAAIAEoAgQiAjYCwOABIAAgAjYCvOABIAAgAiABKAIIaiICNgK44AEgACACNgLE4AEgASgCuNABBEAgAEKBgICAEDcDiOEBIAAgAUGk0ABqNgIMIAAgAUGUIGo2AgggACABQZwwajYCBCAAIAFBDGo2AgAgAEGs0AFqIAFBqNABaigCADYCACAAQbDQAWogAUGs0AFqKAIANgIAIABBtNABaiABQbDQAWooAgA2AgAPCyAAQgA3A4jhAQs7ACACRQRAQbp/DwsgBEUEQEFsDwsgAiAEEGAEQCAAIAEgAiADIAQgBRBhDwsgACABIAIgAyAEIAUQZQtGAQF/IwBBEGsiBSQAIAVBCGogBBAOAn8gBS0ACQRAIAAgASACIAMgBBAyDAELIAAgASACIAMgBBA0CyEAIAVBEGokACAACzQAIAAgAyAEIAUQNiIFEAMEQCAFDwsgBSAESQR/IAEgAiADIAVqIAQgBWsgABA1BUG4fwsLRgEBfyMAQRBrIgUkACAFQQhqIAQQDgJ/IAUtAAkEQCAAIAEgAiADIAQQYgwBCyAAIAEgAiADIAQQNQshACAFQRBqJAAgAAtZAQF/QQ8hAiABIABJBEAgAUEEdCAAbiECCyAAQQh2IgEgAkEYbCIAQYwIaigCAGwgAEGICGooAgBqIgJBA3YgAmogAEGACGooAgAgAEGECGooAgAgAWxqSQs3ACAAIAMgBCAFQYAQEDMiBRADBEAgBQ8LIAUgBEkEfyABIAIgAyAFaiAEIAVrIAAQMgVBuH8LC78DAQN/IwBBIGsiBSQAIAVBCGogAiADEAYiAhADRQRAIAAgAWoiB0F9aiEGIAUgBBAOIARBBGohAiAFLQACIQMDQEEAIAAgBkkgBUEIahAEGwRAIAAgAiAFQQhqIAMQAkECdGoiBC8BADsAACAFQQhqIAQtAAIQASAAIAQtAANqIgQgAiAFQQhqIAMQAkECdGoiAC8BADsAACAFQQhqIAAtAAIQASAEIAAtAANqIQAMAQUgB0F+aiEEA0AgBUEIahAEIAAgBEtyRQRAIAAgAiAFQQhqIAMQAkECdGoiBi8BADsAACAFQQhqIAYtAAIQASAAIAYtAANqIQAMAQsLA0AgACAES0UEQCAAIAIgBUEIaiADEAJBAnRqIgYvAQA7AAAgBUEIaiAGLQACEAEgACAGLQADaiEADAELCwJAIAAgB08NACAAIAIgBUEIaiADEAIiA0ECdGoiAC0AADoAACAALQADQQFGBEAgBUEIaiAALQACEAEMAQsgBSgCDEEfSw0AIAVBCGogAiADQQJ0ai0AAhABIAUoAgxBIUkNACAFQSA2AgwLIAFBbCAFQQhqEAobIQILCwsgBUEgaiQAIAILkgIBBH8jAEFAaiIJJAAgCSADQTQQCyEDAkAgBEECSA0AIAMgBEECdGooAgAhCSADQTxqIAgQIyADQQE6AD8gAyACOgA+QQAhBCADKAI8IQoDQCAEIAlGDQEgACAEQQJ0aiAKNgEAIARBAWohBAwAAAsAC0EAIQkDQCAGIAlGRQRAIAMgBSAJQQF0aiIKLQABIgtBAnRqIgwoAgAhBCADQTxqIAotAABBCHQgCGpB//8DcRAjIANBAjoAPyADIAcgC2siCiACajoAPiAEQQEgASAKa3RqIQogAygCPCELA0AgACAEQQJ0aiALNgEAIARBAWoiBCAKSQ0ACyAMIAo2AgAgCUEBaiEJDAELCyADQUBrJAALowIBCX8jAEHQAGsiCSQAIAlBEGogBUE0EAsaIAcgBmshDyAHIAFrIRADQAJAIAMgCkcEQEEBIAEgByACIApBAXRqIgYtAAEiDGsiCGsiC3QhDSAGLQAAIQ4gCUEQaiAMQQJ0aiIMKAIAIQYgCyAPTwRAIAAgBkECdGogCyAIIAUgCEE0bGogCCAQaiIIQQEgCEEBShsiCCACIAQgCEECdGooAgAiCEEBdGogAyAIayAHIA4QYyAGIA1qIQgMAgsgCUEMaiAOECMgCUEBOgAPIAkgCDoADiAGIA1qIQggCSgCDCELA0AgBiAITw0CIAAgBkECdGogCzYBACAGQQFqIQYMAAALAAsgCUHQAGokAA8LIAwgCDYCACAKQQFqIQoMAAALAAs0ACAAIAMgBCAFEDYiBRADBEAgBQ8LIAUgBEkEfyABIAIgAyAFaiAEIAVrIAAQNAVBuH8LCyMAIAA/AEEQdGtB//8DakEQdkAAQX9GBEBBAA8LQQAQAEEBCzsBAX8gAgRAA0AgACABIAJBgCAgAkGAIEkbIgMQCyEAIAFBgCBqIQEgAEGAIGohACACIANrIgINAAsLCwYAIAAQAwsLqBUJAEGICAsNAQAAAAEAAAACAAAAAgBBoAgLswYBAAAAAQAAAAIAAAACAAAAJgAAAIIAAAAhBQAASgAAAGcIAAAmAAAAwAEAAIAAAABJBQAASgAAAL4IAAApAAAALAIAAIAAAABJBQAASgAAAL4IAAAvAAAAygIAAIAAAACKBQAASgAAAIQJAAA1AAAAcwMAAIAAAACdBQAASgAAAKAJAAA9AAAAgQMAAIAAAADrBQAASwAAAD4KAABEAAAAngMAAIAAAABNBgAASwAAAKoKAABLAAAAswMAAIAAAADBBgAATQAAAB8NAABNAAAAUwQAAIAAAAAjCAAAUQAAAKYPAABUAAAAmQQAAIAAAABLCQAAVwAAALESAABYAAAA2gQAAIAAAABvCQAAXQAAACMUAABUAAAARQUAAIAAAABUCgAAagAAAIwUAABqAAAArwUAAIAAAAB2CQAAfAAAAE4QAAB8AAAA0gIAAIAAAABjBwAAkQAAAJAHAACSAAAAAAAAAAEAAAABAAAABQAAAA0AAAAdAAAAPQAAAH0AAAD9AAAA/QEAAP0DAAD9BwAA/Q8AAP0fAAD9PwAA/X8AAP3/AAD9/wEA/f8DAP3/BwD9/w8A/f8fAP3/PwD9/38A/f//AP3//wH9//8D/f//B/3//w/9//8f/f//P/3//38AAAAAAQAAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAAMAAAADQAAAA4AAAAPAAAAEAAAABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABcAAAAYAAAAGQAAABoAAAAbAAAAHAAAAB0AAAAeAAAAHwAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAAA8AAAAQAAAAEQAAABIAAAATAAAAFAAAABUAAAAWAAAAFwAAABgAAAAZAAAAGgAAABsAAAAcAAAAHQAAAB4AAAAfAAAAIAAAACEAAAAiAAAAIwAAACUAAAAnAAAAKQAAACsAAAAvAAAAMwAAADsAAABDAAAAUwAAAGMAAACDAAAAAwEAAAMCAAADBAAAAwgAAAMQAAADIAAAA0AAAAOAAAADAAEAQeAPC1EBAAAAAQAAAAEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAcAAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAAOAAAADwAAABAAQcQQC4sBAQAAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAAMAAAADQAAAA4AAAAPAAAAEAAAABIAAAAUAAAAFgAAABgAAAAcAAAAIAAAACgAAAAwAAAAQAAAAIAAAAAAAQAAAAIAAAAEAAAACAAAABAAAAAgAAAAQAAAAIAAAAAAAQBBkBIL5gQBAAAAAQAAAAEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAAMAAAADQAAAA4AAAAPAAAAEAAAAAEAAAAEAAAACAAAAAAAAAABAAEBBgAAAAAAAAQAAAAAEAAABAAAAAAgAAAFAQAAAAAAAAUDAAAAAAAABQQAAAAAAAAFBgAAAAAAAAUHAAAAAAAABQkAAAAAAAAFCgAAAAAAAAUMAAAAAAAABg4AAAAAAAEFEAAAAAAAAQUUAAAAAAABBRYAAAAAAAIFHAAAAAAAAwUgAAAAAAAEBTAAAAAgAAYFQAAAAAAABwWAAAAAAAAIBgABAAAAAAoGAAQAAAAADAYAEAAAIAAABAAAAAAAAAAEAQAAAAAAAAUCAAAAIAAABQQAAAAAAAAFBQAAACAAAAUHAAAAAAAABQgAAAAgAAAFCgAAAAAAAAULAAAAAAAABg0AAAAgAAEFEAAAAAAAAQUSAAAAIAABBRYAAAAAAAIFGAAAACAAAwUgAAAAAAADBSgAAAAAAAYEQAAAABAABgRAAAAAIAAHBYAAAAAAAAkGAAIAAAAACwYACAAAMAAABAAAAAAQAAAEAQAAACAAAAUCAAAAIAAABQMAAAAgAAAFBQAAACAAAAUGAAAAIAAABQgAAAAgAAAFCQAAACAAAAULAAAAIAAABQwAAAAAAAAGDwAAACAAAQUSAAAAIAABBRQAAAAgAAIFGAAAACAAAgUcAAAAIAADBSgAAAAgAAQFMAAAAAAAEAYAAAEAAAAPBgCAAAAAAA4GAEAAAAAADQYAIABBgBcLhwIBAAEBBQAAAAAAAAUAAAAAAAAGBD0AAAAAAAkF/QEAAAAADwX9fwAAAAAVBf3/HwAAAAMFBQAAAAAABwR9AAAAAAAMBf0PAAAAABIF/f8DAAAAFwX9/38AAAAFBR0AAAAAAAgE/QAAAAAADgX9PwAAAAAUBf3/DwAAAAIFAQAAABAABwR9AAAAAAALBf0HAAAAABEF/f8BAAAAFgX9/z8AAAAEBQ0AAAAQAAgE/QAAAAAADQX9HwAAAAATBf3/BwAAAAEFAQAAABAABgQ9AAAAAAAKBf0DAAAAABAF/f8AAAAAHAX9//8PAAAbBf3//wcAABoF/f//AwAAGQX9//8BAAAYBf3//wBBkBkLhgQBAAEBBgAAAAAAAAYDAAAAAAAABAQAAAAgAAAFBQAAAAAAAAUGAAAAAAAABQgAAAAAAAAFCQAAAAAAAAULAAAAAAAABg0AAAAAAAAGEAAAAAAAAAYTAAAAAAAABhYAAAAAAAAGGQAAAAAAAAYcAAAAAAAABh8AAAAAAAAGIgAAAAAAAQYlAAAAAAABBikAAAAAAAIGLwAAAAAAAwY7AAAAAAAEBlMAAAAAAAcGgwAAAAAACQYDAgAAEAAABAQAAAAAAAAEBQAAACAAAAUGAAAAAAAABQcAAAAgAAAFCQAAAAAAAAUKAAAAAAAABgwAAAAAAAAGDwAAAAAAAAYSAAAAAAAABhUAAAAAAAAGGAAAAAAAAAYbAAAAAAAABh4AAAAAAAAGIQAAAAAAAQYjAAAAAAABBicAAAAAAAIGKwAAAAAAAwYzAAAAAAAEBkMAAAAAAAUGYwAAAAAACAYDAQAAIAAABAQAAAAwAAAEBAAAABAAAAQFAAAAIAAABQcAAAAgAAAFCAAAACAAAAUKAAAAIAAABQsAAAAAAAAGDgAAAAAAAAYRAAAAAAAABhQAAAAAAAAGFwAAAAAAAAYaAAAAAAAABh0AAAAAAAAGIAAAAAAAEAYDAAEAAAAPBgOAAAAAAA4GA0AAAAAADQYDIAAAAAAMBgMQAAAAAAsGAwgAAAAACgYDBABBpB0L2QEBAAAAAwAAAAcAAAAPAAAAHwAAAD8AAAB/AAAA/wAAAP8BAAD/AwAA/wcAAP8PAAD/HwAA/z8AAP9/AAD//wAA//8BAP//AwD//wcA//8PAP//HwD//z8A//9/AP///wD///8B////A////wf///8P////H////z////9/AAAAAAEAAAACAAAABAAAAAAAAAACAAAABAAAAAgAAAAAAAAAAQAAAAIAAAABAAAABAAAAAQAAAAEAAAABAAAAAgAAAAIAAAACAAAAAcAAAAIAAAACQAAAAoAAAALAEGgIAsDwBBQ';
  73910. /**
  73911. * Loader for KTX 2.0 GPU Texture containers.
  73912. *
  73913. * KTX 2.0 is a container format for various GPU texture formats. The loader
  73914. * supports Basis Universal GPU textures, which can be quickly transcoded to
  73915. * a wide variety of GPU texture compression formats, as well as some
  73916. * uncompressed DataTexture and Data3DTexture formats.
  73917. *
  73918. * References:
  73919. * - KTX: http://github.khronos.org/KTX-Specification/
  73920. * - DFD: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor
  73921. */
  73922. const _taskCache$1 = new WeakMap();
  73923. let _activeLoaders = 0;
  73924. let _zstd;
  73925. class KTX2Loader extends Loader {
  73926. constructor( manager ) {
  73927. super( manager );
  73928. this.transcoderPath = '';
  73929. this.transcoderBinary = null;
  73930. this.transcoderPending = null;
  73931. this.workerPool = new WorkerPool$1();
  73932. this.workerSourceURL = '';
  73933. this.workerConfig = null;
  73934. if ( typeof MSC_TRANSCODER !== 'undefined' ) {
  73935. console.warn(
  73936. 'THREE.KTX2Loader: Please update to latest "basis_transcoder".'
  73937. + ' "msc_basis_transcoder" is no longer supported in three.js r125+.'
  73938. );
  73939. }
  73940. }
  73941. setTranscoderPath( path ) {
  73942. this.transcoderPath = path;
  73943. return this;
  73944. }
  73945. setWorkerLimit( num ) {
  73946. this.workerPool.setWorkerLimit( num );
  73947. return this;
  73948. }
  73949. detectSupport( renderer ) {
  73950. this.workerConfig = {
  73951. astcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_astc' ),
  73952. etc1Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc1' ),
  73953. etc2Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc' ),
  73954. dxtSupported: renderer.extensions.has( 'WEBGL_compressed_texture_s3tc' ),
  73955. bptcSupported: renderer.extensions.has( 'EXT_texture_compression_bptc' ),
  73956. pvrtcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_pvrtc' )
  73957. || renderer.extensions.has( 'WEBKIT_WEBGL_compressed_texture_pvrtc' )
  73958. };
  73959. if ( renderer.capabilities.isWebGL2 ) {
  73960. // https://github.com/mrdoob/three.js/pull/22928
  73961. this.workerConfig.etc1Supported = false;
  73962. }
  73963. return this;
  73964. }
  73965. init() {
  73966. if ( ! this.transcoderPending ) {
  73967. // Load transcoder wrapper.
  73968. const jsLoader = new FileLoader( this.manager );
  73969. jsLoader.setPath( this.transcoderPath );
  73970. jsLoader.setWithCredentials( this.withCredentials );
  73971. const jsContent = jsLoader.loadAsync( 'basis_transcoder.js' );
  73972. // Load transcoder WASM binary.
  73973. const binaryLoader = new FileLoader( this.manager );
  73974. binaryLoader.setPath( this.transcoderPath );
  73975. binaryLoader.setResponseType( 'arraybuffer' );
  73976. binaryLoader.setWithCredentials( this.withCredentials );
  73977. const binaryContent = binaryLoader.loadAsync( 'basis_transcoder.wasm' );
  73978. this.transcoderPending = Promise.all( [ jsContent, binaryContent ] )
  73979. .then( ( [ jsContent, binaryContent ] ) => {
  73980. const fn = KTX2Loader.BasisWorker.toString();
  73981. const body = [
  73982. '/* constants */',
  73983. 'let _EngineFormat = ' + JSON.stringify( KTX2Loader.EngineFormat ),
  73984. 'let _TranscoderFormat = ' + JSON.stringify( KTX2Loader.TranscoderFormat ),
  73985. 'let _BasisFormat = ' + JSON.stringify( KTX2Loader.BasisFormat ),
  73986. '/* basis_transcoder.js */',
  73987. jsContent,
  73988. '/* worker */',
  73989. fn.substring( fn.indexOf( '{' ) + 1, fn.lastIndexOf( '}' ) )
  73990. ].join( '\n' );
  73991. this.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) );
  73992. this.transcoderBinary = binaryContent;
  73993. this.workerPool.setWorkerCreator( () => {
  73994. const worker = new Worker( this.workerSourceURL );
  73995. const transcoderBinary = this.transcoderBinary.slice( 0 );
  73996. worker.postMessage( { type: 'init', config: this.workerConfig, transcoderBinary }, [ transcoderBinary ] );
  73997. return worker;
  73998. } );
  73999. } );
  74000. if ( _activeLoaders > 0 ) {
  74001. // Each instance loads a transcoder and allocates workers, increasing network and memory cost.
  74002. console.warn(
  74003. 'THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues.'
  74004. + ' Use a single KTX2Loader instance, or call .dispose() on old instances.'
  74005. );
  74006. }
  74007. _activeLoaders ++;
  74008. }
  74009. return this.transcoderPending;
  74010. }
  74011. load( url, onLoad, onProgress, onError ) {
  74012. if ( this.workerConfig === null ) {
  74013. throw new Error( 'THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.' );
  74014. }
  74015. const loader = new FileLoader( this.manager );
  74016. loader.setResponseType( 'arraybuffer' );
  74017. loader.setWithCredentials( this.withCredentials );
  74018. loader.load( url, ( buffer ) => {
  74019. // Check for an existing task using this buffer. A transferred buffer cannot be transferred
  74020. // again from this thread.
  74021. if ( _taskCache$1.has( buffer ) ) {
  74022. const cachedTask = _taskCache$1.get( buffer );
  74023. return cachedTask.promise.then( onLoad ).catch( onError );
  74024. }
  74025. this._createTexture( buffer )
  74026. .then( ( texture ) => onLoad ? onLoad( texture ) : null )
  74027. .catch( onError );
  74028. }, onProgress, onError );
  74029. }
  74030. _createTextureFrom( transcodeResult, container ) {
  74031. const { mipmaps, width, height, format, type, error, dfdTransferFn, dfdFlags } = transcodeResult;
  74032. if ( type === 'error' ) return Promise.reject( error );
  74033. const texture = container.layerCount > 1
  74034. ? new CompressedArrayTexture( mipmaps, width, height, container.layerCount, format, UnsignedByteType )
  74035. : new CompressedTexture( mipmaps, width, height, format, UnsignedByteType );
  74036. texture.minFilter = mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter;
  74037. texture.magFilter = LinearFilter;
  74038. texture.generateMipmaps = false;
  74039. texture.needsUpdate = true;
  74040. texture.encoding = dfdTransferFn === x$1 ? sRGBEncoding : LinearEncoding;
  74041. texture.premultiplyAlpha = !! ( dfdFlags & p );
  74042. return texture;
  74043. }
  74044. /**
  74045. * @param {ArrayBuffer} buffer
  74046. * @param {object?} config
  74047. * @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
  74048. */
  74049. async _createTexture( buffer, config = {} ) {
  74050. const container = Pi( new Uint8Array( buffer ) );
  74051. if ( container.vkFormat !== nt ) {
  74052. return createDataTexture( container );
  74053. }
  74054. //
  74055. const taskConfig = config;
  74056. const texturePending = this.init().then( () => {
  74057. return this.workerPool.postMessage( { type: 'transcode', buffer, taskConfig: taskConfig }, [ buffer ] );
  74058. } ).then( ( e ) => this._createTextureFrom( e.data, container ) );
  74059. // Cache the task result.
  74060. _taskCache$1.set( buffer, { promise: texturePending } );
  74061. return texturePending;
  74062. }
  74063. dispose() {
  74064. this.workerPool.dispose();
  74065. if ( this.workerSourceURL ) URL.revokeObjectURL( this.workerSourceURL );
  74066. _activeLoaders --;
  74067. return this;
  74068. }
  74069. }
  74070. /* CONSTANTS */
  74071. KTX2Loader.BasisFormat = {
  74072. ETC1S: 0,
  74073. UASTC_4x4: 1,
  74074. };
  74075. KTX2Loader.TranscoderFormat = {
  74076. ETC1: 0,
  74077. ETC2: 1,
  74078. BC1: 2,
  74079. BC3: 3,
  74080. BC4: 4,
  74081. BC5: 5,
  74082. BC7_M6_OPAQUE_ONLY: 6,
  74083. BC7_M5: 7,
  74084. PVRTC1_4_RGB: 8,
  74085. PVRTC1_4_RGBA: 9,
  74086. ASTC_4x4: 10,
  74087. ATC_RGB: 11,
  74088. ATC_RGBA_INTERPOLATED_ALPHA: 12,
  74089. RGBA32: 13,
  74090. RGB565: 14,
  74091. BGR565: 15,
  74092. RGBA4444: 16,
  74093. };
  74094. KTX2Loader.EngineFormat = {
  74095. RGBAFormat: RGBAFormat,
  74096. RGBA_ASTC_4x4_Format: RGBA_ASTC_4x4_Format,
  74097. RGBA_BPTC_Format: RGBA_BPTC_Format,
  74098. RGBA_ETC2_EAC_Format: RGBA_ETC2_EAC_Format,
  74099. RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format,
  74100. RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format$1,
  74101. RGB_ETC1_Format: RGB_ETC1_Format,
  74102. RGB_ETC2_Format: RGB_ETC2_Format,
  74103. RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format,
  74104. RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format,
  74105. };
  74106. /* WEB WORKER */
  74107. KTX2Loader.BasisWorker = function () {
  74108. let config;
  74109. let transcoderPending;
  74110. let BasisModule;
  74111. const EngineFormat = _EngineFormat; // eslint-disable-line no-undef
  74112. const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef
  74113. const BasisFormat = _BasisFormat; // eslint-disable-line no-undef
  74114. self.addEventListener( 'message', function ( e ) {
  74115. const message = e.data;
  74116. switch ( message.type ) {
  74117. case 'init':
  74118. config = message.config;
  74119. init( message.transcoderBinary );
  74120. break;
  74121. case 'transcode':
  74122. transcoderPending.then( () => {
  74123. try {
  74124. const { width, height, hasAlpha, mipmaps, format, dfdTransferFn, dfdFlags } = transcode( message.buffer );
  74125. const buffers = [];
  74126. for ( let i = 0; i < mipmaps.length; ++ i ) {
  74127. buffers.push( mipmaps[ i ].data.buffer );
  74128. }
  74129. self.postMessage( { type: 'transcode', id: message.id, width, height, hasAlpha, mipmaps, format, dfdTransferFn, dfdFlags }, buffers );
  74130. } catch ( error ) {
  74131. console.error( error );
  74132. self.postMessage( { type: 'error', id: message.id, error: error.message } );
  74133. }
  74134. } );
  74135. break;
  74136. }
  74137. } );
  74138. function init( wasmBinary ) {
  74139. transcoderPending = new Promise( ( resolve ) => {
  74140. BasisModule = { wasmBinary, onRuntimeInitialized: resolve };
  74141. BASIS( BasisModule ); // eslint-disable-line no-undef
  74142. } ).then( () => {
  74143. BasisModule.initializeBasis();
  74144. if ( BasisModule.KTX2File === undefined ) {
  74145. console.warn( 'THREE.KTX2Loader: Please update Basis Universal transcoder.' );
  74146. }
  74147. } );
  74148. }
  74149. function transcode( buffer ) {
  74150. const ktx2File = new BasisModule.KTX2File( new Uint8Array( buffer ) );
  74151. function cleanup() {
  74152. ktx2File.close();
  74153. ktx2File.delete();
  74154. }
  74155. if ( ! ktx2File.isValid() ) {
  74156. cleanup();
  74157. throw new Error( 'THREE.KTX2Loader: Invalid or unsupported .ktx2 file' );
  74158. }
  74159. const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
  74160. const width = ktx2File.getWidth();
  74161. const height = ktx2File.getHeight();
  74162. const layers = ktx2File.getLayers() || 1;
  74163. const levels = ktx2File.getLevels();
  74164. const hasAlpha = ktx2File.getHasAlpha();
  74165. const dfdTransferFn = ktx2File.getDFDTransferFunc();
  74166. const dfdFlags = ktx2File.getDFDFlags();
  74167. const { transcoderFormat, engineFormat } = getTranscoderFormat( basisFormat, width, height, hasAlpha );
  74168. if ( ! width || ! height || ! levels ) {
  74169. cleanup();
  74170. throw new Error( 'THREE.KTX2Loader: Invalid texture' );
  74171. }
  74172. if ( ! ktx2File.startTranscoding() ) {
  74173. cleanup();
  74174. throw new Error( 'THREE.KTX2Loader: .startTranscoding failed' );
  74175. }
  74176. const mipmaps = [];
  74177. for ( let mip = 0; mip < levels; mip ++ ) {
  74178. const layerMips = [];
  74179. let mipWidth, mipHeight;
  74180. for ( let layer = 0; layer < layers; layer ++ ) {
  74181. const levelInfo = ktx2File.getImageLevelInfo( mip, layer, 0 );
  74182. mipWidth = levelInfo.origWidth;
  74183. mipHeight = levelInfo.origHeight;
  74184. const dst = new Uint8Array( ktx2File.getImageTranscodedSizeInBytes( mip, layer, 0, transcoderFormat ) );
  74185. const status = ktx2File.transcodeImage(
  74186. dst,
  74187. mip,
  74188. layer,
  74189. 0,
  74190. transcoderFormat,
  74191. 0,
  74192. - 1,
  74193. - 1,
  74194. );
  74195. if ( ! status ) {
  74196. cleanup();
  74197. throw new Error( 'THREE.KTX2Loader: .transcodeImage failed.' );
  74198. }
  74199. layerMips.push( dst );
  74200. }
  74201. mipmaps.push( { data: concat( layerMips ), width: mipWidth, height: mipHeight } );
  74202. }
  74203. cleanup();
  74204. return { width, height, hasAlpha, mipmaps, format: engineFormat, dfdTransferFn, dfdFlags };
  74205. }
  74206. //
  74207. // Optimal choice of a transcoder target format depends on the Basis format (ETC1S or UASTC),
  74208. // device capabilities, and texture dimensions. The list below ranks the formats separately
  74209. // for ETC1S and UASTC.
  74210. //
  74211. // In some cases, transcoding UASTC to RGBA32 might be preferred for higher quality (at
  74212. // significant memory cost) compared to ETC1/2, BC1/3, and PVRTC. The transcoder currently
  74213. // chooses RGBA32 only as a last resort and does not expose that option to the caller.
  74214. const FORMAT_OPTIONS = [
  74215. {
  74216. if: 'astcSupported',
  74217. basisFormat: [ BasisFormat.UASTC_4x4 ],
  74218. transcoderFormat: [ TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4 ],
  74219. engineFormat: [ EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format ],
  74220. priorityETC1S: Infinity,
  74221. priorityUASTC: 1,
  74222. needsPowerOfTwo: false,
  74223. },
  74224. {
  74225. if: 'bptcSupported',
  74226. basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
  74227. transcoderFormat: [ TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5 ],
  74228. engineFormat: [ EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format ],
  74229. priorityETC1S: 3,
  74230. priorityUASTC: 2,
  74231. needsPowerOfTwo: false,
  74232. },
  74233. {
  74234. if: 'dxtSupported',
  74235. basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
  74236. transcoderFormat: [ TranscoderFormat.BC1, TranscoderFormat.BC3 ],
  74237. engineFormat: [ EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format ],
  74238. priorityETC1S: 4,
  74239. priorityUASTC: 5,
  74240. needsPowerOfTwo: false,
  74241. },
  74242. {
  74243. if: 'etc2Supported',
  74244. basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
  74245. transcoderFormat: [ TranscoderFormat.ETC1, TranscoderFormat.ETC2 ],
  74246. engineFormat: [ EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format ],
  74247. priorityETC1S: 1,
  74248. priorityUASTC: 3,
  74249. needsPowerOfTwo: false,
  74250. },
  74251. {
  74252. if: 'etc1Supported',
  74253. basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
  74254. transcoderFormat: [ TranscoderFormat.ETC1 ],
  74255. engineFormat: [ EngineFormat.RGB_ETC1_Format ],
  74256. priorityETC1S: 2,
  74257. priorityUASTC: 4,
  74258. needsPowerOfTwo: false,
  74259. },
  74260. {
  74261. if: 'pvrtcSupported',
  74262. basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
  74263. transcoderFormat: [ TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA ],
  74264. engineFormat: [ EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format ],
  74265. priorityETC1S: 5,
  74266. priorityUASTC: 6,
  74267. needsPowerOfTwo: true,
  74268. },
  74269. ];
  74270. const ETC1S_OPTIONS = FORMAT_OPTIONS.sort( function ( a, b ) {
  74271. return a.priorityETC1S - b.priorityETC1S;
  74272. } );
  74273. const UASTC_OPTIONS = FORMAT_OPTIONS.sort( function ( a, b ) {
  74274. return a.priorityUASTC - b.priorityUASTC;
  74275. } );
  74276. function getTranscoderFormat( basisFormat, width, height, hasAlpha ) {
  74277. let transcoderFormat;
  74278. let engineFormat;
  74279. const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
  74280. for ( let i = 0; i < options.length; i ++ ) {
  74281. const opt = options[ i ];
  74282. if ( ! config[ opt.if ] ) continue;
  74283. if ( ! opt.basisFormat.includes( basisFormat ) ) continue;
  74284. if ( hasAlpha && opt.transcoderFormat.length < 2 ) continue;
  74285. if ( opt.needsPowerOfTwo && ! ( isPowerOfTwo( width ) && isPowerOfTwo( height ) ) ) continue;
  74286. transcoderFormat = opt.transcoderFormat[ hasAlpha ? 1 : 0 ];
  74287. engineFormat = opt.engineFormat[ hasAlpha ? 1 : 0 ];
  74288. return { transcoderFormat, engineFormat };
  74289. }
  74290. console.warn( 'THREE.KTX2Loader: No suitable compressed texture format found. Decoding to RGBA32.' );
  74291. transcoderFormat = TranscoderFormat.RGBA32;
  74292. engineFormat = EngineFormat.RGBAFormat;
  74293. return { transcoderFormat, engineFormat };
  74294. }
  74295. function isPowerOfTwo( value ) {
  74296. if ( value <= 2 ) return true;
  74297. return ( value & ( value - 1 ) ) === 0 && value !== 0;
  74298. }
  74299. /** Concatenates N byte arrays. */
  74300. function concat( arrays ) {
  74301. let totalByteLength = 0;
  74302. for ( const array of arrays ) {
  74303. totalByteLength += array.byteLength;
  74304. }
  74305. const result = new Uint8Array( totalByteLength );
  74306. let byteOffset = 0;
  74307. for ( const array of arrays ) {
  74308. result.set( array, byteOffset );
  74309. byteOffset += array.byteLength;
  74310. }
  74311. return result;
  74312. }
  74313. };
  74314. //
  74315. // DataTexture and Data3DTexture parsing.
  74316. const FORMAT_MAP = {
  74317. [ Ae ]: RGBAFormat,
  74318. [ pe ]: RGBAFormat,
  74319. [ Ot ]: RGBAFormat,
  74320. [ Ft ]: RGBAFormat,
  74321. [ de ]: RGFormat,
  74322. [ se ]: RGFormat,
  74323. [ yt ]: RGFormat,
  74324. [ dt ]: RGFormat,
  74325. [ xe ]: RedFormat,
  74326. [ $t ]: RedFormat,
  74327. [ gt ]: RedFormat,
  74328. [ ct ]: RedFormat,
  74329. };
  74330. const TYPE_MAP = {
  74331. [ Ae ]: FloatType,
  74332. [ pe ]: HalfFloatType,
  74333. [ Ot ]: UnsignedByteType,
  74334. [ Ft ]: UnsignedByteType,
  74335. [ de ]: FloatType,
  74336. [ se ]: HalfFloatType,
  74337. [ yt ]: UnsignedByteType,
  74338. [ dt ]: UnsignedByteType,
  74339. [ xe ]: FloatType,
  74340. [ $t ]: HalfFloatType,
  74341. [ gt ]: UnsignedByteType,
  74342. [ ct ]: UnsignedByteType,
  74343. };
  74344. const ENCODING_MAP = {
  74345. [ Ft ]: sRGBEncoding,
  74346. [ dt ]: sRGBEncoding,
  74347. [ gt ]: sRGBEncoding,
  74348. };
  74349. async function createDataTexture( container ) {
  74350. const { vkFormat, pixelWidth, pixelHeight, pixelDepth } = container;
  74351. if ( FORMAT_MAP[ vkFormat ] === undefined ) {
  74352. throw new Error( 'THREE.KTX2Loader: Unsupported vkFormat.' );
  74353. }
  74354. const level = container.levels[ 0 ];
  74355. let levelData;
  74356. let view;
  74357. if ( container.supercompressionScheme === t ) {
  74358. levelData = level.levelData;
  74359. } else if ( container.supercompressionScheme === n$1 ) {
  74360. if ( ! _zstd ) {
  74361. _zstd = new Promise( async ( resolve ) => {
  74362. const zstd = new ZSTDDecoder();
  74363. await zstd.init();
  74364. resolve( zstd );
  74365. } );
  74366. }
  74367. levelData = ( await _zstd ).decode( level.levelData, level.uncompressedByteLength );
  74368. } else {
  74369. throw new Error( 'THREE.KTX2Loader: Unsupported supercompressionScheme.' );
  74370. }
  74371. if ( TYPE_MAP[ vkFormat ] === FloatType ) {
  74372. view = new Float32Array(
  74373. levelData.buffer,
  74374. levelData.byteOffset,
  74375. levelData.byteLength / Float32Array.BYTES_PER_ELEMENT
  74376. );
  74377. } else if ( TYPE_MAP[ vkFormat ] === HalfFloatType ) {
  74378. view = new Uint16Array(
  74379. levelData.buffer,
  74380. levelData.byteOffset,
  74381. levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT
  74382. );
  74383. } else {
  74384. view = levelData;
  74385. }
  74386. //
  74387. const texture = pixelDepth === 0
  74388. ? new DataTexture( view, pixelWidth, pixelHeight )
  74389. : new Data3DTexture( view, pixelWidth, pixelHeight, pixelDepth );
  74390. texture.type = TYPE_MAP[ vkFormat ];
  74391. texture.format = FORMAT_MAP[ vkFormat ];
  74392. texture.encoding = ENCODING_MAP[ vkFormat ] || LinearEncoding;
  74393. texture.needsUpdate = true;
  74394. //
  74395. return Promise.resolve( texture );
  74396. }
  74397. // This file is part of meshoptimizer library and is distributed under the terms of MIT License.
  74398. // Copyright (C) 2016-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
  74399. var MeshoptDecoder = (function() {
  74400. "use strict";
  74401. // Built with clang version 11.0.0 (https://github.com/llvm/llvm-project.git 0160ad802e899c2922bc9b29564080c22eb0908c)
  74402. // Built from meshoptimizer 0.14
  74403. var wasm_base = "B9h9z9tFBBBF8fL9gBB9gLaaaaaFa9gEaaaB9gFaFa9gEaaaFaEMcBFFFGGGEIIILF9wFFFLEFBFKNFaFCx/IFMO/LFVK9tv9t9vq95GBt9f9f939h9z9t9f9j9h9s9s9f9jW9vq9zBBp9tv9z9o9v9wW9f9kv9j9v9kv9WvqWv94h919m9mvqBF8Z9tv9z9o9v9wW9f9kv9j9v9kv9J9u9kv94h919m9mvqBGy9tv9z9o9v9wW9f9kv9j9v9kv9J9u9kv949TvZ91v9u9jvBEn9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9P9jWBIi9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9R919hWBLn9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9F949wBKI9z9iqlBOc+x8ycGBM/qQFTa8jUUUUBCU/EBlHL8kUUUUBC9+RKGXAGCFJAI9LQBCaRKAE2BBC+gF9HQBALAEAIJHOAGlAGTkUUUBRNCUoBAG9uC/wgBZHKCUGAKCUG9JyRVAECFJRICBRcGXEXAcAF9PQFAVAFAclAcAVJAF9JyRMGXGXAG9FQBAMCbJHKC9wZRSAKCIrCEJCGrRQANCUGJRfCBRbAIRTEXGXAOATlAQ9PQBCBRISEMATAQJRIGXAS9FQBCBRtCBREEXGXAOAIlCi9PQBCBRISLMANCU/CBJAEJRKGXGXGXGXGXATAECKrJ2BBAtCKZrCEZfIBFGEBMAKhB83EBAKCNJhB83EBSEMAKAI2BIAI2BBHmCKrHYAYCE6HYy86BBAKCFJAICIJAYJHY2BBAmCIrCEZHPAPCE6HPy86BBAKCGJAYAPJHY2BBAmCGrCEZHPAPCE6HPy86BBAKCEJAYAPJHY2BBAmCEZHmAmCE6Hmy86BBAKCIJAYAmJHY2BBAI2BFHmCKrHPAPCE6HPy86BBAKCLJAYAPJHY2BBAmCIrCEZHPAPCE6HPy86BBAKCKJAYAPJHY2BBAmCGrCEZHPAPCE6HPy86BBAKCOJAYAPJHY2BBAmCEZHmAmCE6Hmy86BBAKCNJAYAmJHY2BBAI2BGHmCKrHPAPCE6HPy86BBAKCVJAYAPJHY2BBAmCIrCEZHPAPCE6HPy86BBAKCcJAYAPJHY2BBAmCGrCEZHPAPCE6HPy86BBAKCMJAYAPJHY2BBAmCEZHmAmCE6Hmy86BBAKCSJAYAmJHm2BBAI2BEHICKrHYAYCE6HYy86BBAKCQJAmAYJHm2BBAICIrCEZHYAYCE6HYy86BBAKCfJAmAYJHm2BBAICGrCEZHYAYCE6HYy86BBAKCbJAmAYJHK2BBAICEZHIAICE6HIy86BBAKAIJRISGMAKAI2BNAI2BBHmCIrHYAYCb6HYy86BBAKCFJAICNJAYJHY2BBAmCbZHmAmCb6Hmy86BBAKCGJAYAmJHm2BBAI2BFHYCIrHPAPCb6HPy86BBAKCEJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCIJAmAYJHm2BBAI2BGHYCIrHPAPCb6HPy86BBAKCLJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCKJAmAYJHm2BBAI2BEHYCIrHPAPCb6HPy86BBAKCOJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCNJAmAYJHm2BBAI2BIHYCIrHPAPCb6HPy86BBAKCVJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCcJAmAYJHm2BBAI2BLHYCIrHPAPCb6HPy86BBAKCMJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCSJAmAYJHm2BBAI2BKHYCIrHPAPCb6HPy86BBAKCQJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCfJAmAYJHm2BBAI2BOHICIrHYAYCb6HYy86BBAKCbJAmAYJHK2BBAICbZHIAICb6HIy86BBAKAIJRISFMAKAI8pBB83BBAKCNJAICNJ8pBB83BBAICTJRIMAtCGJRtAECTJHEAS9JQBMMGXAIQBCBRISEMGXAM9FQBANAbJ2BBRtCBRKAfREEXAEANCU/CBJAKJ2BBHTCFrCBATCFZl9zAtJHt86BBAEAGJREAKCFJHKAM9HQBMMAfCFJRfAIRTAbCFJHbAG9HQBMMABAcAG9sJANCUGJAMAG9sTkUUUBpANANCUGJAMCaJAG9sJAGTkUUUBpMAMCBAIyAcJRcAIQBMC9+RKSFMCBC99AOAIlAGCAAGCA9Ly6yRKMALCU/EBJ8kUUUUBAKM+OmFTa8jUUUUBCoFlHL8kUUUUBC9+RKGXAFCE9uHOCtJAI9LQBCaRKAE2BBHNC/wFZC/gF9HQBANCbZHVCF9LQBALCoBJCgFCUFT+JUUUBpALC84Jha83EBALC8wJha83EBALC8oJha83EBALCAJha83EBALCiJha83EBALCTJha83EBALha83ENALha83EBAEAIJC9wJRcAECFJHNAOJRMGXAF9FQBCQCbAVCF6yRSABRECBRVCBRQCBRfCBRICBRKEXGXAMAcuQBC9+RKSEMGXGXAN2BBHOC/vF9LQBALCoBJAOCIrCa9zAKJCbZCEWJHb8oGIRTAb8oGBRtGXAOCbZHbAS9PQBALAOCa9zAIJCbZCGWJ8oGBAVAbyROAb9FRbGXGXAGCG9HQBABAt87FBABCIJAO87FBABCGJAT87FBSFMAEAtjGBAECNJAOjGBAECIJATjGBMAVAbJRVALCoBJAKCEWJHmAOjGBAmATjGIALAICGWJAOjGBALCoBJAKCFJCbZHKCEWJHTAtjGBATAOjGIAIAbJRIAKCFJRKSGMGXGXAbCb6QBAQAbJAbC989zJCFJRQSFMAM1BBHbCgFZROGXGXAbCa9MQBAMCFJRMSFMAM1BFHbCgBZCOWAOCgBZqROGXAbCa9MQBAMCGJRMSFMAM1BGHbCgBZCfWAOqROGXAbCa9MQBAMCEJRMSFMAM1BEHbCgBZCdWAOqROGXAbCa9MQBAMCIJRMSFMAM2BIC8cWAOqROAMCLJRMMAOCFrCBAOCFZl9zAQJRQMGXGXAGCG9HQBABAt87FBABCIJAQ87FBABCGJAT87FBSFMAEAtjGBAECNJAQjGBAECIJATjGBMALCoBJAKCEWJHOAQjGBAOATjGIALAICGWJAQjGBALCoBJAKCFJCbZHKCEWJHOAtjGBAOAQjGIAICFJRIAKCFJRKSFMGXAOCDF9LQBALAIAcAOCbZJ2BBHbCIrHTlCbZCGWJ8oGBAVCFJHtATyROALAIAblCbZCGWJ8oGBAtAT9FHmJHtAbCbZHTyRbAT9FRTGXGXAGCG9HQBABAV87FBABCIJAb87FBABCGJAO87FBSFMAEAVjGBAECNJAbjGBAECIJAOjGBMALAICGWJAVjGBALCoBJAKCEWJHYAOjGBAYAVjGIALAICFJHICbZCGWJAOjGBALCoBJAKCFJCbZCEWJHYAbjGBAYAOjGIALAIAmJCbZHICGWJAbjGBALCoBJAKCGJCbZHKCEWJHOAVjGBAOAbjGIAKCFJRKAIATJRIAtATJRVSFMAVCBAM2BBHYyHTAOC/+F6HPJROAYCbZRtGXGXAYCIrHmQBAOCFJRbSFMAORbALAIAmlCbZCGWJ8oGBROMGXGXAtQBAbCFJRVSFMAbRVALAIAYlCbZCGWJ8oGBRbMGXGXAP9FQBAMCFJRYSFMAM1BFHYCgFZRTGXGXAYCa9MQBAMCGJRYSFMAM1BGHYCgBZCOWATCgBZqRTGXAYCa9MQBAMCEJRYSFMAM1BEHYCgBZCfWATqRTGXAYCa9MQBAMCIJRYSFMAM1BIHYCgBZCdWATqRTGXAYCa9MQBAMCLJRYSFMAMCKJRYAM2BLC8cWATqRTMATCFrCBATCFZl9zAQJHQRTMGXGXAmCb6QBAYRPSFMAY1BBHMCgFZROGXGXAMCa9MQBAYCFJRPSFMAY1BFHMCgBZCOWAOCgBZqROGXAMCa9MQBAYCGJRPSFMAY1BGHMCgBZCfWAOqROGXAMCa9MQBAYCEJRPSFMAY1BEHMCgBZCdWAOqROGXAMCa9MQBAYCIJRPSFMAYCLJRPAY2BIC8cWAOqROMAOCFrCBAOCFZl9zAQJHQROMGXGXAtCb6QBAPRMSFMAP1BBHMCgFZRbGXGXAMCa9MQBAPCFJRMSFMAP1BFHMCgBZCOWAbCgBZqRbGXAMCa9MQBAPCGJRMSFMAP1BGHMCgBZCfWAbqRbGXAMCa9MQBAPCEJRMSFMAP1BEHMCgBZCdWAbqRbGXAMCa9MQBAPCIJRMSFMAPCLJRMAP2BIC8cWAbqRbMAbCFrCBAbCFZl9zAQJHQRbMGXGXAGCG9HQBABAT87FBABCIJAb87FBABCGJAO87FBSFMAEATjGBAECNJAbjGBAECIJAOjGBMALCoBJAKCEWJHYAOjGBAYATjGIALAICGWJATjGBALCoBJAKCFJCbZCEWJHYAbjGBAYAOjGIALAICFJHICbZCGWJAOjGBALCoBJAKCGJCbZCEWJHOATjGBAOAbjGIALAIAm9FAmCb6qJHICbZCGWJAbjGBAIAt9FAtCb6qJRIAKCEJRKMANCFJRNABCKJRBAECSJREAKCbZRKAICbZRIAfCEJHfAF9JQBMMCBC99AMAc6yRKMALCoFJ8kUUUUBAKM/tIFGa8jUUUUBCTlRLC9+RKGXAFCLJAI9LQBCaRKAE2BBC/+FZC/QF9HQBALhB83ENAECFJRKAEAIJC98JREGXAF9FQBGXAGCG6QBEXGXAKAE9JQBC9+bMAK1BBHGCgFZRIGXGXAGCa9MQBAKCFJRKSFMAK1BFHGCgBZCOWAICgBZqRIGXAGCa9MQBAKCGJRKSFMAK1BGHGCgBZCfWAIqRIGXAGCa9MQBAKCEJRKSFMAK1BEHGCgBZCdWAIqRIGXAGCa9MQBAKCIJRKSFMAK2BIC8cWAIqRIAKCLJRKMALCNJAICFZCGWqHGAICGrCBAICFrCFZl9zAG8oGBJHIjGBABAIjGBABCIJRBAFCaJHFQBSGMMEXGXAKAE9JQBC9+bMAK1BBHGCgFZRIGXGXAGCa9MQBAKCFJRKSFMAK1BFHGCgBZCOWAICgBZqRIGXAGCa9MQBAKCGJRKSFMAK1BGHGCgBZCfWAIqRIGXAGCa9MQBAKCEJRKSFMAK1BEHGCgBZCdWAIqRIGXAGCa9MQBAKCIJRKSFMAK2BIC8cWAIqRIAKCLJRKMABAICGrCBAICFrCFZl9zALCNJAICFZCGWqHI8oGBJHG87FBAIAGjGBABCGJRBAFCaJHFQBMMCBC99AKAE6yRKMAKM+lLKFaF99GaG99FaG99GXGXAGCI9HQBAF9FQFEXGXGX9DBBB8/9DBBB+/ABCGJHG1BB+yAB1BBHE+yHI+L+TABCFJHL1BBHK+yHO+L+THN9DBBBB9gHVyAN9DBB/+hANAN+U9DBBBBANAVyHcAc+MHMAECa3yAI+SHIAI+UAcAMAKCa3yAO+SHcAc+U+S+S+R+VHO+U+SHN+L9DBBB9P9d9FQBAN+oRESFMCUUUU94REMAGAE86BBGXGX9DBBB8/9DBBB+/Ac9DBBBB9gyAcAO+U+SHN+L9DBBB9P9d9FQBAN+oRGSFMCUUUU94RGMALAG86BBGXGX9DBBB8/9DBBB+/AI9DBBBB9gyAIAO+U+SHN+L9DBBB9P9d9FQBAN+oRGSFMCUUUU94RGMABAG86BBABCIJRBAFCaJHFQBSGMMAF9FQBEXGXGX9DBBB8/9DBBB+/ABCIJHG8uFB+yAB8uFBHE+yHI+L+TABCGJHL8uFBHK+yHO+L+THN9DBBBB9gHVyAN9DB/+g6ANAN+U9DBBBBANAVyHcAc+MHMAECa3yAI+SHIAI+UAcAMAKCa3yAO+SHcAc+U+S+S+R+VHO+U+SHN+L9DBBB9P9d9FQBAN+oRESFMCUUUU94REMAGAE87FBGXGX9DBBB8/9DBBB+/Ac9DBBBB9gyAcAO+U+SHN+L9DBBB9P9d9FQBAN+oRGSFMCUUUU94RGMALAG87FBGXGX9DBBB8/9DBBB+/AI9DBBBB9gyAIAO+U+SHN+L9DBBB9P9d9FQBAN+oRGSFMCUUUU94RGMABAG87FBABCNJRBAFCaJHFQBMMM/SEIEaE99EaF99GXAF9FQBCBREABRIEXGXGX9D/zI818/AICKJ8uFBHLCEq+y+VHKAI8uFB+y+UHO9DB/+g6+U9DBBB8/9DBBB+/AO9DBBBB9gy+SHN+L9DBBB9P9d9FQBAN+oRVSFMCUUUU94RVMAICIJ8uFBRcAICGJ8uFBRMABALCFJCEZAEqCFWJAV87FBGXGXAKAM+y+UHN9DB/+g6+U9DBBB8/9DBBB+/AN9DBBBB9gy+SHS+L9DBBB9P9d9FQBAS+oRMSFMCUUUU94RMMABALCGJCEZAEqCFWJAM87FBGXGXAKAc+y+UHK9DB/+g6+U9DBBB8/9DBBB+/AK9DBBBB9gy+SHS+L9DBBB9P9d9FQBAS+oRcSFMCUUUU94RcMABALCaJCEZAEqCFWJAc87FBGXGX9DBBU8/AOAO+U+TANAN+U+TAKAK+U+THO9DBBBBAO9DBBBB9gy+R9DB/+g6+U9DBBB8/+SHO+L9DBBB9P9d9FQBAO+oRcSFMCUUUU94RcMABALCEZAEqCFWJAc87FBAICNJRIAECIJREAFCaJHFQBMMM9JBGXAGCGrAF9sHF9FQBEXABAB8oGBHGCNWCN91+yAGCi91CnWCUUU/8EJ+++U84GBABCIJRBAFCaJHFQBMMM9TFEaCBCB8oGUkUUBHFABCEJC98ZJHBjGUkUUBGXGXAB8/BCTWHGuQBCaREABAGlCggEJCTrXBCa6QFMAFREMAEM/lFFFaGXGXAFABqCEZ9FQBABRESFMGXGXAGCT9PQBABRESFMABREEXAEAF8oGBjGBAECIJAFCIJ8oGBjGBAECNJAFCNJ8oGBjGBAECSJAFCSJ8oGBjGBAECTJREAFCTJRFAGC9wJHGCb9LQBMMAGCI9JQBEXAEAF8oGBjGBAFCIJRFAECIJREAGC98JHGCE9LQBMMGXAG9FQBEXAEAF2BB86BBAECFJREAFCFJRFAGCaJHGQBMMABMoFFGaGXGXABCEZ9FQBABRESFMAFCgFZC+BwsN9sRIGXGXAGCT9PQBABRESFMABREEXAEAIjGBAECSJAIjGBAECNJAIjGBAECIJAIjGBAECTJREAGC9wJHGCb9LQBMMAGCI9JQBEXAEAIjGBAECIJREAGC98JHGCE9LQBMMGXAG9FQBEXAEAF86BBAECFJREAGCaJHGQBMMABMMMFBCUNMIT9kBB";
  74404. var wasm_simd = "B9h9z9tFBBBFiI9gBB9gLaaaaaFa9gEaaaB9gFaFaEMcBBFBFFGGGEILF9wFFFLEFBFKNFaFCx/aFMO/LFVK9tv9t9vq95GBt9f9f939h9z9t9f9j9h9s9s9f9jW9vq9zBBp9tv9z9o9v9wW9f9kv9j9v9kv9WvqWv94h919m9mvqBG8Z9tv9z9o9v9wW9f9kv9j9v9kv9J9u9kv94h919m9mvqBIy9tv9z9o9v9wW9f9kv9j9v9kv9J9u9kv949TvZ91v9u9jvBLn9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9P9jWBKi9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9R919hWBOn9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9F949wBNI9z9iqlBVc+N9IcIBTEM9+FLa8jUUUUBCTlRBCBRFEXCBRGCBREEXABCNJAGJAECUaAFAGrCFZHIy86BBAEAIJREAGCFJHGCN9HQBMAFCx+YUUBJAE86BBAFCEWCxkUUBJAB8pEN83EBAFCFJHFCUG9HQBMMk8lLbaE97F9+FaL978jUUUUBCU/KBlHL8kUUUUBC9+RKGXAGCFJAI9LQBCaRKAE2BBC+gF9HQBALAEAIJHOAGlAG/8cBBCUoBAG9uC/wgBZHKCUGAKCUG9JyRNAECFJRKCBRVGXEXAVAF9PQFANAFAVlAVANJAF9JyRcGXGXAG9FQBAcCbJHIC9wZHMCE9sRSAMCFWRQAICIrCEJCGrRfCBRbEXAKRTCBRtGXEXGXAOATlAf9PQBCBRKSLMALCU/CBJAtAM9sJRmATAfJRKCBREGXAMCoB9JQBAOAKlC/gB9JQBCBRIEXAmAIJREGXGXGXGXGXATAICKrJ2BBHYCEZfIBFGEBMAECBDtDMIBSEMAEAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHiCEWCxkUUBJDBEBAiCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHiCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIBAKCIJAeDeBJAiCx+YUUBJ2BBJRKSGMAEAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHiCEWCxkUUBJDBEBAiCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHiCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIBAKCNJAeDeBJAiCx+YUUBJ2BBJRKSFMAEAKDBBBDMIBAKCTJRKMGXGXGXGXGXAYCGrCEZfIBFGEBMAECBDtDMITSEMAEAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHiCEWCxkUUBJDBEBAiCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHiCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMITAKCIJAeDeBJAiCx+YUUBJ2BBJRKSGMAEAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHiCEWCxkUUBJDBEBAiCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHiCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMITAKCNJAeDeBJAiCx+YUUBJ2BBJRKSFMAEAKDBBBDMITAKCTJRKMGXGXGXGXGXAYCIrCEZfIBFGEBMAECBDtDMIASEMAEAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHiCEWCxkUUBJDBEBAiCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHiCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIAAKCIJAeDeBJAiCx+YUUBJ2BBJRKSGMAEAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHiCEWCxkUUBJDBEBAiCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHiCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIAAKCNJAeDeBJAiCx+YUUBJ2BBJRKSFMAEAKDBBBDMIAAKCTJRKMGXGXGXGXGXAYCKrfIBFGEBMAECBDtDMI8wSEMAEAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHYCEWCxkUUBJDBEBAYCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHYCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMI8wAKCIJAeDeBJAYCx+YUUBJ2BBJRKSGMAEAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHYCEWCxkUUBJDBEBAYCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHYCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMI8wAKCNJAeDeBJAYCx+YUUBJ2BBJRKSFMAEAKDBBBDMI8wAKCTJRKMAICoBJREAICUFJAM9LQFAERIAOAKlC/fB9LQBMMGXAEAM9PQBAECErRIEXGXAOAKlCi9PQBCBRKSOMAmAEJRYGXGXGXGXGXATAECKrJ2BBAICKZrCEZfIBFGEBMAYCBDtDMIBSEMAYAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHiCEWCxkUUBJDBEBAiCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHiCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIBAKCIJAeDeBJAiCx+YUUBJ2BBJRKSGMAYAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPAPDQBFGENVcMILKOSQfbHeD8dBh+BsxoxoUwN0AeD8dFhxoUwkwk+gUa0sHnhTkAnsHnhNkAnsHn7CgFZHiCEWCxkUUBJDBEBAiCx+YUUBJDBBBHeAeDQBBBBBBBBBBBBBBBBAnhAk7CgFZHiCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIBAKCNJAeDeBJAiCx+YUUBJ2BBJRKSFMAYAKDBBBDMIBAKCTJRKMAICGJRIAECTJHEAM9JQBMMGXAK9FQBAKRTAtCFJHtCI6QGSFMMCBRKSEMGXAM9FQBALCUGJAbJREALAbJDBGBReCBRYEXAEALCU/CBJAYJHIDBIBHdCFD9tAdCFDbHPD9OD9hD9RHdAIAMJDBIBH8ZCFD9tA8ZAPD9OD9hD9RH8ZDQBTFtGmEYIPLdKeOnHpAIAQJDBIBHyCFD9tAyAPD9OD9hD9RHyAIASJDBIBH8cCFD9tA8cAPD9OD9hD9RH8cDQBTFtGmEYIPLdKeOnH8dDQBFTtGEmYILPdKOenHPAPDQBFGEBFGEBFGEBFGEAeD9uHeDyBjGBAEAGJHIAeAPAPDQILKOILKOILKOILKOD9uHeDyBjGBAIAGJHIAeAPAPDQNVcMNVcMNVcMNVcMD9uHeDyBjGBAIAGJHIAeAPAPDQSQfbSQfbSQfbSQfbD9uHeDyBjGBAIAGJHIAeApA8dDQNVi8ZcMpySQ8c8dfb8e8fHPAPDQBFGEBFGEBFGEBFGED9uHeDyBjGBAIAGJHIAeAPAPDQILKOILKOILKOILKOD9uHeDyBjGBAIAGJHIAeAPAPDQNVcMNVcMNVcMNVcMD9uHeDyBjGBAIAGJHIAeAPAPDQSQfbSQfbSQfbSQfbD9uHeDyBjGBAIAGJHIAeAdA8ZDQNiV8ZcpMyS8cQ8df8eb8fHdAyA8cDQNiV8ZcpMyS8cQ8df8eb8fH8ZDQBFTtGEmYILPdKOenHPAPDQBFGEBFGEBFGEBFGED9uHeDyBjGBAIAGJHIAeAPAPDQILKOILKOILKOILKOD9uHeDyBjGBAIAGJHIAeAPAPDQNVcMNVcMNVcMNVcMD9uHeDyBjGBAIAGJHIAeAPAPDQSQfbSQfbSQfbSQfbD9uHeDyBjGBAIAGJHIAeAdA8ZDQNVi8ZcMpySQ8c8dfb8e8fHPAPDQBFGEBFGEBFGEBFGED9uHeDyBjGBAIAGJHIAeAPAPDQILKOILKOILKOILKOD9uHeDyBjGBAIAGJHIAeAPAPDQNVcMNVcMNVcMNVcMD9uHeDyBjGBAIAGJHIAeAPAPDQSQfbSQfbSQfbSQfbD9uHeDyBjGBAIAGJREAYCTJHYAM9JQBMMAbCIJHbAG9JQBMMABAVAG9sJALCUGJAcAG9s/8cBBALALCUGJAcCaJAG9sJAG/8cBBMAcCBAKyAVJRVAKQBMC9+RKSFMCBC99AOAKlAGCAAGCA9Ly6yRKMALCU/KBJ8kUUUUBAKMNBT+BUUUBM+KmFTa8jUUUUBCoFlHL8kUUUUBC9+RKGXAFCE9uHOCtJAI9LQBCaRKAE2BBHNC/wFZC/gF9HQBANCbZHVCF9LQBALCoBJCgFCUF/8MBALC84Jha83EBALC8wJha83EBALC8oJha83EBALCAJha83EBALCiJha83EBALCTJha83EBALha83ENALha83EBAEAIJC9wJRcAECFJHNAOJRMGXAF9FQBCQCbAVCF6yRSABRECBRVCBRQCBRfCBRICBRKEXGXAMAcuQBC9+RKSEMGXGXAN2BBHOC/vF9LQBALCoBJAOCIrCa9zAKJCbZCEWJHb8oGIRTAb8oGBRtGXAOCbZHbAS9PQBALAOCa9zAIJCbZCGWJ8oGBAVAbyROAb9FRbGXGXAGCG9HQBABAt87FBABCIJAO87FBABCGJAT87FBSFMAEAtjGBAECNJAOjGBAECIJATjGBMAVAbJRVALCoBJAKCEWJHmAOjGBAmATjGIALAICGWJAOjGBALCoBJAKCFJCbZHKCEWJHTAtjGBATAOjGIAIAbJRIAKCFJRKSGMGXGXAbCb6QBAQAbJAbC989zJCFJRQSFMAM1BBHbCgFZROGXGXAbCa9MQBAMCFJRMSFMAM1BFHbCgBZCOWAOCgBZqROGXAbCa9MQBAMCGJRMSFMAM1BGHbCgBZCfWAOqROGXAbCa9MQBAMCEJRMSFMAM1BEHbCgBZCdWAOqROGXAbCa9MQBAMCIJRMSFMAM2BIC8cWAOqROAMCLJRMMAOCFrCBAOCFZl9zAQJRQMGXGXAGCG9HQBABAt87FBABCIJAQ87FBABCGJAT87FBSFMAEAtjGBAECNJAQjGBAECIJATjGBMALCoBJAKCEWJHOAQjGBAOATjGIALAICGWJAQjGBALCoBJAKCFJCbZHKCEWJHOAtjGBAOAQjGIAICFJRIAKCFJRKSFMGXAOCDF9LQBALAIAcAOCbZJ2BBHbCIrHTlCbZCGWJ8oGBAVCFJHtATyROALAIAblCbZCGWJ8oGBAtAT9FHmJHtAbCbZHTyRbAT9FRTGXGXAGCG9HQBABAV87FBABCIJAb87FBABCGJAO87FBSFMAEAVjGBAECNJAbjGBAECIJAOjGBMALAICGWJAVjGBALCoBJAKCEWJHYAOjGBAYAVjGIALAICFJHICbZCGWJAOjGBALCoBJAKCFJCbZCEWJHYAbjGBAYAOjGIALAIAmJCbZHICGWJAbjGBALCoBJAKCGJCbZHKCEWJHOAVjGBAOAbjGIAKCFJRKAIATJRIAtATJRVSFMAVCBAM2BBHYyHTAOC/+F6HPJROAYCbZRtGXGXAYCIrHmQBAOCFJRbSFMAORbALAIAmlCbZCGWJ8oGBROMGXGXAtQBAbCFJRVSFMAbRVALAIAYlCbZCGWJ8oGBRbMGXGXAP9FQBAMCFJRYSFMAM1BFHYCgFZRTGXGXAYCa9MQBAMCGJRYSFMAM1BGHYCgBZCOWATCgBZqRTGXAYCa9MQBAMCEJRYSFMAM1BEHYCgBZCfWATqRTGXAYCa9MQBAMCIJRYSFMAM1BIHYCgBZCdWATqRTGXAYCa9MQBAMCLJRYSFMAMCKJRYAM2BLC8cWATqRTMATCFrCBATCFZl9zAQJHQRTMGXGXAmCb6QBAYRPSFMAY1BBHMCgFZROGXGXAMCa9MQBAYCFJRPSFMAY1BFHMCgBZCOWAOCgBZqROGXAMCa9MQBAYCGJRPSFMAY1BGHMCgBZCfWAOqROGXAMCa9MQBAYCEJRPSFMAY1BEHMCgBZCdWAOqROGXAMCa9MQBAYCIJRPSFMAYCLJRPAY2BIC8cWAOqROMAOCFrCBAOCFZl9zAQJHQROMGXGXAtCb6QBAPRMSFMAP1BBHMCgFZRbGXGXAMCa9MQBAPCFJRMSFMAP1BFHMCgBZCOWAbCgBZqRbGXAMCa9MQBAPCGJRMSFMAP1BGHMCgBZCfWAbqRbGXAMCa9MQBAPCEJRMSFMAP1BEHMCgBZCdWAbqRbGXAMCa9MQBAPCIJRMSFMAPCLJRMAP2BIC8cWAbqRbMAbCFrCBAbCFZl9zAQJHQRbMGXGXAGCG9HQBABAT87FBABCIJAb87FBABCGJAO87FBSFMAEATjGBAECNJAbjGBAECIJAOjGBMALCoBJAKCEWJHYAOjGBAYATjGIALAICGWJATjGBALCoBJAKCFJCbZCEWJHYAbjGBAYAOjGIALAICFJHICbZCGWJAOjGBALCoBJAKCGJCbZCEWJHOATjGBAOAbjGIALAIAm9FAmCb6qJHICbZCGWJAbjGBAIAt9FAtCb6qJRIAKCEJRKMANCFJRNABCKJRBAECSJREAKCbZRKAICbZRIAfCEJHfAF9JQBMMCBC99AMAc6yRKMALCoFJ8kUUUUBAKM/tIFGa8jUUUUBCTlRLC9+RKGXAFCLJAI9LQBCaRKAE2BBC/+FZC/QF9HQBALhB83ENAECFJRKAEAIJC98JREGXAF9FQBGXAGCG6QBEXGXAKAE9JQBC9+bMAK1BBHGCgFZRIGXGXAGCa9MQBAKCFJRKSFMAK1BFHGCgBZCOWAICgBZqRIGXAGCa9MQBAKCGJRKSFMAK1BGHGCgBZCfWAIqRIGXAGCa9MQBAKCEJRKSFMAK1BEHGCgBZCdWAIqRIGXAGCa9MQBAKCIJRKSFMAK2BIC8cWAIqRIAKCLJRKMALCNJAICFZCGWqHGAICGrCBAICFrCFZl9zAG8oGBJHIjGBABAIjGBABCIJRBAFCaJHFQBSGMMEXGXAKAE9JQBC9+bMAK1BBHGCgFZRIGXGXAGCa9MQBAKCFJRKSFMAK1BFHGCgBZCOWAICgBZqRIGXAGCa9MQBAKCGJRKSFMAK1BGHGCgBZCfWAIqRIGXAGCa9MQBAKCEJRKSFMAK1BEHGCgBZCdWAIqRIGXAGCa9MQBAKCIJRKSFMAK2BIC8cWAIqRIAKCLJRKMABAICGrCBAICFrCFZl9zALCNJAICFZCGWqHI8oGBJHG87FBAIAGjGBABCGJRBAFCaJHFQBMMCBC99AKAE6yRKMAKM/dLEK97FaF97GXGXAGCI9HQBAF9FQFCBRGEXABABDBBBHECiD+rFCiD+sFD/6FHIAECND+rFCiD+sFD/6FAID/gFAECTD+rFCiD+sFD/6FHLD/gFD/kFD/lFHKCBDtD+2FHOAICUUUU94DtHND9OD9RD/kFHI9DBB/+hDYAIAID/mFAKAKD/mFALAOALAND9OD9RD/kFHIAID/mFD/kFD/kFD/jFD/nFHLD/mF9DBBX9LDYHOD/kFCgFDtD9OAECUUU94DtD9OD9QAIALD/mFAOD/kFCND+rFCU/+EDtD9OD9QAKALD/mFAOD/kFCTD+rFCUU/8ODtD9OD9QDMBBABCTJRBAGCIJHGAF9JQBSGMMAF9FQBCBRGEXABCTJHVAVDBBBHECBDtHOCUU98D8cFCUU98D8cEHND9OABDBBBHKAEDQILKOSQfbPden8c8d8e8fCggFDtD9OD/6FAKAEDQBFGENVcMTtmYi8ZpyHECTD+sFD/6FHID/gFAECTD+rFCTD+sFD/6FHLD/gFD/kFD/lFHE9DB/+g6DYALAEAOD+2FHOALCUUUU94DtHcD9OD9RD/kFHLALD/mFAEAED/mFAIAOAIAcD9OD9RD/kFHEAED/mFD/kFD/kFD/jFD/nFHID/mF9DBBX9LDYHOD/kFCTD+rFALAID/mFAOD/kFCggEDtD9OD9QHLAEAID/mFAOD/kFCaDbCBDnGCBDnECBDnKCBDnOCBDncCBDnMCBDnfCBDnbD9OHEDQNVi8ZcMpySQ8c8dfb8e8fD9QDMBBABAKAND9OALAEDQBFTtGEmYILPdKOenD9QDMBBABCAJRBAGCIJHGAF9JQBMMM/hEIGaF97FaL978jUUUUBCTlREGXAF9FQBCBRIEXAEABDBBBHLABCTJHKDBBBHODQILKOSQfbPden8c8d8e8fHNCTD+sFHVCID+rFDMIBAB9DBBU8/DY9D/zI818/DYAVCEDtD9QD/6FD/nFHVALAODQBFGENVcMTtmYi8ZpyHLCTD+rFCTD+sFD/6FD/mFHOAOD/mFAVALCTD+sFD/6FD/mFHcAcD/mFAVANCTD+rFCTD+sFD/6FD/mFHNAND/mFD/kFD/kFD/lFCBDtD+4FD/jF9DB/+g6DYHVD/mF9DBBX9LDYHLD/kFCggEDtHMD9OAcAVD/mFALD/kFCTD+rFD9QHcANAVD/mFALD/kFCTD+rFAOAVD/mFALD/kFAMD9OD9QHVDQBFTtGEmYILPdKOenHLD8dBAEDBIBDyB+t+J83EBABCNJALD8dFAEDBIBDyF+t+J83EBAKAcAVDQNVi8ZcMpySQ8c8dfb8e8fHVD8dBAEDBIBDyG+t+J83EBABCiJAVD8dFAEDBIBDyE+t+J83EBABCAJRBAICIJHIAF9JQBMMM9jFF97GXAGCGrAF9sHG9FQBCBRFEXABABDBBBHECND+rFCND+sFD/6FAECiD+sFCnD+rFCUUU/8EDtD+uFD/mFDMBBABCTJRBAFCIJHFAG9JQBMMM9TFEaCBCB8oGUkUUBHFABCEJC98ZJHBjGUkUUBGXGXAB8/BCTWHGuQBCaREABAGlCggEJCTrXBCa6QFMAFREMAEMMMFBCUNMIT9tBB";
  74405. // Uses bulk-memory and simd extensions
  74406. var detector = new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,3,2,0,0,5,3,1,0,1,12,1,0,10,22,2,12,0,65,0,65,0,65,0,252,10,0,0,11,7,0,65,0,253,15,26,11]);
  74407. // Used to unpack wasm
  74408. var wasmpack = new Uint8Array([32,0,65,253,3,1,2,34,4,106,6,5,11,8,7,20,13,33,12,16,128,9,116,64,19,113,127,15,10,21,22,14,255,66,24,54,136,107,18,23,192,26,114,118,132,17,77,101,130,144,27,87,131,44,45,74,156,154,70,167]);
  74409. if (typeof WebAssembly !== 'object') {
  74410. // This module requires WebAssembly to function
  74411. return {
  74412. supported: false,
  74413. };
  74414. }
  74415. var wasm = wasm_base;
  74416. if (WebAssembly.validate(detector)) {
  74417. wasm = wasm_simd;
  74418. console.log("Warning: meshopt_decoder is using experimental SIMD support");
  74419. }
  74420. var instance;
  74421. var promise =
  74422. WebAssembly.instantiate(unpack(wasm), {})
  74423. .then(function(result) {
  74424. instance = result.instance;
  74425. instance.exports.__wasm_call_ctors();
  74426. });
  74427. function unpack(data) {
  74428. var result = new Uint8Array(data.length);
  74429. for (var i = 0; i < data.length; ++i) {
  74430. var ch = data.charCodeAt(i);
  74431. result[i] = ch > 96 ? ch - 71 : ch > 64 ? ch - 65 : ch > 47 ? ch + 4 : ch > 46 ? 63 : 62;
  74432. }
  74433. var write = 0;
  74434. for (var i = 0; i < data.length; ++i) {
  74435. result[write++] = (result[i] < 60) ? wasmpack[result[i]] : (result[i] - 60) * 64 + result[++i];
  74436. }
  74437. return result.buffer.slice(0, write);
  74438. }
  74439. function decode(fun, target, count, size, source, filter) {
  74440. var sbrk = instance.exports.sbrk;
  74441. var count4 = (count + 3) & ~3; // pad for SIMD filter
  74442. var tp = sbrk(count4 * size);
  74443. var sp = sbrk(source.length);
  74444. var heap = new Uint8Array(instance.exports.memory.buffer);
  74445. heap.set(source, sp);
  74446. var res = fun(tp, count, size, sp, source.length);
  74447. if (res == 0 && filter) {
  74448. filter(tp, count4, size);
  74449. }
  74450. target.set(heap.subarray(tp, tp + count * size));
  74451. sbrk(tp - sbrk(0));
  74452. if (res != 0) {
  74453. throw new Error("Malformed buffer data: " + res);
  74454. }
  74455. };
  74456. var filters = {
  74457. // legacy index-based enums for glTF
  74458. 0: "",
  74459. 1: "meshopt_decodeFilterOct",
  74460. 2: "meshopt_decodeFilterQuat",
  74461. 3: "meshopt_decodeFilterExp",
  74462. // string-based enums for glTF
  74463. NONE: "",
  74464. OCTAHEDRAL: "meshopt_decodeFilterOct",
  74465. QUATERNION: "meshopt_decodeFilterQuat",
  74466. EXPONENTIAL: "meshopt_decodeFilterExp",
  74467. };
  74468. var decoders = {
  74469. // legacy index-based enums for glTF
  74470. 0: "meshopt_decodeVertexBuffer",
  74471. 1: "meshopt_decodeIndexBuffer",
  74472. 2: "meshopt_decodeIndexSequence",
  74473. // string-based enums for glTF
  74474. ATTRIBUTES: "meshopt_decodeVertexBuffer",
  74475. TRIANGLES: "meshopt_decodeIndexBuffer",
  74476. INDICES: "meshopt_decodeIndexSequence",
  74477. };
  74478. return {
  74479. ready: promise,
  74480. supported: true,
  74481. decodeVertexBuffer: function(target, count, size, source, filter) {
  74482. decode(instance.exports.meshopt_decodeVertexBuffer, target, count, size, source, instance.exports[filters[filter]]);
  74483. },
  74484. decodeIndexBuffer: function(target, count, size, source) {
  74485. decode(instance.exports.meshopt_decodeIndexBuffer, target, count, size, source);
  74486. },
  74487. decodeIndexSequence: function(target, count, size, source) {
  74488. decode(instance.exports.meshopt_decodeIndexSequence, target, count, size, source);
  74489. },
  74490. decodeGltfBuffer: function(target, count, size, source, mode, filter) {
  74491. decode(instance.exports[decoders[mode]], target, count, size, source, instance.exports[filters[filter]]);
  74492. }
  74493. };
  74494. })();
  74495. var DDSLoader = function ( manager ) {
  74496. CompressedTextureLoader.call( this, manager );
  74497. };
  74498. DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prototype ), {
  74499. constructor: DDSLoader,
  74500. parse: function ( buffer, loadMipmaps ) {
  74501. var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 };
  74502. // Adapted from @toji's DDS utils
  74503. // https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js
  74504. // All values and structures referenced from:
  74505. // http://msdn.microsoft.com/en-us/library/bb943991.aspx/
  74506. var DDS_MAGIC = 0x20534444;
  74507. // var DDSD_CAPS = 0x1;
  74508. // var DDSD_HEIGHT = 0x2;
  74509. // var DDSD_WIDTH = 0x4;
  74510. // var DDSD_PITCH = 0x8;
  74511. // var DDSD_PIXELFORMAT = 0x1000;
  74512. var DDSD_MIPMAPCOUNT = 0x20000;
  74513. // var DDSD_LINEARSIZE = 0x80000;
  74514. // var DDSD_DEPTH = 0x800000;
  74515. // var DDSCAPS_COMPLEX = 0x8;
  74516. // var DDSCAPS_MIPMAP = 0x400000;
  74517. // var DDSCAPS_TEXTURE = 0x1000;
  74518. var DDSCAPS2_CUBEMAP = 0x200;
  74519. var DDSCAPS2_CUBEMAP_POSITIVEX = 0x400;
  74520. var DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800;
  74521. var DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000;
  74522. var DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000;
  74523. var DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000;
  74524. var DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000;
  74525. // var DDSCAPS2_VOLUME = 0x200000;
  74526. // var DDPF_ALPHAPIXELS = 0x1;
  74527. // var DDPF_ALPHA = 0x2;
  74528. var DDPF_FOURCC = 0x4;
  74529. // var DDPF_RGB = 0x40;
  74530. // var DDPF_YUV = 0x200;
  74531. // var DDPF_LUMINANCE = 0x20000;
  74532. function fourCCToInt32( value ) {
  74533. return value.charCodeAt( 0 ) +
  74534. ( value.charCodeAt( 1 ) << 8 ) +
  74535. ( value.charCodeAt( 2 ) << 16 ) +
  74536. ( value.charCodeAt( 3 ) << 24 );
  74537. }
  74538. function int32ToFourCC( value ) {
  74539. return String.fromCharCode(
  74540. value & 0xff,
  74541. ( value >> 8 ) & 0xff,
  74542. ( value >> 16 ) & 0xff,
  74543. ( value >> 24 ) & 0xff
  74544. );
  74545. }
  74546. function loadARGBMip( buffer, dataOffset, width, height ) {
  74547. var dataLength = width * height * 4;
  74548. var srcBuffer = new Uint8Array( buffer, dataOffset, dataLength );
  74549. var byteArray = new Uint8Array( dataLength );
  74550. var dst = 0;
  74551. var src = 0;
  74552. for ( var y = 0; y < height; y ++ ) {
  74553. for ( var x = 0; x < width; x ++ ) {
  74554. var b = srcBuffer[ src ]; src ++;
  74555. var g = srcBuffer[ src ]; src ++;
  74556. var r = srcBuffer[ src ]; src ++;
  74557. var a = srcBuffer[ src ]; src ++;
  74558. byteArray[ dst ] = r; dst ++; //r
  74559. byteArray[ dst ] = g; dst ++; //g
  74560. byteArray[ dst ] = b; dst ++; //b
  74561. byteArray[ dst ] = a; dst ++; //a
  74562. }
  74563. }
  74564. return byteArray;
  74565. }
  74566. var FOURCC_DXT1 = fourCCToInt32( 'DXT1' );
  74567. var FOURCC_DXT3 = fourCCToInt32( 'DXT3' );
  74568. var FOURCC_DXT5 = fourCCToInt32( 'DXT5' );
  74569. var FOURCC_ETC1 = fourCCToInt32( 'ETC1' );
  74570. var headerLengthInt = 31; // The header length in 32 bit ints
  74571. // Offsets into the header array
  74572. var off_magic = 0;
  74573. var off_size = 1;
  74574. var off_flags = 2;
  74575. var off_height = 3;
  74576. var off_width = 4;
  74577. var off_mipmapCount = 7;
  74578. var off_pfFlags = 20;
  74579. var off_pfFourCC = 21;
  74580. var off_RGBBitCount = 22;
  74581. var off_RBitMask = 23;
  74582. var off_GBitMask = 24;
  74583. var off_BBitMask = 25;
  74584. var off_ABitMask = 26;
  74585. // var off_caps = 27;
  74586. var off_caps2 = 28;
  74587. // var off_caps3 = 29;
  74588. // var off_caps4 = 30;
  74589. // Parse header
  74590. var header = new Int32Array( buffer, 0, headerLengthInt );
  74591. if ( header[ off_magic ] !== DDS_MAGIC ) {
  74592. console.error( 'THREE.DDSLoader.parse: Invalid magic number in DDS header.' );
  74593. return dds;
  74594. }
  74595. if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) {
  74596. console.error( 'THREE.DDSLoader.parse: Unsupported format, must contain a FourCC code.' );
  74597. return dds;
  74598. }
  74599. var blockBytes;
  74600. var fourCC = header[ off_pfFourCC ];
  74601. var isRGBAUncompressed = false;
  74602. switch ( fourCC ) {
  74603. case FOURCC_DXT1:
  74604. blockBytes = 8;
  74605. dds.format = RGB_S3TC_DXT1_Format;
  74606. break;
  74607. case FOURCC_DXT3:
  74608. blockBytes = 16;
  74609. dds.format = RGBA_S3TC_DXT3_Format;
  74610. break;
  74611. case FOURCC_DXT5:
  74612. blockBytes = 16;
  74613. dds.format = RGBA_S3TC_DXT5_Format$1;
  74614. break;
  74615. case FOURCC_ETC1:
  74616. blockBytes = 8;
  74617. dds.format = RGB_ETC1_Format;
  74618. break;
  74619. default:
  74620. if ( header[ off_RGBBitCount ] === 32
  74621. && header[ off_RBitMask ] & 0xff0000
  74622. && header[ off_GBitMask ] & 0xff00
  74623. && header[ off_BBitMask ] & 0xff
  74624. && header[ off_ABitMask ] & 0xff000000 ) {
  74625. isRGBAUncompressed = true;
  74626. blockBytes = 64;
  74627. dds.format = RGBAFormat;
  74628. } else {
  74629. console.error( 'THREE.DDSLoader.parse: Unsupported FourCC code ', int32ToFourCC( fourCC ) );
  74630. return dds;
  74631. }
  74632. }
  74633. dds.mipmapCount = 1;
  74634. if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) {
  74635. dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] );
  74636. }
  74637. var caps2 = header[ off_caps2 ];
  74638. dds.isCubemap = caps2 & DDSCAPS2_CUBEMAP ? true : false;
  74639. if ( dds.isCubemap && (
  74640. ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) ||
  74641. ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX ) ||
  74642. ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEY ) ||
  74643. ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY ) ||
  74644. ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ ) ||
  74645. ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ )
  74646. ) ) {
  74647. console.error( 'THREE.DDSLoader.parse: Incomplete cubemap faces' );
  74648. return dds;
  74649. }
  74650. dds.width = header[ off_width ];
  74651. dds.height = header[ off_height ];
  74652. var dataOffset = header[ off_size ] + 4;
  74653. // Extract mipmaps buffers
  74654. var faces = dds.isCubemap ? 6 : 1;
  74655. for ( var face = 0; face < faces; face ++ ) {
  74656. var width = dds.width;
  74657. var height = dds.height;
  74658. for ( var i = 0; i < dds.mipmapCount; i ++ ) {
  74659. if ( isRGBAUncompressed ) {
  74660. var byteArray = loadARGBMip( buffer, dataOffset, width, height );
  74661. var dataLength = byteArray.length;
  74662. } else {
  74663. var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes;
  74664. var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
  74665. }
  74666. var mipmap = { 'data': byteArray, 'width': width, 'height': height };
  74667. dds.mipmaps.push( mipmap );
  74668. dataOffset += dataLength;
  74669. width = Math.max( width >> 1, 1 );
  74670. height = Math.max( height >> 1, 1 );
  74671. }
  74672. }
  74673. return dds;
  74674. }
  74675. } );
  74676. /* let sid = 0
  74677. let getName = ()=>{
  74678. return sid ++
  74679. } */
  74680. class BasicMaterial extends ShaderMaterial{
  74681. constructor(o={}){
  74682. super( Object.assign({},{
  74683. uniforms:{
  74684. color: {type:'v3', value: o.color || new Color("#FFF")} ,
  74685. map: {type: 't', value: o.map },
  74686. opacity : {type:'f', value : o.opacity == void 0 ? 1 : o.opacity }
  74687. },
  74688. vertexShader: Shaders['basicTextured.vs'],
  74689. fragmentShader: Shaders['basicTextured.fs'],
  74690. defines:{HasColor:'' }
  74691. },o));
  74692. //this.name111 = getName()
  74693. }
  74694. copy(source){
  74695. super.copy(source);
  74696. //console.log('copy', source.name111, this.name111, !!source.map )
  74697. this.map = source.map;
  74698. return this
  74699. }
  74700. set opacity(o){
  74701. this.uniforms && (this.uniforms.opacity.value = o);
  74702. }
  74703. get opacity(){
  74704. return this.uniforms.opacity.value
  74705. }
  74706. set map(o){
  74707. this.uniforms.map.value = o;
  74708. if(o){
  74709. this.defines.HasMap = '';
  74710. }else {
  74711. delete this.defines.HasMap;
  74712. }
  74713. //console.log('hasMap', !!o, this.name111 )
  74714. }
  74715. get map(){
  74716. return this.uniforms.map.value
  74717. }
  74718. }
  74719. //xzw add:----
  74720. let unknownExtensions = {};
  74721. let oldSet = MeshBasicMaterial.prototype.setValues;
  74722. MeshBasicMaterial.prototype.setValues = function(values){
  74723. return oldSet.call(this,values)
  74724. };
  74725. class GLTFLoader extends Loader {
  74726. constructor( manager, renderer, urlPrefix ) {
  74727. super( manager );
  74728. //xzw add:
  74729. this.dracoLoader = new DRACOLoader;
  74730. this.ktx2Loader = new KTX2Loader;
  74731. this.meshoptDecoder = MeshoptDecoder;
  74732. this.ddsLoader = new DDSLoader; //这个没测过
  74733. //路径相对于index.html
  74734. this.dracoLoader.setDecoderPath( urlPrefix + 'three.js/loaders/draco/' /*or 'https://unpkg.com/three@0.144.0/examples/js/libs/draco/gltf/' 版本可升级 */); //这两个路径可以自己改。在laser的环境也要放一份这个路径
  74735. this.ktx2Loader.setTranscoderPath(urlPrefix + 'three.js/loaders/basic/' /*or 'https://unpkg.com/three@0.144.0/examples/js/libs/basis/' 版本可升级 */).detectSupport( renderer );
  74736. this.pluginCallbacks = [];
  74737. this.register( function ( parser ) {
  74738. return new GLTFMaterialsClearcoatExtension( parser );
  74739. } );
  74740. this.register( function ( parser ) {
  74741. return new GLTFTextureBasisUExtension( parser );
  74742. } );
  74743. this.register( function ( parser ) {
  74744. return new GLTFTextureWebPExtension( parser );
  74745. } );
  74746. this.register( function ( parser ) {
  74747. return new GLTFMaterialsSheenExtension( parser );
  74748. } );
  74749. this.register( function ( parser ) {
  74750. return new GLTFMaterialsTransmissionExtension( parser );
  74751. } );
  74752. this.register( function ( parser ) {
  74753. return new GLTFMaterialsVolumeExtension( parser );
  74754. } );
  74755. this.register( function ( parser ) {
  74756. return new GLTFMaterialsIorExtension( parser );
  74757. } );
  74758. this.register( function ( parser ) {
  74759. return new GLTFMaterialsEmissiveStrengthExtension( parser );
  74760. } );
  74761. this.register( function ( parser ) {
  74762. return new GLTFMaterialsSpecularExtension( parser );
  74763. } );
  74764. this.register( function ( parser ) {
  74765. return new GLTFMaterialsIridescenceExtension( parser );
  74766. } );
  74767. this.register( function ( parser ) {
  74768. return new GLTFLightsExtension( parser );
  74769. } );
  74770. this.register( function ( parser ) {
  74771. return new GLTFMeshoptCompression( parser );
  74772. } );
  74773. this.register( function ( parser ) {
  74774. return new GLTFMeshGpuInstancing( parser );
  74775. } );
  74776. }
  74777. load( url, onLoad, onProgress, onError ) {
  74778. const scope = this;
  74779. let resourcePath;
  74780. if ( this.resourcePath !== '' ) {
  74781. resourcePath = this.resourcePath;
  74782. } else if ( this.path !== '' ) {
  74783. resourcePath = this.path;
  74784. } else {
  74785. resourcePath = LoaderUtils.extractUrlBase( url );
  74786. }
  74787. // Tells the LoadingManager to track an extra item, which resolves after
  74788. // the model is fully loaded. This means the count of items loaded will
  74789. // be incorrect, but ensures manager.onLoad() does not fire early.
  74790. this.manager.itemStart( url );
  74791. const _onError = function ( e ) {
  74792. if ( onError ) {
  74793. onError( e );
  74794. } else {
  74795. console.error( e );
  74796. }
  74797. scope.manager.itemError( url );
  74798. scope.manager.itemEnd( url );
  74799. };
  74800. const loader = new FileLoader( this.manager );
  74801. loader.setPath( this.path );
  74802. loader.setResponseType( 'arraybuffer' );
  74803. loader.setRequestHeader( this.requestHeader );
  74804. loader.setWithCredentials( this.withCredentials );
  74805. loader.load( url, function ( data ) {
  74806. try {
  74807. scope.parse( data, resourcePath, function ( gltf ) {
  74808. onLoad( gltf );
  74809. scope.manager.itemEnd( url );
  74810. }, _onError );
  74811. } catch ( e ) {
  74812. _onError( e );
  74813. }
  74814. }, onProgress, _onError );
  74815. }
  74816. setDRACOLoader( dracoLoader ) {
  74817. this.dracoLoader = dracoLoader;
  74818. return this;
  74819. }
  74820. setDDSLoader() {
  74821. throw new Error(
  74822. 'THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".'
  74823. );
  74824. }
  74825. setKTX2Loader( ktx2Loader ) {
  74826. this.ktx2Loader = ktx2Loader;
  74827. return this;
  74828. }
  74829. setMeshoptDecoder( meshoptDecoder ) {
  74830. this.meshoptDecoder = meshoptDecoder;
  74831. return this;
  74832. }
  74833. register( callback ) {
  74834. if ( this.pluginCallbacks.indexOf( callback ) === - 1 ) {
  74835. this.pluginCallbacks.push( callback );
  74836. }
  74837. return this;
  74838. }
  74839. unregister( callback ) {
  74840. if ( this.pluginCallbacks.indexOf( callback ) !== - 1 ) {
  74841. this.pluginCallbacks.splice( this.pluginCallbacks.indexOf( callback ), 1 );
  74842. }
  74843. return this;
  74844. }
  74845. parse( data, path, onLoad, onError ) {
  74846. let json;
  74847. const extensions = {};
  74848. const plugins = {};
  74849. if ( typeof data === 'string' ) {
  74850. json = JSON.parse( data );
  74851. } else if ( data instanceof ArrayBuffer ) {
  74852. const magic = LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) );
  74853. if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
  74854. try {
  74855. extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );
  74856. } catch ( error ) {
  74857. if ( onError ) onError( error );
  74858. return;
  74859. }
  74860. json = JSON.parse( extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content );
  74861. } else {
  74862. json = JSON.parse( LoaderUtils.decodeText( new Uint8Array( data ) ) );
  74863. }
  74864. } else {
  74865. json = data;
  74866. }
  74867. if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {
  74868. if ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) );
  74869. return;
  74870. }
  74871. const parser = new GLTFParser( json, {
  74872. path: path || this.resourcePath || '',
  74873. crossOrigin: this.crossOrigin,
  74874. requestHeader: this.requestHeader,
  74875. manager: this.manager,
  74876. ktx2Loader: this.ktx2Loader,
  74877. meshoptDecoder: this.meshoptDecoder
  74878. } );
  74879. parser.fileLoader.setRequestHeader( this.requestHeader );
  74880. for ( let i = 0; i < this.pluginCallbacks.length; i ++ ) {
  74881. const plugin = this.pluginCallbacks[ i ]( parser );
  74882. plugins[ plugin.name ] = plugin;
  74883. // Workaround to avoid determining as unknown extension
  74884. // in addUnknownExtensionsToUserData().
  74885. // Remove this workaround if we move all the existing
  74886. // extension handlers to plugin system
  74887. extensions[ plugin.name ] = true;
  74888. }
  74889. if ( json.extensionsUsed ) {
  74890. for ( let i = 0; i < json.extensionsUsed.length; ++ i ) {
  74891. const extensionName = json.extensionsUsed[ i ];
  74892. const extensionsRequired = json.extensionsRequired || [];
  74893. switch ( extensionName ) {
  74894. case EXTENSIONS.KHR_MATERIALS_UNLIT:
  74895. extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
  74896. break;
  74897. case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
  74898. extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
  74899. break;
  74900. case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
  74901. extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );
  74902. break;
  74903. case EXTENSIONS.KHR_TEXTURE_TRANSFORM:
  74904. extensions[ extensionName ] = new GLTFTextureTransformExtension();
  74905. break;
  74906. case EXTENSIONS.KHR_MESH_QUANTIZATION:
  74907. extensions[ extensionName ] = new GLTFMeshQuantizationExtension();
  74908. break;
  74909. default:
  74910. if ( extensionsRequired.indexOf( extensionName ) >= 0 && plugins[ extensionName ] === undefined ) {
  74911. if(!unknownExtensions[extensionName]){
  74912. console.warn( 'GLTFLoader: Unknown extension "' + extensionName + '".' ,'使用默认的KHR_materials_unlit材质' );
  74913. unknownExtensions[extensionName] = 1;
  74914. }
  74915. //xzw add: 默认
  74916. json.extensionsRequired = 'KHR_materials_unlit';
  74917. json.materials = [{
  74918. extensions: {KHR_materials_unlit: {}},
  74919. pbrMetallicRoughness:{
  74920. baseColorFactor:[1, 1, 1, 1],
  74921. baseColorTexture: {index: 0, texCoord: 0},
  74922. metallicFactor: 0,
  74923. roughnessFactor: 0.5,
  74924. }
  74925. }];
  74926. extensions[ json.extensionsRequired ] = new GLTFMaterialsUnlitExtension();
  74927. }
  74928. /*
  74929. 如原先:
  74930. json.materials = KHR_techniques_webgl:{
  74931. technique: 0,
  74932. values:{u_diffuse:{index: 0,texCoord: 0}}
  74933. }
  74934. */
  74935. }
  74936. }
  74937. }
  74938. parser.setExtensions( extensions );
  74939. parser.setPlugins( plugins );
  74940. parser.parse( onLoad, onError );
  74941. }
  74942. parseAsync( data, path ) {
  74943. const scope = this;
  74944. return new Promise( function ( resolve, reject ) {
  74945. scope.parse( data, path, resolve, reject );
  74946. } );
  74947. }
  74948. }
  74949. /* GLTFREGISTRY */
  74950. function GLTFRegistry() {
  74951. let objects = {};
  74952. return {
  74953. get: function ( key ) {
  74954. return objects[ key ];
  74955. },
  74956. add: function ( key, object ) {
  74957. objects[ key ] = object;
  74958. },
  74959. remove: function ( key ) {
  74960. delete objects[ key ];
  74961. },
  74962. removeAll: function () {
  74963. objects = {};
  74964. }
  74965. };
  74966. }
  74967. /*********************************/
  74968. /********** EXTENSIONS ***********/
  74969. /*********************************/
  74970. const EXTENSIONS = {
  74971. KHR_BINARY_GLTF: 'KHR_binary_glTF',
  74972. KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
  74973. KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
  74974. KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
  74975. KHR_MATERIALS_IOR: 'KHR_materials_ior',
  74976. KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
  74977. KHR_MATERIALS_SHEEN: 'KHR_materials_sheen',
  74978. KHR_MATERIALS_SPECULAR: 'KHR_materials_specular',
  74979. KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
  74980. KHR_MATERIALS_IRIDESCENCE: 'KHR_materials_iridescence',
  74981. KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
  74982. KHR_MATERIALS_VOLUME: 'KHR_materials_volume',
  74983. KHR_TEXTURE_BASISU: 'KHR_texture_basisu',
  74984. KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
  74985. KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
  74986. KHR_MATERIALS_EMISSIVE_STRENGTH: 'KHR_materials_emissive_strength',
  74987. EXT_TEXTURE_WEBP: 'EXT_texture_webp',
  74988. EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',
  74989. EXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing'
  74990. };
  74991. /**
  74992. * Punctual Lights Extension
  74993. *
  74994. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
  74995. */
  74996. class GLTFLightsExtension {
  74997. constructor( parser ) {
  74998. this.parser = parser;
  74999. this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;
  75000. // Object3D instance caches
  75001. this.cache = { refs: {}, uses: {} };
  75002. }
  75003. _markDefs() {
  75004. const parser = this.parser;
  75005. const nodeDefs = this.parser.json.nodes || [];
  75006. for ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {
  75007. const nodeDef = nodeDefs[ nodeIndex ];
  75008. if ( nodeDef.extensions
  75009. && nodeDef.extensions[ this.name ]
  75010. && nodeDef.extensions[ this.name ].light !== undefined ) {
  75011. parser._addNodeRef( this.cache, nodeDef.extensions[ this.name ].light );
  75012. }
  75013. }
  75014. }
  75015. _loadLight( lightIndex ) {
  75016. const parser = this.parser;
  75017. const cacheKey = 'light:' + lightIndex;
  75018. let dependency = parser.cache.get( cacheKey );
  75019. if ( dependency ) return dependency;
  75020. const json = parser.json;
  75021. const extensions = ( json.extensions && json.extensions[ this.name ] ) || {};
  75022. const lightDefs = extensions.lights || [];
  75023. const lightDef = lightDefs[ lightIndex ];
  75024. let lightNode;
  75025. const color = new Color( 0xffffff );
  75026. if ( lightDef.color !== undefined ) color.fromArray( lightDef.color );
  75027. const range = lightDef.range !== undefined ? lightDef.range : 0;
  75028. switch ( lightDef.type ) {
  75029. case 'directional':
  75030. lightNode = new DirectionalLight( color );
  75031. lightNode.target.position.set( 0, 0, - 1 );
  75032. lightNode.add( lightNode.target );
  75033. break;
  75034. case 'point':
  75035. lightNode = new PointLight( color );
  75036. lightNode.distance = range;
  75037. break;
  75038. case 'spot':
  75039. lightNode = new SpotLight( color );
  75040. lightNode.distance = range;
  75041. // Handle spotlight properties.
  75042. lightDef.spot = lightDef.spot || {};
  75043. lightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;
  75044. lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
  75045. lightNode.angle = lightDef.spot.outerConeAngle;
  75046. lightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;
  75047. lightNode.target.position.set( 0, 0, - 1 );
  75048. lightNode.add( lightNode.target );
  75049. break;
  75050. default:
  75051. throw new Error( 'THREE.GLTFLoader: Unexpected light type: ' + lightDef.type );
  75052. }
  75053. // Some lights (e.g. spot) default to a position other than the origin. Reset the position
  75054. // here, because node-level parsing will only override position if explicitly specified.
  75055. lightNode.position.set( 0, 0, 0 );
  75056. lightNode.decay = 2;
  75057. if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
  75058. lightNode.name = parser.createUniqueName( lightDef.name || ( 'light_' + lightIndex ) );
  75059. dependency = Promise.resolve( lightNode );
  75060. parser.cache.add( cacheKey, dependency );
  75061. return dependency;
  75062. }
  75063. createNodeAttachment( nodeIndex ) {
  75064. const self = this;
  75065. const parser = this.parser;
  75066. const json = parser.json;
  75067. const nodeDef = json.nodes[ nodeIndex ];
  75068. const lightDef = ( nodeDef.extensions && nodeDef.extensions[ this.name ] ) || {};
  75069. const lightIndex = lightDef.light;
  75070. if ( lightIndex === undefined ) return null;
  75071. return this._loadLight( lightIndex ).then( function ( light ) {
  75072. return parser._getNodeRef( self.cache, lightIndex, light );
  75073. } );
  75074. }
  75075. }
  75076. /**
  75077. * Unlit Materials Extension
  75078. *
  75079. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit
  75080. */
  75081. class GLTFMaterialsUnlitExtension {
  75082. constructor() {
  75083. this.name = EXTENSIONS.KHR_MATERIALS_UNLIT;
  75084. }
  75085. getMaterialType() {
  75086. return MeshBasicMaterial;
  75087. }
  75088. extendParams( materialParams, materialDef, parser ) {
  75089. const pending = [];
  75090. materialParams.color = new Color( 1.0, 1.0, 1.0 );
  75091. materialParams.opacity = 1.0;
  75092. const metallicRoughness = materialDef.pbrMetallicRoughness;
  75093. if ( metallicRoughness ) {
  75094. if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
  75095. const array = metallicRoughness.baseColorFactor;
  75096. materialParams.color.fromArray( array );
  75097. materialParams.opacity = array[ 3 ];
  75098. }
  75099. if ( metallicRoughness.baseColorTexture !== undefined ) {
  75100. pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, sRGBEncoding ) );
  75101. }
  75102. }
  75103. return Promise.all( pending );
  75104. }
  75105. }
  75106. /**
  75107. * Materials Emissive Strength Extension
  75108. *
  75109. * Specification: https://github.com/KhronosGroup/glTF/blob/5768b3ce0ef32bc39cdf1bef10b948586635ead3/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md
  75110. */
  75111. class GLTFMaterialsEmissiveStrengthExtension {
  75112. constructor( parser ) {
  75113. this.parser = parser;
  75114. this.name = EXTENSIONS.KHR_MATERIALS_EMISSIVE_STRENGTH;
  75115. }
  75116. extendMaterialParams( materialIndex, materialParams ) {
  75117. const parser = this.parser;
  75118. const materialDef = parser.json.materials[ materialIndex ];
  75119. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
  75120. return Promise.resolve();
  75121. }
  75122. const emissiveStrength = materialDef.extensions[ this.name ].emissiveStrength;
  75123. if ( emissiveStrength !== undefined ) {
  75124. materialParams.emissiveIntensity = emissiveStrength;
  75125. }
  75126. return Promise.resolve();
  75127. }
  75128. }
  75129. /**
  75130. * Clearcoat Materials Extension
  75131. *
  75132. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
  75133. */
  75134. class GLTFMaterialsClearcoatExtension {
  75135. constructor( parser ) {
  75136. this.parser = parser;
  75137. this.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;
  75138. }
  75139. getMaterialType( materialIndex ) {
  75140. const parser = this.parser;
  75141. const materialDef = parser.json.materials[ materialIndex ];
  75142. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
  75143. return MeshPhysicalMaterial;
  75144. }
  75145. extendMaterialParams( materialIndex, materialParams ) {
  75146. const parser = this.parser;
  75147. const materialDef = parser.json.materials[ materialIndex ];
  75148. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
  75149. return Promise.resolve();
  75150. }
  75151. const pending = [];
  75152. const extension = materialDef.extensions[ this.name ];
  75153. if ( extension.clearcoatFactor !== undefined ) {
  75154. materialParams.clearcoat = extension.clearcoatFactor;
  75155. }
  75156. if ( extension.clearcoatTexture !== undefined ) {
  75157. pending.push( parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) );
  75158. }
  75159. if ( extension.clearcoatRoughnessFactor !== undefined ) {
  75160. materialParams.clearcoatRoughness = extension.clearcoatRoughnessFactor;
  75161. }
  75162. if ( extension.clearcoatRoughnessTexture !== undefined ) {
  75163. pending.push( parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) );
  75164. }
  75165. if ( extension.clearcoatNormalTexture !== undefined ) {
  75166. pending.push( parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) );
  75167. if ( extension.clearcoatNormalTexture.scale !== undefined ) {
  75168. const scale = extension.clearcoatNormalTexture.scale;
  75169. materialParams.clearcoatNormalScale = new Vector2( scale, scale );
  75170. }
  75171. }
  75172. return Promise.all( pending );
  75173. }
  75174. }
  75175. /**
  75176. * Iridescence Materials Extension
  75177. *
  75178. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_iridescence
  75179. */
  75180. class GLTFMaterialsIridescenceExtension {
  75181. constructor( parser ) {
  75182. this.parser = parser;
  75183. this.name = EXTENSIONS.KHR_MATERIALS_IRIDESCENCE;
  75184. }
  75185. getMaterialType( materialIndex ) {
  75186. const parser = this.parser;
  75187. const materialDef = parser.json.materials[ materialIndex ];
  75188. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
  75189. return MeshPhysicalMaterial;
  75190. }
  75191. extendMaterialParams( materialIndex, materialParams ) {
  75192. const parser = this.parser;
  75193. const materialDef = parser.json.materials[ materialIndex ];
  75194. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
  75195. return Promise.resolve();
  75196. }
  75197. const pending = [];
  75198. const extension = materialDef.extensions[ this.name ];
  75199. if ( extension.iridescenceFactor !== undefined ) {
  75200. materialParams.iridescence = extension.iridescenceFactor;
  75201. }
  75202. if ( extension.iridescenceTexture !== undefined ) {
  75203. pending.push( parser.assignTexture( materialParams, 'iridescenceMap', extension.iridescenceTexture ) );
  75204. }
  75205. if ( extension.iridescenceIor !== undefined ) {
  75206. materialParams.iridescenceIOR = extension.iridescenceIor;
  75207. }
  75208. if ( materialParams.iridescenceThicknessRange === undefined ) {
  75209. materialParams.iridescenceThicknessRange = [ 100, 400 ];
  75210. }
  75211. if ( extension.iridescenceThicknessMinimum !== undefined ) {
  75212. materialParams.iridescenceThicknessRange[ 0 ] = extension.iridescenceThicknessMinimum;
  75213. }
  75214. if ( extension.iridescenceThicknessMaximum !== undefined ) {
  75215. materialParams.iridescenceThicknessRange[ 1 ] = extension.iridescenceThicknessMaximum;
  75216. }
  75217. if ( extension.iridescenceThicknessTexture !== undefined ) {
  75218. pending.push( parser.assignTexture( materialParams, 'iridescenceThicknessMap', extension.iridescenceThicknessTexture ) );
  75219. }
  75220. return Promise.all( pending );
  75221. }
  75222. }
  75223. /**
  75224. * Sheen Materials Extension
  75225. *
  75226. * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_sheen
  75227. */
  75228. class GLTFMaterialsSheenExtension {
  75229. constructor( parser ) {
  75230. this.parser = parser;
  75231. this.name = EXTENSIONS.KHR_MATERIALS_SHEEN;
  75232. }
  75233. getMaterialType( materialIndex ) {
  75234. const parser = this.parser;
  75235. const materialDef = parser.json.materials[ materialIndex ];
  75236. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
  75237. return MeshPhysicalMaterial;
  75238. }
  75239. extendMaterialParams( materialIndex, materialParams ) {
  75240. const parser = this.parser;
  75241. const materialDef = parser.json.materials[ materialIndex ];
  75242. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
  75243. return Promise.resolve();
  75244. }
  75245. const pending = [];
  75246. materialParams.sheenColor = new Color( 0, 0, 0 );
  75247. materialParams.sheenRoughness = 0;
  75248. materialParams.sheen = 1;
  75249. const extension = materialDef.extensions[ this.name ];
  75250. if ( extension.sheenColorFactor !== undefined ) {
  75251. materialParams.sheenColor.fromArray( extension.sheenColorFactor );
  75252. }
  75253. if ( extension.sheenRoughnessFactor !== undefined ) {
  75254. materialParams.sheenRoughness = extension.sheenRoughnessFactor;
  75255. }
  75256. if ( extension.sheenColorTexture !== undefined ) {
  75257. pending.push( parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, sRGBEncoding ) );
  75258. }
  75259. if ( extension.sheenRoughnessTexture !== undefined ) {
  75260. pending.push( parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) );
  75261. }
  75262. return Promise.all( pending );
  75263. }
  75264. }
  75265. /**
  75266. * Transmission Materials Extension
  75267. *
  75268. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
  75269. * Draft: https://github.com/KhronosGroup/glTF/pull/1698
  75270. */
  75271. class GLTFMaterialsTransmissionExtension {
  75272. constructor( parser ) {
  75273. this.parser = parser;
  75274. this.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION;
  75275. }
  75276. getMaterialType( materialIndex ) {
  75277. const parser = this.parser;
  75278. const materialDef = parser.json.materials[ materialIndex ];
  75279. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
  75280. return MeshPhysicalMaterial;
  75281. }
  75282. extendMaterialParams( materialIndex, materialParams ) {
  75283. const parser = this.parser;
  75284. const materialDef = parser.json.materials[ materialIndex ];
  75285. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
  75286. return Promise.resolve();
  75287. }
  75288. const pending = [];
  75289. const extension = materialDef.extensions[ this.name ];
  75290. if ( extension.transmissionFactor !== undefined ) {
  75291. materialParams.transmission = extension.transmissionFactor;
  75292. }
  75293. if ( extension.transmissionTexture !== undefined ) {
  75294. pending.push( parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );
  75295. }
  75296. return Promise.all( pending );
  75297. }
  75298. }
  75299. /**
  75300. * Materials Volume Extension
  75301. *
  75302. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume
  75303. */
  75304. class GLTFMaterialsVolumeExtension {
  75305. constructor( parser ) {
  75306. this.parser = parser;
  75307. this.name = EXTENSIONS.KHR_MATERIALS_VOLUME;
  75308. }
  75309. getMaterialType( materialIndex ) {
  75310. const parser = this.parser;
  75311. const materialDef = parser.json.materials[ materialIndex ];
  75312. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
  75313. return MeshPhysicalMaterial;
  75314. }
  75315. extendMaterialParams( materialIndex, materialParams ) {
  75316. const parser = this.parser;
  75317. const materialDef = parser.json.materials[ materialIndex ];
  75318. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
  75319. return Promise.resolve();
  75320. }
  75321. const pending = [];
  75322. const extension = materialDef.extensions[ this.name ];
  75323. materialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0;
  75324. if ( extension.thicknessTexture !== undefined ) {
  75325. pending.push( parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );
  75326. }
  75327. materialParams.attenuationDistance = extension.attenuationDistance || Infinity;
  75328. const colorArray = extension.attenuationColor || [ 1, 1, 1 ];
  75329. materialParams.attenuationColor = new Color( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ] );
  75330. return Promise.all( pending );
  75331. }
  75332. }
  75333. /**
  75334. * Materials ior Extension
  75335. *
  75336. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_ior
  75337. */
  75338. class GLTFMaterialsIorExtension {
  75339. constructor( parser ) {
  75340. this.parser = parser;
  75341. this.name = EXTENSIONS.KHR_MATERIALS_IOR;
  75342. }
  75343. getMaterialType( materialIndex ) {
  75344. const parser = this.parser;
  75345. const materialDef = parser.json.materials[ materialIndex ];
  75346. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
  75347. return MeshPhysicalMaterial;
  75348. }
  75349. extendMaterialParams( materialIndex, materialParams ) {
  75350. const parser = this.parser;
  75351. const materialDef = parser.json.materials[ materialIndex ];
  75352. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
  75353. return Promise.resolve();
  75354. }
  75355. const extension = materialDef.extensions[ this.name ];
  75356. materialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;
  75357. return Promise.resolve();
  75358. }
  75359. }
  75360. /**
  75361. * Materials specular Extension
  75362. *
  75363. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_specular
  75364. */
  75365. class GLTFMaterialsSpecularExtension {
  75366. constructor( parser ) {
  75367. this.parser = parser;
  75368. this.name = EXTENSIONS.KHR_MATERIALS_SPECULAR;
  75369. }
  75370. getMaterialType( materialIndex ) {
  75371. const parser = this.parser;
  75372. const materialDef = parser.json.materials[ materialIndex ];
  75373. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
  75374. return MeshPhysicalMaterial;
  75375. }
  75376. extendMaterialParams( materialIndex, materialParams ) {
  75377. const parser = this.parser;
  75378. const materialDef = parser.json.materials[ materialIndex ];
  75379. if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
  75380. return Promise.resolve();
  75381. }
  75382. const pending = [];
  75383. const extension = materialDef.extensions[ this.name ];
  75384. materialParams.specularIntensity = extension.specularFactor !== undefined ? extension.specularFactor : 1.0;
  75385. if ( extension.specularTexture !== undefined ) {
  75386. pending.push( parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) );
  75387. }
  75388. const colorArray = extension.specularColorFactor || [ 1, 1, 1 ];
  75389. materialParams.specularColor = new Color( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ] );
  75390. if ( extension.specularColorTexture !== undefined ) {
  75391. pending.push( parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, sRGBEncoding ) );
  75392. }
  75393. return Promise.all( pending );
  75394. }
  75395. }
  75396. /**
  75397. * BasisU Texture Extension
  75398. *
  75399. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_basisu
  75400. */
  75401. class GLTFTextureBasisUExtension {
  75402. constructor( parser ) {
  75403. this.parser = parser;
  75404. this.name = EXTENSIONS.KHR_TEXTURE_BASISU;
  75405. }
  75406. loadTexture( textureIndex ) {
  75407. const parser = this.parser;
  75408. const json = parser.json;
  75409. const textureDef = json.textures[ textureIndex ];
  75410. if ( ! textureDef.extensions || ! textureDef.extensions[ this.name ] ) {
  75411. return null;
  75412. }
  75413. const extension = textureDef.extensions[ this.name ];
  75414. const loader = parser.options.ktx2Loader;
  75415. if ( ! loader ) {
  75416. if ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {
  75417. throw new Error( 'THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures' );
  75418. } else {
  75419. // Assumes that the extension is optional and that a fallback texture is present
  75420. return null;
  75421. }
  75422. }
  75423. return parser.loadTextureImage( textureIndex, extension.source, loader );
  75424. }
  75425. }
  75426. /**
  75427. * WebP Texture Extension
  75428. *
  75429. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_webp
  75430. */
  75431. class GLTFTextureWebPExtension {
  75432. constructor( parser ) {
  75433. this.parser = parser;
  75434. this.name = EXTENSIONS.EXT_TEXTURE_WEBP;
  75435. this.isSupported = null;
  75436. }
  75437. loadTexture( textureIndex ) {
  75438. const name = this.name;
  75439. const parser = this.parser;
  75440. const json = parser.json;
  75441. const textureDef = json.textures[ textureIndex ];
  75442. if ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) {
  75443. return null;
  75444. }
  75445. const extension = textureDef.extensions[ name ];
  75446. const source = json.images[ extension.source ];
  75447. let loader = parser.textureLoader;
  75448. if ( source.uri ) {
  75449. const handler = parser.options.manager.getHandler( source.uri );
  75450. if ( handler !== null ) loader = handler;
  75451. }
  75452. return this.detectSupport().then( function ( isSupported ) {
  75453. if ( isSupported ) return parser.loadTextureImage( textureIndex, extension.source, loader );
  75454. if ( json.extensionsRequired && json.extensionsRequired.indexOf( name ) >= 0 ) {
  75455. throw new Error( 'THREE.GLTFLoader: WebP required by asset but unsupported.' );
  75456. }
  75457. // Fall back to PNG or JPEG.
  75458. return parser.loadTexture( textureIndex );
  75459. } );
  75460. }
  75461. detectSupport() {
  75462. if ( ! this.isSupported ) {
  75463. this.isSupported = new Promise( function ( resolve ) {
  75464. const image = new Image();
  75465. // Lossy test image. Support for lossy images doesn't guarantee support for all
  75466. // WebP images, unfortunately.
  75467. image.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';
  75468. image.onload = image.onerror = function () {
  75469. resolve( image.height === 1 );
  75470. };
  75471. } );
  75472. }
  75473. return this.isSupported;
  75474. }
  75475. }
  75476. /**
  75477. * meshopt BufferView Compression Extension
  75478. *
  75479. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_meshopt_compression
  75480. */
  75481. class GLTFMeshoptCompression {
  75482. constructor( parser ) {
  75483. this.name = EXTENSIONS.EXT_MESHOPT_COMPRESSION;
  75484. this.parser = parser;
  75485. }
  75486. loadBufferView( index ) {
  75487. const json = this.parser.json;
  75488. const bufferView = json.bufferViews[ index ];
  75489. if ( bufferView.extensions && bufferView.extensions[ this.name ] ) {
  75490. const extensionDef = bufferView.extensions[ this.name ];
  75491. const buffer = this.parser.getDependency( 'buffer', extensionDef.buffer );
  75492. const decoder = this.parser.options.meshoptDecoder;
  75493. if ( ! decoder || ! decoder.supported ) {
  75494. if ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {
  75495. throw new Error( 'THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files' );
  75496. } else {
  75497. // Assumes that the extension is optional and that fallback buffer data is present
  75498. return null;
  75499. }
  75500. }
  75501. return buffer.then( function ( res ) {
  75502. const byteOffset = extensionDef.byteOffset || 0;
  75503. const byteLength = extensionDef.byteLength || 0;
  75504. const count = extensionDef.count;
  75505. const stride = extensionDef.byteStride;
  75506. const source = new Uint8Array( res, byteOffset, byteLength );
  75507. if ( decoder.decodeGltfBufferAsync ) {
  75508. return decoder.decodeGltfBufferAsync( count, stride, source, extensionDef.mode, extensionDef.filter ).then( function ( res ) {
  75509. return res.buffer;
  75510. } );
  75511. } else {
  75512. // Support for MeshoptDecoder 0.18 or earlier, without decodeGltfBufferAsync
  75513. return decoder.ready.then( function () {
  75514. const result = new ArrayBuffer( count * stride );
  75515. decoder.decodeGltfBuffer( new Uint8Array( result ), count, stride, source, extensionDef.mode, extensionDef.filter );
  75516. return result;
  75517. } );
  75518. }
  75519. } );
  75520. } else {
  75521. return null;
  75522. }
  75523. }
  75524. }
  75525. /**
  75526. * GPU Instancing Extension
  75527. *
  75528. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing
  75529. *
  75530. */
  75531. class GLTFMeshGpuInstancing {
  75532. constructor( parser ) {
  75533. this.name = EXTENSIONS.EXT_MESH_GPU_INSTANCING;
  75534. this.parser = parser;
  75535. }
  75536. createNodeMesh( nodeIndex ) {
  75537. const json = this.parser.json;
  75538. const nodeDef = json.nodes[ nodeIndex ];
  75539. if ( ! nodeDef.extensions || ! nodeDef.extensions[ this.name ] ||
  75540. nodeDef.mesh === undefined ) {
  75541. return null;
  75542. }
  75543. const meshDef = json.meshes[ nodeDef.mesh ];
  75544. // No Points or Lines + Instancing support yet
  75545. for ( const primitive of meshDef.primitives ) {
  75546. if ( primitive.mode !== WEBGL_CONSTANTS.TRIANGLES &&
  75547. primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_STRIP &&
  75548. primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_FAN &&
  75549. primitive.mode !== undefined ) {
  75550. return null;
  75551. }
  75552. }
  75553. const extensionDef = nodeDef.extensions[ this.name ];
  75554. const attributesDef = extensionDef.attributes;
  75555. // @TODO: Can we support InstancedMesh + SkinnedMesh?
  75556. const pending = [];
  75557. const attributes = {};
  75558. for ( const key in attributesDef ) {
  75559. pending.push( this.parser.getDependency( 'accessor', attributesDef[ key ] ).then( accessor => {
  75560. attributes[ key ] = accessor;
  75561. return attributes[ key ];
  75562. } ) );
  75563. }
  75564. if ( pending.length < 1 ) {
  75565. return null;
  75566. }
  75567. pending.push( this.parser.createNodeMesh( nodeIndex ) );
  75568. return Promise.all( pending ).then( results => {
  75569. const nodeObject = results.pop();
  75570. const meshes = nodeObject.isGroup ? nodeObject.children : [ nodeObject ];
  75571. const count = results[ 0 ].count; // All attribute counts should be same
  75572. const instancedMeshes = [];
  75573. for ( const mesh of meshes ) {
  75574. // Temporal variables
  75575. const m = new Matrix4();
  75576. const p = new Vector3();
  75577. const q = new Quaternion();
  75578. const s = new Vector3( 1, 1, 1 );
  75579. const instancedMesh = new InstancedMesh( mesh.geometry, mesh.material, count );
  75580. for ( let i = 0; i < count; i ++ ) {
  75581. if ( attributes.TRANSLATION ) {
  75582. p.fromBufferAttribute( attributes.TRANSLATION, i );
  75583. }
  75584. if ( attributes.ROTATION ) {
  75585. q.fromBufferAttribute( attributes.ROTATION, i );
  75586. }
  75587. if ( attributes.SCALE ) {
  75588. s.fromBufferAttribute( attributes.SCALE, i );
  75589. }
  75590. instancedMesh.setMatrixAt( i, m.compose( p, q, s ) );
  75591. }
  75592. // Add instance attributes to the geometry, excluding TRS.
  75593. for ( const attributeName in attributes ) {
  75594. if ( attributeName !== 'TRANSLATION' &&
  75595. attributeName !== 'ROTATION' &&
  75596. attributeName !== 'SCALE' ) {
  75597. mesh.geometry.setAttribute( attributeName, attributes[ attributeName ] );
  75598. }
  75599. }
  75600. // Just in case
  75601. Object3D.prototype.copy.call( instancedMesh, mesh );
  75602. // https://github.com/mrdoob/three.js/issues/18334
  75603. instancedMesh.frustumCulled = false;
  75604. this.parser.assignFinalMaterial( instancedMesh );
  75605. instancedMeshes.push( instancedMesh );
  75606. }
  75607. if ( nodeObject.isGroup ) {
  75608. nodeObject.clear();
  75609. nodeObject.add( ... instancedMeshes );
  75610. return nodeObject;
  75611. }
  75612. return instancedMeshes[ 0 ];
  75613. } );
  75614. }
  75615. }
  75616. /* BINARY EXTENSION */
  75617. const BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
  75618. const BINARY_EXTENSION_HEADER_LENGTH = 12;
  75619. const BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };
  75620. class GLTFBinaryExtension {
  75621. constructor( data ) {
  75622. this.name = EXTENSIONS.KHR_BINARY_GLTF;
  75623. this.content = null;
  75624. this.body = null;
  75625. const headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );
  75626. this.header = {
  75627. magic: LoaderUtils.decodeText( new Uint8Array( data.slice( 0, 4 ) ) ),
  75628. version: headerView.getUint32( 4, true ),
  75629. length: headerView.getUint32( 8, true )
  75630. };
  75631. if ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {
  75632. throw new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );
  75633. } else if ( this.header.version < 2.0 ) {
  75634. throw new Error( 'THREE.GLTFLoader: Legacy binary file detected.' );
  75635. }
  75636. const chunkContentsLength = this.header.length - BINARY_EXTENSION_HEADER_LENGTH;
  75637. const chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );
  75638. let chunkIndex = 0;
  75639. while ( chunkIndex < chunkContentsLength ) {
  75640. const chunkLength = chunkView.getUint32( chunkIndex, true );
  75641. chunkIndex += 4;
  75642. const chunkType = chunkView.getUint32( chunkIndex, true );
  75643. chunkIndex += 4;
  75644. if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {
  75645. const contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );
  75646. this.content = LoaderUtils.decodeText( contentArray );
  75647. } else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {
  75648. const byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;
  75649. this.body = data.slice( byteOffset, byteOffset + chunkLength );
  75650. }
  75651. // Clients must ignore chunks with unknown types.
  75652. chunkIndex += chunkLength;
  75653. }
  75654. if ( this.content === null ) {
  75655. throw new Error( 'THREE.GLTFLoader: JSON content not found.' );
  75656. }
  75657. }
  75658. }
  75659. /**
  75660. * DRACO Mesh Compression Extension
  75661. *
  75662. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
  75663. */
  75664. class GLTFDracoMeshCompressionExtension {
  75665. constructor( json, dracoLoader ) {
  75666. if ( ! dracoLoader ) {
  75667. throw new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );
  75668. }
  75669. this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
  75670. this.json = json;
  75671. this.dracoLoader = dracoLoader;
  75672. this.dracoLoader.preload();
  75673. }
  75674. decodePrimitive( primitive, parser ) {
  75675. const json = this.json;
  75676. const dracoLoader = this.dracoLoader;
  75677. const bufferViewIndex = primitive.extensions[ this.name ].bufferView;
  75678. const gltfAttributeMap = primitive.extensions[ this.name ].attributes;
  75679. const threeAttributeMap = {};
  75680. const attributeNormalizedMap = {};
  75681. const attributeTypeMap = {};
  75682. for ( const attributeName in gltfAttributeMap ) {
  75683. const threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();
  75684. threeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ];
  75685. }
  75686. for ( const attributeName in primitive.attributes ) {
  75687. const threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();
  75688. if ( gltfAttributeMap[ attributeName ] !== undefined ) {
  75689. const accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];
  75690. const componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
  75691. attributeTypeMap[ threeAttributeName ] = componentType.name;
  75692. attributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;
  75693. }
  75694. }
  75695. return parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {
  75696. return new Promise( function ( resolve ) {
  75697. dracoLoader.decodeDracoFile( bufferView, function ( geometry ) {
  75698. for ( const attributeName in geometry.attributes ) {
  75699. const attribute = geometry.attributes[ attributeName ];
  75700. const normalized = attributeNormalizedMap[ attributeName ];
  75701. if ( normalized !== undefined ) attribute.normalized = normalized;
  75702. }
  75703. resolve( geometry );
  75704. }, threeAttributeMap, attributeTypeMap );
  75705. } );
  75706. } );
  75707. }
  75708. }
  75709. /**
  75710. * Texture Transform Extension
  75711. *
  75712. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform
  75713. */
  75714. class GLTFTextureTransformExtension {
  75715. constructor() {
  75716. this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;
  75717. }
  75718. extendTexture( texture, transform ) {
  75719. if ( transform.texCoord !== undefined ) {
  75720. console.warn( 'THREE.GLTFLoader: Custom UV sets in "' + this.name + '" extension not yet supported.' );
  75721. }
  75722. if ( transform.offset === undefined && transform.rotation === undefined && transform.scale === undefined ) {
  75723. // See https://github.com/mrdoob/three.js/issues/21819.
  75724. return texture;
  75725. }
  75726. texture = texture.clone();
  75727. if ( transform.offset !== undefined ) {
  75728. texture.offset.fromArray( transform.offset );
  75729. }
  75730. if ( transform.rotation !== undefined ) {
  75731. texture.rotation = transform.rotation;
  75732. }
  75733. if ( transform.scale !== undefined ) {
  75734. texture.repeat.fromArray( transform.scale );
  75735. }
  75736. texture.needsUpdate = true;
  75737. return texture;
  75738. }
  75739. }
  75740. /**
  75741. * Specular-Glossiness Extension
  75742. *
  75743. * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness
  75744. */
  75745. /**
  75746. * A sub class of StandardMaterial with some of the functionality
  75747. * changed via the `onBeforeCompile` callback
  75748. * @pailhead
  75749. */
  75750. class GLTFMeshStandardSGMaterial extends MeshStandardMaterial {
  75751. constructor( params ) {
  75752. super();
  75753. this.isGLTFSpecularGlossinessMaterial = true;
  75754. //various chunks that need replacing
  75755. const specularMapParsFragmentChunk = [
  75756. '#ifdef USE_SPECULARMAP',
  75757. ' uniform sampler2D specularMap;',
  75758. '#endif'
  75759. ].join( '\n' );
  75760. const glossinessMapParsFragmentChunk = [
  75761. '#ifdef USE_GLOSSINESSMAP',
  75762. ' uniform sampler2D glossinessMap;',
  75763. '#endif'
  75764. ].join( '\n' );
  75765. const specularMapFragmentChunk = [
  75766. 'vec3 specularFactor = specular;',
  75767. '#ifdef USE_SPECULARMAP',
  75768. ' vec4 texelSpecular = texture2D( specularMap, vUv );',
  75769. ' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',
  75770. ' specularFactor *= texelSpecular.rgb;',
  75771. '#endif'
  75772. ].join( '\n' );
  75773. const glossinessMapFragmentChunk = [
  75774. 'float glossinessFactor = glossiness;',
  75775. '#ifdef USE_GLOSSINESSMAP',
  75776. ' vec4 texelGlossiness = texture2D( glossinessMap, vUv );',
  75777. ' // reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture',
  75778. ' glossinessFactor *= texelGlossiness.a;',
  75779. '#endif'
  75780. ].join( '\n' );
  75781. const lightPhysicalFragmentChunk = [
  75782. 'PhysicalMaterial material;',
  75783. 'material.diffuseColor = diffuseColor.rgb * ( 1. - max( specularFactor.r, max( specularFactor.g, specularFactor.b ) ) );',
  75784. 'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );',
  75785. 'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );',
  75786. 'material.roughness = max( 1.0 - glossinessFactor, 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap.',
  75787. 'material.roughness += geometryRoughness;',
  75788. 'material.roughness = min( material.roughness, 1.0 );',
  75789. 'material.specularColor = specularFactor;',
  75790. ].join( '\n' );
  75791. const uniforms = {
  75792. specular: { value: new Color().setHex( 0xffffff ) },
  75793. glossiness: { value: 1 },
  75794. specularMap: { value: null },
  75795. glossinessMap: { value: null }
  75796. };
  75797. this._extraUniforms = uniforms;
  75798. this.onBeforeCompile = function ( shader ) {
  75799. for ( const uniformName in uniforms ) {
  75800. shader.uniforms[ uniformName ] = uniforms[ uniformName ];
  75801. }
  75802. shader.fragmentShader = shader.fragmentShader
  75803. .replace( 'uniform float roughness;', 'uniform vec3 specular;' )
  75804. .replace( 'uniform float metalness;', 'uniform float glossiness;' )
  75805. .replace( '#include <roughnessmap_pars_fragment>', specularMapParsFragmentChunk )
  75806. .replace( '#include <metalnessmap_pars_fragment>', glossinessMapParsFragmentChunk )
  75807. .replace( '#include <roughnessmap_fragment>', specularMapFragmentChunk )
  75808. .replace( '#include <metalnessmap_fragment>', glossinessMapFragmentChunk )
  75809. .replace( '#include <lights_physical_fragment>', lightPhysicalFragmentChunk );
  75810. };
  75811. Object.defineProperties( this, {
  75812. specular: {
  75813. get: function () {
  75814. return uniforms.specular.value;
  75815. },
  75816. set: function ( v ) {
  75817. uniforms.specular.value = v;
  75818. }
  75819. },
  75820. specularMap: {
  75821. get: function () {
  75822. return uniforms.specularMap.value;
  75823. },
  75824. set: function ( v ) {
  75825. uniforms.specularMap.value = v;
  75826. if ( v ) {
  75827. this.defines.USE_SPECULARMAP = ''; // USE_UV is set by the renderer for specular maps
  75828. } else {
  75829. delete this.defines.USE_SPECULARMAP;
  75830. }
  75831. }
  75832. },
  75833. glossiness: {
  75834. get: function () {
  75835. return uniforms.glossiness.value;
  75836. },
  75837. set: function ( v ) {
  75838. uniforms.glossiness.value = v;
  75839. }
  75840. },
  75841. glossinessMap: {
  75842. get: function () {
  75843. return uniforms.glossinessMap.value;
  75844. },
  75845. set: function ( v ) {
  75846. uniforms.glossinessMap.value = v;
  75847. if ( v ) {
  75848. this.defines.USE_GLOSSINESSMAP = '';
  75849. this.defines.USE_UV = '';
  75850. } else {
  75851. delete this.defines.USE_GLOSSINESSMAP;
  75852. delete this.defines.USE_UV;
  75853. }
  75854. }
  75855. }
  75856. } );
  75857. delete this.metalness;
  75858. delete this.roughness;
  75859. delete this.metalnessMap;
  75860. delete this.roughnessMap;
  75861. this.setValues( params );
  75862. }
  75863. copy( source ) {
  75864. super.copy( source );
  75865. this.specularMap = source.specularMap;
  75866. this.specular.copy( source.specular );
  75867. this.glossinessMap = source.glossinessMap;
  75868. this.glossiness = source.glossiness;
  75869. delete this.metalness;
  75870. delete this.roughness;
  75871. delete this.metalnessMap;
  75872. delete this.roughnessMap;
  75873. return this;
  75874. }
  75875. }
  75876. class GLTFMaterialsPbrSpecularGlossinessExtension {
  75877. constructor() {
  75878. this.name = EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS;
  75879. this.specularGlossinessParams = [
  75880. 'color',
  75881. 'map',
  75882. 'lightMap',
  75883. 'lightMapIntensity',
  75884. 'aoMap',
  75885. 'aoMapIntensity',
  75886. 'emissive',
  75887. 'emissiveIntensity',
  75888. 'emissiveMap',
  75889. 'bumpMap',
  75890. 'bumpScale',
  75891. 'normalMap',
  75892. 'normalMapType',
  75893. 'displacementMap',
  75894. 'displacementScale',
  75895. 'displacementBias',
  75896. 'specularMap',
  75897. 'specular',
  75898. 'glossinessMap',
  75899. 'glossiness',
  75900. 'alphaMap',
  75901. 'envMap',
  75902. 'envMapIntensity'
  75903. ];
  75904. }
  75905. getMaterialType() {
  75906. return GLTFMeshStandardSGMaterial;
  75907. }
  75908. extendParams( materialParams, materialDef, parser ) {
  75909. const pbrSpecularGlossiness = materialDef.extensions[ this.name ];
  75910. materialParams.color = new Color( 1.0, 1.0, 1.0 );
  75911. materialParams.opacity = 1.0;
  75912. const pending = [];
  75913. if ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {
  75914. const array = pbrSpecularGlossiness.diffuseFactor;
  75915. materialParams.color.fromArray( array );
  75916. materialParams.opacity = array[ 3 ];
  75917. }
  75918. if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
  75919. pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture, sRGBEncoding ) );
  75920. }
  75921. materialParams.emissive = new Color( 0.0, 0.0, 0.0 );
  75922. materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;
  75923. materialParams.specular = new Color( 1.0, 1.0, 1.0 );
  75924. if ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {
  75925. materialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor );
  75926. }
  75927. if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {
  75928. const specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
  75929. pending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) );
  75930. pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef, sRGBEncoding ) );
  75931. }
  75932. return Promise.all( pending );
  75933. }
  75934. createMaterial( materialParams ) {
  75935. const material = new GLTFMeshStandardSGMaterial( materialParams );
  75936. material.fog = true;
  75937. material.color = materialParams.color;
  75938. material.map = materialParams.map === undefined ? null : materialParams.map;
  75939. material.lightMap = null;
  75940. material.lightMapIntensity = 1.0;
  75941. material.aoMap = materialParams.aoMap === undefined ? null : materialParams.aoMap;
  75942. material.aoMapIntensity = 1.0;
  75943. material.emissive = materialParams.emissive;
  75944. material.emissiveIntensity = materialParams.emissiveIntensity === undefined ? 1.0 : materialParams.emissiveIntensity;
  75945. material.emissiveMap = materialParams.emissiveMap === undefined ? null : materialParams.emissiveMap;
  75946. material.bumpMap = materialParams.bumpMap === undefined ? null : materialParams.bumpMap;
  75947. material.bumpScale = 1;
  75948. material.normalMap = materialParams.normalMap === undefined ? null : materialParams.normalMap;
  75949. material.normalMapType = TangentSpaceNormalMap;
  75950. if ( materialParams.normalScale ) material.normalScale = materialParams.normalScale;
  75951. material.displacementMap = null;
  75952. material.displacementScale = 1;
  75953. material.displacementBias = 0;
  75954. material.specularMap = materialParams.specularMap === undefined ? null : materialParams.specularMap;
  75955. material.specular = materialParams.specular;
  75956. material.glossinessMap = materialParams.glossinessMap === undefined ? null : materialParams.glossinessMap;
  75957. material.glossiness = materialParams.glossiness;
  75958. material.alphaMap = null;
  75959. material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;
  75960. material.envMapIntensity = 1.0;
  75961. return material;
  75962. }
  75963. }
  75964. /**
  75965. * Mesh Quantization Extension
  75966. *
  75967. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization
  75968. */
  75969. class GLTFMeshQuantizationExtension {
  75970. constructor() {
  75971. this.name = EXTENSIONS.KHR_MESH_QUANTIZATION;
  75972. }
  75973. }
  75974. /*********************************/
  75975. /********** INTERPOLATION ********/
  75976. /*********************************/
  75977. // Spline Interpolation
  75978. // Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation
  75979. class GLTFCubicSplineInterpolant extends Interpolant {
  75980. constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
  75981. super( parameterPositions, sampleValues, sampleSize, resultBuffer );
  75982. }
  75983. copySampleValue_( index ) {
  75984. // Copies a sample value to the result buffer. See description of glTF
  75985. // CUBICSPLINE values layout in interpolate_() function below.
  75986. const result = this.resultBuffer,
  75987. values = this.sampleValues,
  75988. valueSize = this.valueSize,
  75989. offset = index * valueSize * 3 + valueSize;
  75990. for ( let i = 0; i !== valueSize; i ++ ) {
  75991. result[ i ] = values[ offset + i ];
  75992. }
  75993. return result;
  75994. }
  75995. interpolate_( i1, t0, t, t1 ) {
  75996. const result = this.resultBuffer;
  75997. const values = this.sampleValues;
  75998. const stride = this.valueSize;
  75999. const stride2 = stride * 2;
  76000. const stride3 = stride * 3;
  76001. const td = t1 - t0;
  76002. const p = ( t - t0 ) / td;
  76003. const pp = p * p;
  76004. const ppp = pp * p;
  76005. const offset1 = i1 * stride3;
  76006. const offset0 = offset1 - stride3;
  76007. const s2 = - 2 * ppp + 3 * pp;
  76008. const s3 = ppp - pp;
  76009. const s0 = 1 - s2;
  76010. const s1 = s3 - pp + p;
  76011. // Layout of keyframe output values for CUBICSPLINE animations:
  76012. // [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]
  76013. for ( let i = 0; i !== stride; i ++ ) {
  76014. const p0 = values[ offset0 + i + stride ]; // splineVertex_k
  76015. const m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)
  76016. const p1 = values[ offset1 + i + stride ]; // splineVertex_k+1
  76017. const m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)
  76018. result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;
  76019. }
  76020. return result;
  76021. }
  76022. }
  76023. const _q = new Quaternion();
  76024. class GLTFCubicSplineQuaternionInterpolant extends GLTFCubicSplineInterpolant {
  76025. interpolate_( i1, t0, t, t1 ) {
  76026. const result = super.interpolate_( i1, t0, t, t1 );
  76027. _q.fromArray( result ).normalize().toArray( result );
  76028. return result;
  76029. }
  76030. }
  76031. /*********************************/
  76032. /********** INTERNALS ************/
  76033. /*********************************/
  76034. /* CONSTANTS */
  76035. const WEBGL_CONSTANTS = {
  76036. FLOAT: 5126,
  76037. //FLOAT_MAT2: 35674,
  76038. FLOAT_MAT3: 35675,
  76039. FLOAT_MAT4: 35676,
  76040. FLOAT_VEC2: 35664,
  76041. FLOAT_VEC3: 35665,
  76042. FLOAT_VEC4: 35666,
  76043. LINEAR: 9729,
  76044. REPEAT: 10497,
  76045. SAMPLER_2D: 35678,
  76046. POINTS: 0,
  76047. LINES: 1,
  76048. LINE_LOOP: 2,
  76049. LINE_STRIP: 3,
  76050. TRIANGLES: 4,
  76051. TRIANGLE_STRIP: 5,
  76052. TRIANGLE_FAN: 6,
  76053. UNSIGNED_BYTE: 5121,
  76054. UNSIGNED_SHORT: 5123
  76055. };
  76056. const WEBGL_COMPONENT_TYPES = {
  76057. 5120: Int8Array,
  76058. 5121: Uint8Array,
  76059. 5122: Int16Array,
  76060. 5123: Uint16Array,
  76061. 5125: Uint32Array,
  76062. 5126: Float32Array
  76063. };
  76064. const WEBGL_FILTERS = {
  76065. 9728: NearestFilter,
  76066. 9729: LinearFilter,
  76067. 9984: NearestMipmapNearestFilter,
  76068. 9985: LinearMipmapNearestFilter,
  76069. 9986: NearestMipmapLinearFilter,
  76070. 9987: LinearMipmapLinearFilter
  76071. };
  76072. const WEBGL_WRAPPINGS = {
  76073. 33071: ClampToEdgeWrapping,
  76074. 33648: MirroredRepeatWrapping,
  76075. 10497: RepeatWrapping
  76076. };
  76077. const WEBGL_TYPE_SIZES = {
  76078. 'SCALAR': 1,
  76079. 'VEC2': 2,
  76080. 'VEC3': 3,
  76081. 'VEC4': 4,
  76082. 'MAT2': 4,
  76083. 'MAT3': 9,
  76084. 'MAT4': 16
  76085. };
  76086. const ATTRIBUTES = {
  76087. POSITION: 'position',
  76088. NORMAL: 'normal',
  76089. TANGENT: 'tangent',
  76090. TEXCOORD_0: 'uv',
  76091. TEXCOORD_1: 'uv2',
  76092. COLOR_0: 'color',
  76093. WEIGHTS_0: 'skinWeight',
  76094. JOINTS_0: 'skinIndex',
  76095. };
  76096. const PATH_PROPERTIES = {
  76097. scale: 'scale',
  76098. translation: 'position',
  76099. rotation: 'quaternion',
  76100. weights: 'morphTargetInfluences'
  76101. };
  76102. const INTERPOLATION = {
  76103. CUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each
  76104. // keyframe track will be initialized with a default interpolation type, then modified.
  76105. LINEAR: InterpolateLinear,
  76106. STEP: InterpolateDiscrete
  76107. };
  76108. const ALPHA_MODES = {
  76109. OPAQUE: 'OPAQUE',
  76110. MASK: 'MASK',
  76111. BLEND: 'BLEND'
  76112. };
  76113. /**
  76114. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
  76115. */
  76116. function createDefaultMaterial( cache ) {
  76117. if ( cache[ 'DefaultMaterial' ] === undefined ) {
  76118. cache[ 'DefaultMaterial' ] = new MeshStandardMaterial( {
  76119. color: 0xFFFFFF,
  76120. emissive: 0x000000,
  76121. metalness: 1,
  76122. roughness: 1,
  76123. transparent: false,
  76124. depthTest: true,
  76125. side: FrontSide
  76126. } );
  76127. }
  76128. return cache[ 'DefaultMaterial' ];
  76129. }
  76130. function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {
  76131. // Add unknown glTF extensions to an object's userData.
  76132. for ( const name in objectDef.extensions ) {
  76133. if ( knownExtensions[ name ] === undefined ) {
  76134. object.userData.gltfExtensions = object.userData.gltfExtensions || {};
  76135. object.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];
  76136. }
  76137. }
  76138. }
  76139. /**
  76140. * @param {Object3D|Material|BufferGeometry} object
  76141. * @param {GLTF.definition} gltfDef
  76142. */
  76143. function assignExtrasToUserData( object, gltfDef ) {
  76144. if ( gltfDef.extras !== undefined ) {
  76145. if ( typeof gltfDef.extras === 'object' ) {
  76146. Object.assign( object.userData, gltfDef.extras );
  76147. } else {
  76148. console.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );
  76149. }
  76150. }
  76151. }
  76152. /**
  76153. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
  76154. *
  76155. * @param {BufferGeometry} geometry
  76156. * @param {Array<GLTF.Target>} targets
  76157. * @param {GLTFParser} parser
  76158. * @return {Promise<BufferGeometry>}
  76159. */
  76160. function addMorphTargets( geometry, targets, parser ) {
  76161. let hasMorphPosition = false;
  76162. let hasMorphNormal = false;
  76163. let hasMorphColor = false;
  76164. for ( let i = 0, il = targets.length; i < il; i ++ ) {
  76165. const target = targets[ i ];
  76166. if ( target.POSITION !== undefined ) hasMorphPosition = true;
  76167. if ( target.NORMAL !== undefined ) hasMorphNormal = true;
  76168. if ( target.COLOR_0 !== undefined ) hasMorphColor = true;
  76169. if ( hasMorphPosition && hasMorphNormal && hasMorphColor ) break;
  76170. }
  76171. if ( ! hasMorphPosition && ! hasMorphNormal && ! hasMorphColor ) return Promise.resolve( geometry );
  76172. const pendingPositionAccessors = [];
  76173. const pendingNormalAccessors = [];
  76174. const pendingColorAccessors = [];
  76175. for ( let i = 0, il = targets.length; i < il; i ++ ) {
  76176. const target = targets[ i ];
  76177. if ( hasMorphPosition ) {
  76178. const pendingAccessor = target.POSITION !== undefined
  76179. ? parser.getDependency( 'accessor', target.POSITION )
  76180. : geometry.attributes.position;
  76181. pendingPositionAccessors.push( pendingAccessor );
  76182. }
  76183. if ( hasMorphNormal ) {
  76184. const pendingAccessor = target.NORMAL !== undefined
  76185. ? parser.getDependency( 'accessor', target.NORMAL )
  76186. : geometry.attributes.normal;
  76187. pendingNormalAccessors.push( pendingAccessor );
  76188. }
  76189. if ( hasMorphColor ) {
  76190. const pendingAccessor = target.COLOR_0 !== undefined
  76191. ? parser.getDependency( 'accessor', target.COLOR_0 )
  76192. : geometry.attributes.color;
  76193. pendingColorAccessors.push( pendingAccessor );
  76194. }
  76195. }
  76196. return Promise.all( [
  76197. Promise.all( pendingPositionAccessors ),
  76198. Promise.all( pendingNormalAccessors ),
  76199. Promise.all( pendingColorAccessors )
  76200. ] ).then( function ( accessors ) {
  76201. const morphPositions = accessors[ 0 ];
  76202. const morphNormals = accessors[ 1 ];
  76203. const morphColors = accessors[ 2 ];
  76204. if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;
  76205. if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;
  76206. if ( hasMorphColor ) geometry.morphAttributes.color = morphColors;
  76207. geometry.morphTargetsRelative = true;
  76208. return geometry;
  76209. } );
  76210. }
  76211. /**
  76212. * @param {Mesh} mesh
  76213. * @param {GLTF.Mesh} meshDef
  76214. */
  76215. function updateMorphTargets( mesh, meshDef ) {
  76216. mesh.updateMorphTargets();
  76217. if ( meshDef.weights !== undefined ) {
  76218. for ( let i = 0, il = meshDef.weights.length; i < il; i ++ ) {
  76219. mesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];
  76220. }
  76221. }
  76222. // .extras has user-defined data, so check that .extras.targetNames is an array.
  76223. if ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {
  76224. const targetNames = meshDef.extras.targetNames;
  76225. if ( mesh.morphTargetInfluences.length === targetNames.length ) {
  76226. mesh.morphTargetDictionary = {};
  76227. for ( let i = 0, il = targetNames.length; i < il; i ++ ) {
  76228. mesh.morphTargetDictionary[ targetNames[ i ] ] = i;
  76229. }
  76230. } else {
  76231. console.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );
  76232. }
  76233. }
  76234. }
  76235. function createPrimitiveKey( primitiveDef ) {
  76236. const dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];
  76237. let geometryKey;
  76238. if ( dracoExtension ) {
  76239. geometryKey = 'draco:' + dracoExtension.bufferView
  76240. + ':' + dracoExtension.indices
  76241. + ':' + createAttributesKey( dracoExtension.attributes );
  76242. } else {
  76243. geometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;
  76244. }
  76245. return geometryKey;
  76246. }
  76247. function createAttributesKey( attributes ) {
  76248. let attributesKey = '';
  76249. const keys = Object.keys( attributes ).sort();
  76250. for ( let i = 0, il = keys.length; i < il; i ++ ) {
  76251. attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';
  76252. }
  76253. return attributesKey;
  76254. }
  76255. function getNormalizedComponentScale( constructor ) {
  76256. // Reference:
  76257. // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization#encoding-quantized-data
  76258. switch ( constructor ) {
  76259. case Int8Array:
  76260. return 1 / 127;
  76261. case Uint8Array:
  76262. return 1 / 255;
  76263. case Int16Array:
  76264. return 1 / 32767;
  76265. case Uint16Array:
  76266. return 1 / 65535;
  76267. default:
  76268. throw new Error( 'THREE.GLTFLoader: Unsupported normalized accessor component type.' );
  76269. }
  76270. }
  76271. function getImageURIMimeType( uri ) {
  76272. if ( uri.search( /\.jpe?g($|\?)/i ) > 0 || uri.search( /^data\:image\/jpeg/ ) === 0 ) return 'image/jpeg';
  76273. if ( uri.search( /\.webp($|\?)/i ) > 0 || uri.search( /^data\:image\/webp/ ) === 0 ) return 'image/webp';
  76274. return 'image/png';
  76275. }
  76276. /* GLTF PARSER */
  76277. class GLTFParser {
  76278. constructor( json = {}, options = {} ) {
  76279. this.json = json;
  76280. this.extensions = {};
  76281. this.plugins = {};
  76282. this.options = options;
  76283. // loader object cache
  76284. this.cache = new GLTFRegistry();
  76285. // associations between Three.js objects and glTF elements
  76286. this.associations = new Map();
  76287. // BufferGeometry caching
  76288. this.primitiveCache = {};
  76289. // Object3D instance caches
  76290. this.meshCache = { refs: {}, uses: {} };
  76291. this.cameraCache = { refs: {}, uses: {} };
  76292. this.lightCache = { refs: {}, uses: {} };
  76293. this.sourceCache = {};
  76294. this.textureCache = {};
  76295. // Track node names, to ensure no duplicates
  76296. this.nodeNamesUsed = {};
  76297. // Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the
  76298. // expensive work of uploading a texture to the GPU off the main thread.
  76299. const isSafari = /^((?!chrome|android).)*safari/i.test( navigator.userAgent ) === true;
  76300. const isFirefox = navigator.userAgent.indexOf( 'Firefox' ) > - 1;
  76301. const firefoxVersion = isFirefox ? navigator.userAgent.match( /Firefox\/([0-9]+)\./ )[ 1 ] : - 1;
  76302. // if ( typeof createImageBitmap === 'undefined' || isSafari || ( isFirefox && firefoxVersion < 98 ) ) {
  76303. this.textureLoader = new TextureLoader( this.options.manager );
  76304. /*} else {
  76305. //为了防止chrome出现报错 The source image could not be decoded. 导致reject,改用TextureLoader by xzw
  76306. this.textureLoader = new ImageBitmapLoader( this.options.manager );
  76307. }
  76308. */
  76309. this.textureLoader.setCrossOrigin( this.options.crossOrigin );
  76310. this.textureLoader.setRequestHeader( this.options.requestHeader );
  76311. this.fileLoader = new FileLoader( this.options.manager );
  76312. this.fileLoader.setResponseType( 'arraybuffer' );
  76313. if ( this.options.crossOrigin === 'use-credentials' ) {
  76314. this.fileLoader.setWithCredentials( true );
  76315. }
  76316. }
  76317. setExtensions( extensions ) {
  76318. this.extensions = extensions;
  76319. }
  76320. setPlugins( plugins ) {
  76321. this.plugins = plugins;
  76322. }
  76323. parse( onLoad, onError ) {
  76324. const parser = this;
  76325. const json = this.json;
  76326. const extensions = this.extensions;
  76327. // Clear the loader cache
  76328. this.cache.removeAll();
  76329. // Mark the special nodes/meshes in json for efficient parse
  76330. this._invokeAll( function ( ext ) {
  76331. return ext._markDefs && ext._markDefs();
  76332. } );
  76333. Promise.all( this._invokeAll( function ( ext ) {
  76334. return ext.beforeRoot && ext.beforeRoot();
  76335. } ) ).then( function () {
  76336. return Promise.all( [
  76337. parser.getDependencies( 'scene' ),
  76338. parser.getDependencies( 'animation' ),
  76339. parser.getDependencies( 'camera' ),
  76340. ] );
  76341. } ).then( function ( dependencies ) {
  76342. const result = {
  76343. scene: dependencies[ 0 ][ json.scene || 0 ],
  76344. scenes: dependencies[ 0 ],
  76345. animations: dependencies[ 1 ],
  76346. cameras: dependencies[ 2 ],
  76347. asset: json.asset,
  76348. parser: parser,
  76349. userData: {}
  76350. };
  76351. addUnknownExtensionsToUserData( extensions, result, json );
  76352. assignExtrasToUserData( result, json );
  76353. Promise.all( parser._invokeAll( function ( ext ) {
  76354. return ext.afterRoot && ext.afterRoot( result );
  76355. } ) ).then( function () {
  76356. onLoad( result );
  76357. } );
  76358. } ).catch( onError );
  76359. }
  76360. /**
  76361. * Marks the special nodes/meshes in json for efficient parse.
  76362. */
  76363. _markDefs() {
  76364. const nodeDefs = this.json.nodes || [];
  76365. const skinDefs = this.json.skins || [];
  76366. const meshDefs = this.json.meshes || [];
  76367. // Nothing in the node definition indicates whether it is a Bone or an
  76368. // Object3D. Use the skins' joint references to mark bones.
  76369. for ( let skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) {
  76370. const joints = skinDefs[ skinIndex ].joints;
  76371. for ( let i = 0, il = joints.length; i < il; i ++ ) {
  76372. nodeDefs[ joints[ i ] ].isBone = true;
  76373. }
  76374. }
  76375. // Iterate over all nodes, marking references to shared resources,
  76376. // as well as skeleton joints.
  76377. for ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {
  76378. const nodeDef = nodeDefs[ nodeIndex ];
  76379. if ( nodeDef.mesh !== undefined ) {
  76380. this._addNodeRef( this.meshCache, nodeDef.mesh );
  76381. // Nothing in the mesh definition indicates whether it is
  76382. // a SkinnedMesh or Mesh. Use the node's mesh reference
  76383. // to mark SkinnedMesh if node has skin.
  76384. if ( nodeDef.skin !== undefined ) {
  76385. meshDefs[ nodeDef.mesh ].isSkinnedMesh = true;
  76386. }
  76387. }
  76388. if ( nodeDef.camera !== undefined ) {
  76389. this._addNodeRef( this.cameraCache, nodeDef.camera );
  76390. }
  76391. }
  76392. }
  76393. /**
  76394. * Counts references to shared node / Object3D resources. These resources
  76395. * can be reused, or "instantiated", at multiple nodes in the scene
  76396. * hierarchy. Mesh, Camera, and Light instances are instantiated and must
  76397. * be marked. Non-scenegraph resources (like Materials, Geometries, and
  76398. * Textures) can be reused directly and are not marked here.
  76399. *
  76400. * Example: CesiumMilkTruck sample model reuses "Wheel" meshes.
  76401. */
  76402. _addNodeRef( cache, index ) {
  76403. if ( index === undefined ) return;
  76404. if ( cache.refs[ index ] === undefined ) {
  76405. cache.refs[ index ] = cache.uses[ index ] = 0;
  76406. }
  76407. cache.refs[ index ] ++;
  76408. }
  76409. /** Returns a reference to a shared resource, cloning it if necessary. */
  76410. _getNodeRef( cache, index, object ) {
  76411. if ( cache.refs[ index ] <= 1 ) return object;
  76412. const ref = object.clone();
  76413. // Propagates mappings to the cloned object, prevents mappings on the
  76414. // original object from being lost.
  76415. const updateMappings = ( original, clone ) => {
  76416. const mappings = this.associations.get( original );
  76417. if ( mappings != null ) {
  76418. this.associations.set( clone, mappings );
  76419. }
  76420. for ( const [ i, child ] of original.children.entries() ) {
  76421. updateMappings( child, clone.children[ i ] );
  76422. }
  76423. };
  76424. updateMappings( object, ref );
  76425. ref.name += '_instance_' + ( cache.uses[ index ] ++ );
  76426. return ref;
  76427. }
  76428. _invokeOne( func ) {
  76429. const extensions = Object.values( this.plugins );
  76430. extensions.push( this );
  76431. for ( let i = 0; i < extensions.length; i ++ ) {
  76432. const result = func( extensions[ i ] );
  76433. if ( result ) return result;
  76434. }
  76435. return null;
  76436. }
  76437. _invokeAll( func ) {
  76438. const extensions = Object.values( this.plugins );
  76439. extensions.unshift( this );
  76440. const pending = [];
  76441. for ( let i = 0; i < extensions.length; i ++ ) {
  76442. const result = func( extensions[ i ] );
  76443. if ( result ) pending.push( result );
  76444. }
  76445. return pending;
  76446. }
  76447. /**
  76448. * Requests the specified dependency asynchronously, with caching.
  76449. * @param {string} type
  76450. * @param {number} index
  76451. * @return {Promise<Object3D|Material|THREE.Texture|AnimationClip|ArrayBuffer|Object>}
  76452. */
  76453. getDependency( type, index ) {
  76454. const cacheKey = type + ':' + index;
  76455. let dependency = this.cache.get( cacheKey );
  76456. if ( ! dependency ) {
  76457. switch ( type ) {
  76458. case 'scene':
  76459. dependency = this.loadScene( index );
  76460. break;
  76461. case 'node':
  76462. dependency = this.loadNode( index );
  76463. break;
  76464. case 'mesh':
  76465. dependency = this._invokeOne( function ( ext ) {
  76466. return ext.loadMesh && ext.loadMesh( index );
  76467. } );
  76468. break;
  76469. case 'accessor':
  76470. dependency = this.loadAccessor( index );
  76471. break;
  76472. case 'bufferView':
  76473. dependency = this._invokeOne( function ( ext ) {
  76474. return ext.loadBufferView && ext.loadBufferView( index );
  76475. } );
  76476. break;
  76477. case 'buffer':
  76478. dependency = this.loadBuffer( index );
  76479. break;
  76480. case 'material':
  76481. dependency = this._invokeOne( function ( ext ) {
  76482. return ext.loadMaterial && ext.loadMaterial( index );
  76483. } );
  76484. break;
  76485. case 'texture':
  76486. dependency = this._invokeOne( function ( ext ) {
  76487. return ext.loadTexture && ext.loadTexture( index );
  76488. } );
  76489. break;
  76490. case 'skin':
  76491. dependency = this.loadSkin( index );
  76492. break;
  76493. case 'animation':
  76494. dependency = this._invokeOne( function ( ext ) {
  76495. return ext.loadAnimation && ext.loadAnimation( index );
  76496. } );
  76497. break;
  76498. case 'camera':
  76499. dependency = this.loadCamera( index );
  76500. break;
  76501. default:
  76502. throw new Error( 'Unknown type: ' + type );
  76503. }
  76504. this.cache.add( cacheKey, dependency );
  76505. }
  76506. return dependency;
  76507. }
  76508. /**
  76509. * Requests all dependencies of the specified type asynchronously, with caching.
  76510. * @param {string} type
  76511. * @return {Promise<Array<Object>>}
  76512. */
  76513. getDependencies( type ) {
  76514. let dependencies = this.cache.get( type );
  76515. if ( ! dependencies ) {
  76516. const parser = this;
  76517. const defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];
  76518. dependencies = Promise.all( defs.map( function ( def, index ) {
  76519. return parser.getDependency( type, index );
  76520. } ) );
  76521. this.cache.add( type, dependencies );
  76522. }
  76523. return dependencies;
  76524. }
  76525. /**
  76526. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
  76527. * @param {number} bufferIndex
  76528. * @return {Promise<ArrayBuffer>}
  76529. */
  76530. loadBuffer( bufferIndex ) {
  76531. const bufferDef = this.json.buffers[ bufferIndex ];
  76532. const loader = this.fileLoader;
  76533. if ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {
  76534. throw new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );
  76535. }
  76536. // If present, GLB container is required to be the first buffer.
  76537. if ( bufferDef.uri === undefined && bufferIndex === 0 ) {
  76538. return Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );
  76539. }
  76540. const options = this.options;
  76541. return new Promise( function ( resolve, reject ) {
  76542. loader.load( LoaderUtils.resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {
  76543. reject( new Error( 'THREE.GLTFLoader: Failed to load buffer "' + bufferDef.uri + '".' ) );
  76544. } );
  76545. } );
  76546. }
  76547. /**
  76548. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
  76549. * @param {number} bufferViewIndex
  76550. * @return {Promise<ArrayBuffer>}
  76551. */
  76552. loadBufferView( bufferViewIndex ) {
  76553. const bufferViewDef = this.json.bufferViews[ bufferViewIndex ];
  76554. return this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {
  76555. const byteLength = bufferViewDef.byteLength || 0;
  76556. const byteOffset = bufferViewDef.byteOffset || 0;
  76557. return buffer.slice( byteOffset, byteOffset + byteLength );
  76558. } );
  76559. }
  76560. /**
  76561. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors
  76562. * @param {number} accessorIndex
  76563. * @return {Promise<BufferAttribute|InterleavedBufferAttribute>}
  76564. */
  76565. loadAccessor( accessorIndex ) {
  76566. const parser = this;
  76567. const json = this.json;
  76568. const accessorDef = this.json.accessors[ accessorIndex ];
  76569. if ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {
  76570. // Ignore empty accessors, which may be used to declare runtime
  76571. // information about attributes coming from another source (e.g. Draco
  76572. // compression extension).
  76573. return Promise.resolve( null );
  76574. }
  76575. const pendingBufferViews = [];
  76576. if ( accessorDef.bufferView !== undefined ) {
  76577. pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );
  76578. } else {
  76579. pendingBufferViews.push( null );
  76580. }
  76581. if ( accessorDef.sparse !== undefined ) {
  76582. pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );
  76583. pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );
  76584. }
  76585. return Promise.all( pendingBufferViews ).then( function ( bufferViews ) {
  76586. const bufferView = bufferViews[ 0 ];
  76587. const itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];
  76588. const TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
  76589. // For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.
  76590. const elementBytes = TypedArray.BYTES_PER_ELEMENT;
  76591. const itemBytes = elementBytes * itemSize;
  76592. const byteOffset = accessorDef.byteOffset || 0;
  76593. const byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;
  76594. const normalized = accessorDef.normalized === true;
  76595. let array, bufferAttribute;
  76596. // The buffer is not interleaved if the stride is the item size in bytes.
  76597. if ( byteStride && byteStride !== itemBytes ) {
  76598. // Each "slice" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer
  76599. // This makes sure that IBA.count reflects accessor.count properly
  76600. const ibSlice = Math.floor( byteOffset / byteStride );
  76601. const ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;
  76602. let ib = parser.cache.get( ibCacheKey );
  76603. if ( ! ib ) {
  76604. array = new TypedArray( bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes );
  76605. // Integer parameters to IB/IBA are in array elements, not bytes.
  76606. ib = new InterleavedBuffer( array, byteStride / elementBytes );
  76607. parser.cache.add( ibCacheKey, ib );
  76608. }
  76609. bufferAttribute = new InterleavedBufferAttribute( ib, itemSize, ( byteOffset % byteStride ) / elementBytes, normalized );
  76610. } else {
  76611. if ( bufferView === null ) {
  76612. array = new TypedArray( accessorDef.count * itemSize );
  76613. } else {
  76614. array = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );
  76615. }
  76616. bufferAttribute = new BufferAttribute( array, itemSize, normalized );
  76617. }
  76618. // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors
  76619. if ( accessorDef.sparse !== undefined ) {
  76620. const itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;
  76621. const TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];
  76622. const byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;
  76623. const byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;
  76624. const sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );
  76625. const sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );
  76626. if ( bufferView !== null ) {
  76627. // Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.
  76628. bufferAttribute = new BufferAttribute( bufferAttribute.array.slice(), bufferAttribute.itemSize, bufferAttribute.normalized );
  76629. }
  76630. for ( let i = 0, il = sparseIndices.length; i < il; i ++ ) {
  76631. const index = sparseIndices[ i ];
  76632. bufferAttribute.setX( index, sparseValues[ i * itemSize ] );
  76633. if ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );
  76634. if ( itemSize >= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );
  76635. if ( itemSize >= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );
  76636. if ( itemSize >= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );
  76637. }
  76638. }
  76639. return bufferAttribute;
  76640. } );
  76641. }
  76642. /**
  76643. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
  76644. * @param {number} textureIndex
  76645. * @return {Promise<THREE.Texture>}
  76646. */
  76647. loadTexture( textureIndex ) {
  76648. const json = this.json;
  76649. const options = this.options;
  76650. const textureDef = json.textures[ textureIndex ];
  76651. const sourceIndex = textureDef.source;
  76652. const sourceDef = json.images[ sourceIndex ];
  76653. let loader = this.textureLoader;
  76654. if ( sourceDef.uri ) {
  76655. const handler = options.manager.getHandler( sourceDef.uri );
  76656. if ( handler !== null ) loader = handler;
  76657. }
  76658. return this.loadTextureImage( textureIndex, sourceIndex, loader );
  76659. }
  76660. loadTextureImage( textureIndex, sourceIndex, loader ) {
  76661. const parser = this;
  76662. const json = this.json;
  76663. const textureDef = json.textures[ textureIndex ];
  76664. const sourceDef = json.images[ sourceIndex ];
  76665. const cacheKey = ( sourceDef.uri || sourceDef.bufferView ) + ':' + textureDef.sampler;
  76666. if ( this.textureCache[ cacheKey ] ) {
  76667. // See https://github.com/mrdoob/three.js/issues/21559.
  76668. return this.textureCache[ cacheKey ];
  76669. }
  76670. const promise = this.loadImageSource( sourceIndex, loader ).then( function ( texture ) {
  76671. texture.flipY = false;
  76672. texture.name = textureDef.name || sourceDef.name || '';
  76673. const samplers = json.samplers || {};
  76674. const sampler = samplers[ textureDef.sampler ] || {};
  76675. /* //xzw 删除设置,因为已经makeTexDontResize
  76676. texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || LinearFilter;
  76677. texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || LinearMipmapLinearFilter;
  76678. texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || RepeatWrapping;
  76679. texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || RepeatWrapping;
  76680. */
  76681. parser.associations.set( texture, { textures: textureIndex } );
  76682. return texture;
  76683. } ).catch( function () {
  76684. return null;
  76685. } );
  76686. this.textureCache[ cacheKey ] = promise;
  76687. return promise;
  76688. }
  76689. loadImageSource( sourceIndex, loader ) {
  76690. const parser = this;
  76691. const json = this.json;
  76692. const options = this.options;
  76693. if ( this.sourceCache[ sourceIndex ] !== undefined ) {
  76694. return this.sourceCache[ sourceIndex ].then( ( texture ) => texture.clone() );
  76695. }
  76696. const sourceDef = json.images[ sourceIndex ];
  76697. const URL = self.URL || self.webkitURL;
  76698. let sourceURI = sourceDef.uri || '';
  76699. let isObjectURL = false;
  76700. if ( sourceDef.bufferView !== undefined ) {
  76701. // Load binary image data from bufferView, if provided.
  76702. sourceURI = parser.getDependency( 'bufferView', sourceDef.bufferView ).then( function ( bufferView ) {
  76703. isObjectURL = true;
  76704. const blob = new Blob( [ bufferView ], { type: sourceDef.mimeType } );
  76705. sourceURI = URL.createObjectURL( blob );
  76706. return sourceURI;
  76707. } );
  76708. } else if ( sourceDef.uri === undefined ) {
  76709. throw new Error( 'THREE.GLTFLoader: Image ' + sourceIndex + ' is missing URI and bufferView' );
  76710. }
  76711. const promise = Promise.resolve( sourceURI ).then( function ( sourceURI ) {
  76712. return new Promise( function ( resolve, reject ) {
  76713. //为了防止chrome出现报错 The source image could not be decoded. 导致reject,重新写贴图加载方式: xzw
  76714. parser.textureLoader.load(sourceURI, (tex)=>{
  76715. tex.minFilter = THREE.LinearMipmapLinearFilter; //原本:NearestMipMapNearestFilter 闪烁
  76716. Potree.Utils.makeTexDontResize(tex);
  76717. //console.log(tex.image.width, tex.image.height)
  76718. resolve(tex);
  76719. });
  76720. return;
  76721. let onLoad = resolve;
  76722. if ( loader.isImageBitmapLoader === true ) {
  76723. onLoad = function ( imageBitmap ) {
  76724. const texture = new Texture( imageBitmap );
  76725. texture.needsUpdate = true;
  76726. resolve( texture );
  76727. };
  76728. }
  76729. loader.load( LoaderUtils.resolveURL( sourceURI, options.path ), onLoad, undefined, reject );
  76730. } );
  76731. } ).then( function ( texture ) {
  76732. // Clean up resources and configure Texture.
  76733. if ( isObjectURL === true ) {
  76734. URL.revokeObjectURL( sourceURI );
  76735. }
  76736. texture.userData = {};//xzw add
  76737. texture.userData.mimeType = sourceDef.mimeType || getImageURIMimeType( sourceDef.uri || sourceDef.mimeType );
  76738. return texture;
  76739. } ).catch( function ( error ) {
  76740. console.error( 'THREE.GLTFLoader: Couldn\'t load texture', sourceURI );
  76741. throw error;
  76742. } );
  76743. this.sourceCache[ sourceIndex ] = promise;
  76744. return promise;
  76745. }
  76746. /**
  76747. * Asynchronously assigns a texture to the given material parameters.
  76748. * @param {Object} materialParams
  76749. * @param {string} mapName
  76750. * @param {Object} mapDef
  76751. * @return {Promise<Texture>}
  76752. */
  76753. assignTexture( materialParams, mapName, mapDef, encoding ) {
  76754. const parser = this;
  76755. return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
  76756. // Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured
  76757. // However, we will copy UV set 0 to UV set 1 on demand for aoMap
  76758. if ( mapDef.texCoord !== undefined && mapDef.texCoord != 0 && ! ( mapName === 'aoMap' && mapDef.texCoord == 1 ) ) {
  76759. console.warn( 'THREE.GLTFLoader: Custom UV set ' + mapDef.texCoord + ' for texture ' + mapName + ' not yet supported.' );
  76760. }
  76761. if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {
  76762. const transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;
  76763. if ( transform ) {
  76764. const gltfReference = parser.associations.get( texture );
  76765. texture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );
  76766. parser.associations.set( texture, gltfReference );
  76767. }
  76768. }
  76769. if ( encoding !== undefined ) {
  76770. texture.encoding = encoding;
  76771. }
  76772. materialParams[ mapName ] = texture;
  76773. return texture;
  76774. } );
  76775. }
  76776. /**
  76777. * Assigns final material to a Mesh, Line, or Points instance. The instance
  76778. * already has a material (generated from the glTF material options alone)
  76779. * but reuse of the same glTF material may require multiple threejs materials
  76780. * to accommodate different primitive types, defines, etc. New materials will
  76781. * be created if necessary, and reused from a cache.
  76782. * @param {Object3D} mesh Mesh, Line, or Points instance.
  76783. */
  76784. assignFinalMaterial( mesh ) {
  76785. const geometry = mesh.geometry;
  76786. let material = mesh.material;
  76787. const useDerivativeTangents = geometry.attributes.tangent === undefined;
  76788. const useVertexColors = geometry.attributes.color !== undefined;
  76789. const useFlatShading = geometry.attributes.normal === undefined;
  76790. if ( mesh.isPoints ) {
  76791. const cacheKey = 'PointsMaterial:' + material.uuid;
  76792. let pointsMaterial = this.cache.get( cacheKey );
  76793. if ( ! pointsMaterial ) {
  76794. pointsMaterial = new PointsMaterial();
  76795. Material.prototype.copy.call( pointsMaterial, material );
  76796. pointsMaterial.color.copy( material.color );
  76797. pointsMaterial.map = material.map;
  76798. pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
  76799. this.cache.add( cacheKey, pointsMaterial );
  76800. }
  76801. material = pointsMaterial;
  76802. } else if ( mesh.isLine ) {
  76803. const cacheKey = 'LineBasicMaterial:' + material.uuid;
  76804. let lineMaterial = this.cache.get( cacheKey );
  76805. if ( ! lineMaterial ) {
  76806. lineMaterial = new LineBasicMaterial();
  76807. Material.prototype.copy.call( lineMaterial, material );
  76808. lineMaterial.color.copy( material.color );
  76809. this.cache.add( cacheKey, lineMaterial );
  76810. }
  76811. material = lineMaterial;
  76812. }
  76813. // Clone the material if it will be modified
  76814. if ( useDerivativeTangents || useVertexColors || useFlatShading ) {
  76815. let cacheKey = 'ClonedMaterial:' + material.uuid + ':';
  76816. if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
  76817. if ( useDerivativeTangents ) cacheKey += 'derivative-tangents:';
  76818. if ( useVertexColors ) cacheKey += 'vertex-colors:';
  76819. if ( useFlatShading ) cacheKey += 'flat-shading:';
  76820. let cachedMaterial = this.cache.get( cacheKey );
  76821. if ( ! cachedMaterial ) {
  76822. cachedMaterial = material.clone();
  76823. if ( useVertexColors ) cachedMaterial.vertexColors = true;
  76824. if ( useFlatShading ) cachedMaterial.flatShading = true;
  76825. if ( useDerivativeTangents ) {
  76826. // https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995
  76827. if ( cachedMaterial.normalScale ) cachedMaterial.normalScale.y *= - 1;
  76828. if ( cachedMaterial.clearcoatNormalScale ) cachedMaterial.clearcoatNormalScale.y *= - 1;
  76829. }
  76830. this.cache.add( cacheKey, cachedMaterial );
  76831. this.associations.set( cachedMaterial, this.associations.get( material ) );
  76832. }
  76833. material = cachedMaterial;
  76834. }
  76835. // workarounds for mesh and geometry
  76836. if ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) {
  76837. geometry.setAttribute( 'uv2', geometry.attributes.uv );
  76838. }
  76839. mesh.material = material;
  76840. }
  76841. getMaterialType( /* materialIndex */ ) {
  76842. return MeshStandardMaterial;
  76843. }
  76844. /**
  76845. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials
  76846. * @param {number} materialIndex
  76847. * @return {Promise<Material>}
  76848. */
  76849. loadMaterial( materialIndex ) {
  76850. const parser = this;
  76851. const json = this.json;
  76852. const extensions = this.extensions;
  76853. const materialDef = json.materials[ materialIndex ];
  76854. let materialType;
  76855. const materialParams = {};
  76856. const materialExtensions = materialDef.extensions || {};
  76857. const pending = [];
  76858. if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {
  76859. const sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];
  76860. materialType = BasicMaterial;//sgExtension.getMaterialType(); //xzw 改
  76861. pending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );
  76862. } else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {
  76863. const kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];
  76864. materialType = BasicMaterial;//kmuExtension.getMaterialType(); //xzw 改
  76865. pending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );
  76866. } else {
  76867. // Specification:
  76868. // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
  76869. const metallicRoughness = materialDef.pbrMetallicRoughness || {};
  76870. materialParams.color = new Color( 1.0, 1.0, 1.0 );
  76871. materialParams.opacity = 1.0;
  76872. if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
  76873. const array = metallicRoughness.baseColorFactor;
  76874. materialParams.color.fromArray( array );
  76875. materialParams.opacity = array[ 3 ];
  76876. }
  76877. if ( metallicRoughness.baseColorTexture !== undefined ) {
  76878. pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, sRGBEncoding ) );
  76879. }
  76880. materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
  76881. materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
  76882. if ( metallicRoughness.metallicRoughnessTexture !== undefined ) {
  76883. pending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );
  76884. pending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );
  76885. }
  76886. materialType = this._invokeOne( function ( ext ) {
  76887. return BasicMaterial//kmuExtension.getMaterialType(); //xzw 改
  76888. //return ext.getMaterialType && ext.getMaterialType( materialIndex );
  76889. } );
  76890. pending.push( Promise.all( this._invokeAll( function ( ext ) {
  76891. return ext.extendMaterialParams && ext.extendMaterialParams( materialIndex, materialParams );
  76892. } ) ) );
  76893. }
  76894. if ( materialDef.doubleSided === true ) {
  76895. materialParams.side = DoubleSide;
  76896. }
  76897. const alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;
  76898. if ( alphaMode === ALPHA_MODES.BLEND ) {
  76899. materialParams.transparent = true;
  76900. // See: https://github.com/mrdoob/three.js/issues/17706
  76901. materialParams.depthWrite = false;
  76902. } else {
  76903. materialParams.transparent = false;
  76904. if ( alphaMode === ALPHA_MODES.MASK ) {
  76905. materialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
  76906. }
  76907. }
  76908. if ( materialDef.normalTexture !== undefined && materialType !== MeshBasicMaterial ) {
  76909. pending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );
  76910. materialParams.normalScale = new Vector2( 1, 1 );
  76911. if ( materialDef.normalTexture.scale !== undefined ) {
  76912. const scale = materialDef.normalTexture.scale;
  76913. materialParams.normalScale.set( scale, scale );
  76914. }
  76915. }
  76916. if ( materialDef.occlusionTexture !== undefined && materialType !== MeshBasicMaterial ) {
  76917. pending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );
  76918. if ( materialDef.occlusionTexture.strength !== undefined ) {
  76919. materialParams.aoMapIntensity = materialDef.occlusionTexture.strength;
  76920. }
  76921. }
  76922. if ( materialDef.emissiveFactor !== undefined && materialType !== MeshBasicMaterial ) {
  76923. materialParams.emissive = new Color().fromArray( materialDef.emissiveFactor );
  76924. }
  76925. if ( materialDef.emissiveTexture !== undefined && materialType !== MeshBasicMaterial ) {
  76926. pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture, sRGBEncoding ) );
  76927. }
  76928. return Promise.all( pending ).then( function () {
  76929. let material;
  76930. if ( materialType === GLTFMeshStandardSGMaterial ) {
  76931. material = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );
  76932. } else {
  76933. material = new materialType( materialParams );
  76934. }
  76935. if ( materialDef.name ) material.name = materialDef.name;
  76936. assignExtrasToUserData( material, materialDef );
  76937. parser.associations.set( material, { materials: materialIndex } );
  76938. if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
  76939. return material;
  76940. } );
  76941. }
  76942. /** When Object3D instances are targeted by animation, they need unique names. */
  76943. createUniqueName( originalName ) {
  76944. const sanitizedName = PropertyBinding.sanitizeNodeName( originalName || '' );
  76945. let name = sanitizedName;
  76946. for ( let i = 1; this.nodeNamesUsed[ name ]; ++ i ) {
  76947. name = sanitizedName + '_' + i;
  76948. }
  76949. this.nodeNamesUsed[ name ] = true;
  76950. return name;
  76951. }
  76952. /**
  76953. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
  76954. *
  76955. * Creates BufferGeometries from primitives.
  76956. *
  76957. * @param {Array<GLTF.Primitive>} primitives
  76958. * @return {Promise<Array<BufferGeometry>>}
  76959. */
  76960. loadGeometries( primitives ) {
  76961. const parser = this;
  76962. const extensions = this.extensions;
  76963. const cache = this.primitiveCache;
  76964. function createDracoPrimitive( primitive ) {
  76965. return extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]
  76966. .decodePrimitive( primitive, parser )
  76967. .then( function ( geometry ) {
  76968. return addPrimitiveAttributes( geometry, primitive, parser );
  76969. } );
  76970. }
  76971. const pending = [];
  76972. for ( let i = 0, il = primitives.length; i < il; i ++ ) {
  76973. const primitive = primitives[ i ];
  76974. const cacheKey = createPrimitiveKey( primitive );
  76975. // See if we've already created this geometry
  76976. const cached = cache[ cacheKey ];
  76977. if ( cached ) {
  76978. // Use the cached geometry if it exists
  76979. pending.push( cached.promise );
  76980. } else {
  76981. let geometryPromise;
  76982. if ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {
  76983. // Use DRACO geometry if available
  76984. geometryPromise = createDracoPrimitive( primitive );
  76985. } else {
  76986. // Otherwise create a new geometry
  76987. geometryPromise = addPrimitiveAttributes( new BufferGeometry(), primitive, parser );
  76988. }
  76989. // Cache this geometry
  76990. cache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };
  76991. pending.push( geometryPromise );
  76992. }
  76993. }
  76994. return Promise.all( pending );
  76995. }
  76996. /**
  76997. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes
  76998. * @param {number} meshIndex
  76999. * @return {Promise<Group|Mesh|SkinnedMesh>}
  77000. */
  77001. loadMesh( meshIndex ) {
  77002. const parser = this;
  77003. const json = this.json;
  77004. const extensions = this.extensions;
  77005. const meshDef = json.meshes[ meshIndex ];
  77006. const primitives = meshDef.primitives;
  77007. const pending = [];
  77008. for ( let i = 0, il = primitives.length; i < il; i ++ ) {
  77009. const material = primitives[ i ].material === undefined
  77010. ? createDefaultMaterial( this.cache )
  77011. : this.getDependency( 'material', primitives[ i ].material );
  77012. pending.push( material );
  77013. }
  77014. pending.push( parser.loadGeometries( primitives ) );
  77015. return Promise.all( pending ).then( function ( results ) {
  77016. const materials = results.slice( 0, results.length - 1 );
  77017. const geometries = results[ results.length - 1 ];
  77018. const meshes = [];
  77019. for ( let i = 0, il = geometries.length; i < il; i ++ ) {
  77020. const geometry = geometries[ i ];
  77021. const primitive = primitives[ i ];
  77022. // 1. create Mesh
  77023. let mesh;
  77024. const material = materials[ i ];
  77025. if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
  77026. primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
  77027. primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
  77028. primitive.mode === undefined ) {
  77029. // .isSkinnedMesh isn't in glTF spec. See ._markDefs()
  77030. mesh = meshDef.isSkinnedMesh === true
  77031. ? new SkinnedMesh( geometry, material )
  77032. : new Mesh( geometry, material );
  77033. if ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {
  77034. // we normalize floating point skin weight array to fix malformed assets (see #15319)
  77035. // it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
  77036. mesh.normalizeSkinWeights();
  77037. }
  77038. if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
  77039. mesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleStripDrawMode );
  77040. } else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
  77041. mesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleFanDrawMode );
  77042. }
  77043. } else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
  77044. mesh = new LineSegments( geometry, material );
  77045. } else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
  77046. mesh = new Line( geometry, material );
  77047. } else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
  77048. mesh = new LineLoop( geometry, material );
  77049. } else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
  77050. mesh = new Points( geometry, material );
  77051. } else {
  77052. throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
  77053. }
  77054. if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
  77055. updateMorphTargets( mesh, meshDef );
  77056. }
  77057. mesh.name = parser.createUniqueName( meshDef.name || ( 'mesh_' + meshIndex ) );
  77058. assignExtrasToUserData( mesh, meshDef );
  77059. if ( primitive.extensions ) addUnknownExtensionsToUserData( extensions, mesh, primitive );
  77060. parser.assignFinalMaterial( mesh );
  77061. meshes.push( mesh );
  77062. }
  77063. for ( let i = 0, il = meshes.length; i < il; i ++ ) {
  77064. parser.associations.set( meshes[ i ], {
  77065. meshes: meshIndex,
  77066. primitives: i
  77067. } );
  77068. }
  77069. if ( meshes.length === 1 ) {
  77070. return meshes[ 0 ];
  77071. }
  77072. const group = new Group();
  77073. parser.associations.set( group, { meshes: meshIndex } );
  77074. for ( let i = 0, il = meshes.length; i < il; i ++ ) {
  77075. group.add( meshes[ i ] );
  77076. }
  77077. return group;
  77078. } );
  77079. }
  77080. /**
  77081. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras
  77082. * @param {number} cameraIndex
  77083. * @return {Promise<THREE.Camera>}
  77084. */
  77085. loadCamera( cameraIndex ) {
  77086. let camera;
  77087. const cameraDef = this.json.cameras[ cameraIndex ];
  77088. const params = cameraDef[ cameraDef.type ];
  77089. if ( ! params ) {
  77090. console.warn( 'THREE.GLTFLoader: Missing camera parameters.' );
  77091. return;
  77092. }
  77093. if ( cameraDef.type === 'perspective' ) {
  77094. camera = new PerspectiveCamera( MathUtils$1.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );
  77095. } else if ( cameraDef.type === 'orthographic' ) {
  77096. camera = new OrthographicCamera( - params.xmag, params.xmag, params.ymag, - params.ymag, params.znear, params.zfar );
  77097. }
  77098. if ( cameraDef.name ) camera.name = this.createUniqueName( cameraDef.name );
  77099. assignExtrasToUserData( camera, cameraDef );
  77100. return Promise.resolve( camera );
  77101. }
  77102. /**
  77103. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
  77104. * @param {number} skinIndex
  77105. * @return {Promise<Object>}
  77106. */
  77107. loadSkin( skinIndex ) {
  77108. const skinDef = this.json.skins[ skinIndex ];
  77109. const skinEntry = { joints: skinDef.joints };
  77110. if ( skinDef.inverseBindMatrices === undefined ) {
  77111. return Promise.resolve( skinEntry );
  77112. }
  77113. return this.getDependency( 'accessor', skinDef.inverseBindMatrices ).then( function ( accessor ) {
  77114. skinEntry.inverseBindMatrices = accessor;
  77115. return skinEntry;
  77116. } );
  77117. }
  77118. /**
  77119. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations
  77120. * @param {number} animationIndex
  77121. * @return {Promise<AnimationClip>}
  77122. */
  77123. loadAnimation( animationIndex ) {
  77124. const json = this.json;
  77125. const animationDef = json.animations[ animationIndex ];
  77126. const pendingNodes = [];
  77127. const pendingInputAccessors = [];
  77128. const pendingOutputAccessors = [];
  77129. const pendingSamplers = [];
  77130. const pendingTargets = [];
  77131. for ( let i = 0, il = animationDef.channels.length; i < il; i ++ ) {
  77132. const channel = animationDef.channels[ i ];
  77133. const sampler = animationDef.samplers[ channel.sampler ];
  77134. const target = channel.target;
  77135. const name = target.node;
  77136. const input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;
  77137. const output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;
  77138. pendingNodes.push( this.getDependency( 'node', name ) );
  77139. pendingInputAccessors.push( this.getDependency( 'accessor', input ) );
  77140. pendingOutputAccessors.push( this.getDependency( 'accessor', output ) );
  77141. pendingSamplers.push( sampler );
  77142. pendingTargets.push( target );
  77143. }
  77144. return Promise.all( [
  77145. Promise.all( pendingNodes ),
  77146. Promise.all( pendingInputAccessors ),
  77147. Promise.all( pendingOutputAccessors ),
  77148. Promise.all( pendingSamplers ),
  77149. Promise.all( pendingTargets )
  77150. ] ).then( function ( dependencies ) {
  77151. const nodes = dependencies[ 0 ];
  77152. const inputAccessors = dependencies[ 1 ];
  77153. const outputAccessors = dependencies[ 2 ];
  77154. const samplers = dependencies[ 3 ];
  77155. const targets = dependencies[ 4 ];
  77156. const tracks = [];
  77157. for ( let i = 0, il = nodes.length; i < il; i ++ ) {
  77158. const node = nodes[ i ];
  77159. const inputAccessor = inputAccessors[ i ];
  77160. const outputAccessor = outputAccessors[ i ];
  77161. const sampler = samplers[ i ];
  77162. const target = targets[ i ];
  77163. if ( node === undefined ) continue;
  77164. node.updateMatrix();
  77165. let TypedKeyframeTrack;
  77166. switch ( PATH_PROPERTIES[ target.path ] ) {
  77167. case PATH_PROPERTIES.weights:
  77168. TypedKeyframeTrack = NumberKeyframeTrack;
  77169. break;
  77170. case PATH_PROPERTIES.rotation:
  77171. TypedKeyframeTrack = QuaternionKeyframeTrack;
  77172. break;
  77173. case PATH_PROPERTIES.position:
  77174. case PATH_PROPERTIES.scale:
  77175. default:
  77176. TypedKeyframeTrack = VectorKeyframeTrack;
  77177. break;
  77178. }
  77179. const targetName = node.name ? node.name : node.uuid;
  77180. const interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : InterpolateLinear;
  77181. const targetNames = [];
  77182. if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {
  77183. node.traverse( function ( object ) {
  77184. if ( object.morphTargetInfluences ) {
  77185. targetNames.push( object.name ? object.name : object.uuid );
  77186. }
  77187. } );
  77188. } else {
  77189. targetNames.push( targetName );
  77190. }
  77191. let outputArray = outputAccessor.array;
  77192. if ( outputAccessor.normalized ) {
  77193. const scale = getNormalizedComponentScale( outputArray.constructor );
  77194. const scaled = new Float32Array( outputArray.length );
  77195. for ( let j = 0, jl = outputArray.length; j < jl; j ++ ) {
  77196. scaled[ j ] = outputArray[ j ] * scale;
  77197. }
  77198. outputArray = scaled;
  77199. }
  77200. for ( let j = 0, jl = targetNames.length; j < jl; j ++ ) {
  77201. const track = new TypedKeyframeTrack(
  77202. targetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],
  77203. inputAccessor.array,
  77204. outputArray,
  77205. interpolation
  77206. );
  77207. // Override interpolation with custom factory method.
  77208. if ( sampler.interpolation === 'CUBICSPLINE' ) {
  77209. track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {
  77210. // A CUBICSPLINE keyframe in glTF has three output values for each input value,
  77211. // representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()
  77212. // must be divided by three to get the interpolant's sampleSize argument.
  77213. const interpolantType = ( this instanceof QuaternionKeyframeTrack ) ? GLTFCubicSplineQuaternionInterpolant : GLTFCubicSplineInterpolant;
  77214. return new interpolantType( this.times, this.values, this.getValueSize() / 3, result );
  77215. };
  77216. // Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.
  77217. track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;
  77218. }
  77219. tracks.push( track );
  77220. }
  77221. }
  77222. const name = animationDef.name ? animationDef.name : 'animation_' + animationIndex;
  77223. return new AnimationClip( name, undefined, tracks );
  77224. } );
  77225. }
  77226. createNodeMesh( nodeIndex ) {
  77227. const json = this.json;
  77228. const parser = this;
  77229. const nodeDef = json.nodes[ nodeIndex ];
  77230. if ( nodeDef.mesh === undefined ) return null;
  77231. return parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) {
  77232. const node = parser._getNodeRef( parser.meshCache, nodeDef.mesh, mesh );
  77233. // if weights are provided on the node, override weights on the mesh.
  77234. if ( nodeDef.weights !== undefined ) {
  77235. node.traverse( function ( o ) {
  77236. if ( ! o.isMesh ) return;
  77237. for ( let i = 0, il = nodeDef.weights.length; i < il; i ++ ) {
  77238. o.morphTargetInfluences[ i ] = nodeDef.weights[ i ];
  77239. }
  77240. } );
  77241. }
  77242. return node;
  77243. } );
  77244. }
  77245. /**
  77246. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy
  77247. * @param {number} nodeIndex
  77248. * @return {Promise<Object3D>}
  77249. */
  77250. loadNode( nodeIndex ) {
  77251. const json = this.json;
  77252. const extensions = this.extensions;
  77253. const parser = this;
  77254. const nodeDef = json.nodes[ nodeIndex ];
  77255. // reserve node's name before its dependencies, so the root has the intended name.
  77256. const nodeName = nodeDef.name ? parser.createUniqueName( nodeDef.name ) : '';
  77257. return ( function () {
  77258. const pending = [];
  77259. const meshPromise = parser._invokeOne( function ( ext ) {
  77260. return ext.createNodeMesh && ext.createNodeMesh( nodeIndex );
  77261. } );
  77262. if ( meshPromise ) {
  77263. pending.push( meshPromise );
  77264. }
  77265. if ( nodeDef.camera !== undefined ) {
  77266. pending.push( parser.getDependency( 'camera', nodeDef.camera ).then( function ( camera ) {
  77267. return parser._getNodeRef( parser.cameraCache, nodeDef.camera, camera );
  77268. } ) );
  77269. }
  77270. parser._invokeAll( function ( ext ) {
  77271. return ext.createNodeAttachment && ext.createNodeAttachment( nodeIndex );
  77272. } ).forEach( function ( promise ) {
  77273. pending.push( promise );
  77274. } );
  77275. return Promise.all( pending );
  77276. }() ).then( function ( objects ) {
  77277. let node;
  77278. // .isBone isn't in glTF spec. See ._markDefs
  77279. if ( nodeDef.isBone === true ) {
  77280. node = new Bone();
  77281. } else if ( objects.length > 1 ) {
  77282. node = new Group();
  77283. } else if ( objects.length === 1 ) {
  77284. node = objects[ 0 ];
  77285. } else {
  77286. node = new Object3D();
  77287. }
  77288. if ( node !== objects[ 0 ] ) {
  77289. for ( let i = 0, il = objects.length; i < il; i ++ ) {
  77290. node.add( objects[ i ] );
  77291. }
  77292. }
  77293. if ( nodeDef.name ) {
  77294. node.userData.name = nodeDef.name;
  77295. node.name = nodeName;
  77296. }
  77297. assignExtrasToUserData( node, nodeDef );
  77298. if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
  77299. if ( nodeDef.matrix !== undefined ) {
  77300. const matrix = new Matrix4();
  77301. matrix.fromArray( nodeDef.matrix );
  77302. node.applyMatrix4( matrix );
  77303. } else {
  77304. if ( nodeDef.translation !== undefined ) {
  77305. node.position.fromArray( nodeDef.translation );
  77306. }
  77307. if ( nodeDef.rotation !== undefined ) {
  77308. node.quaternion.fromArray( nodeDef.rotation );
  77309. }
  77310. if ( nodeDef.scale !== undefined ) {
  77311. node.scale.fromArray( nodeDef.scale );
  77312. }
  77313. }
  77314. if ( ! parser.associations.has( node ) ) {
  77315. parser.associations.set( node, {} );
  77316. }
  77317. parser.associations.get( node ).nodes = nodeIndex;
  77318. return node;
  77319. } );
  77320. }
  77321. /**
  77322. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes
  77323. * @param {number} sceneIndex
  77324. * @return {Promise<Group>}
  77325. */
  77326. loadScene( sceneIndex ) {
  77327. const json = this.json;
  77328. const extensions = this.extensions;
  77329. const sceneDef = this.json.scenes[ sceneIndex ];
  77330. const parser = this;
  77331. // Loader returns Group, not Scene.
  77332. // See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172
  77333. const scene = new Group();
  77334. if ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name );
  77335. assignExtrasToUserData( scene, sceneDef );
  77336. if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );
  77337. const nodeIds = sceneDef.nodes || [];
  77338. const pending = [];
  77339. for ( let i = 0, il = nodeIds.length; i < il; i ++ ) {
  77340. pending.push( buildNodeHierarchy( nodeIds[ i ], scene, json, parser ) );
  77341. }
  77342. return Promise.all( pending ).then( function () {
  77343. // Removes dangling associations, associations that reference a node that
  77344. // didn't make it into the scene.
  77345. const reduceAssociations = ( node ) => {
  77346. const reducedAssociations = new Map();
  77347. for ( const [ key, value ] of parser.associations ) {
  77348. if ( key instanceof Material || key instanceof Texture ) {
  77349. reducedAssociations.set( key, value );
  77350. }
  77351. }
  77352. node.traverse( ( node ) => {
  77353. const mappings = parser.associations.get( node );
  77354. if ( mappings != null ) {
  77355. reducedAssociations.set( node, mappings );
  77356. }
  77357. } );
  77358. return reducedAssociations;
  77359. };
  77360. parser.associations = reduceAssociations( scene );
  77361. return scene;
  77362. } );
  77363. }
  77364. }
  77365. function buildNodeHierarchy( nodeId, parentObject, json, parser ) {
  77366. const nodeDef = json.nodes[ nodeId ];
  77367. return parser.getDependency( 'node', nodeId ).then( function ( node ) {
  77368. if ( nodeDef.skin === undefined ) return node;
  77369. // build skeleton here as well
  77370. let skinEntry;
  77371. return parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) {
  77372. skinEntry = skin;
  77373. const pendingJoints = [];
  77374. for ( let i = 0, il = skinEntry.joints.length; i < il; i ++ ) {
  77375. pendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) );
  77376. }
  77377. return Promise.all( pendingJoints );
  77378. } ).then( function ( jointNodes ) {
  77379. node.traverse( function ( mesh ) {
  77380. if ( ! mesh.isMesh ) return;
  77381. const bones = [];
  77382. const boneInverses = [];
  77383. for ( let j = 0, jl = jointNodes.length; j < jl; j ++ ) {
  77384. const jointNode = jointNodes[ j ];
  77385. if ( jointNode ) {
  77386. bones.push( jointNode );
  77387. const mat = new Matrix4();
  77388. if ( skinEntry.inverseBindMatrices !== undefined ) {
  77389. mat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 );
  77390. }
  77391. boneInverses.push( mat );
  77392. } else {
  77393. console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinEntry.joints[ j ] );
  77394. }
  77395. }
  77396. mesh.bind( new Skeleton( bones, boneInverses ), mesh.matrixWorld );
  77397. } );
  77398. return node;
  77399. } );
  77400. } ).then( function ( node ) {
  77401. // build node hierachy
  77402. parentObject.add( node );
  77403. const pending = [];
  77404. if ( nodeDef.children ) {
  77405. const children = nodeDef.children;
  77406. for ( let i = 0, il = children.length; i < il; i ++ ) {
  77407. const child = children[ i ];
  77408. pending.push( buildNodeHierarchy( child, node, json, parser ) );
  77409. }
  77410. }
  77411. return Promise.all( pending );
  77412. } );
  77413. }
  77414. /**
  77415. * @param {BufferGeometry} geometry
  77416. * @param {GLTF.Primitive} primitiveDef
  77417. * @param {GLTFParser} parser
  77418. */
  77419. function computeBounds( geometry, primitiveDef, parser ) {
  77420. const attributes = primitiveDef.attributes;
  77421. const box = new Box3();
  77422. if ( attributes.POSITION !== undefined ) {
  77423. const accessor = parser.json.accessors[ attributes.POSITION ];
  77424. const min = accessor.min;
  77425. const max = accessor.max;
  77426. // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.
  77427. if ( min !== undefined && max !== undefined ) {
  77428. box.set(
  77429. new Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
  77430. new Vector3( max[ 0 ], max[ 1 ], max[ 2 ] )
  77431. );
  77432. if ( accessor.normalized ) {
  77433. const boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );
  77434. box.min.multiplyScalar( boxScale );
  77435. box.max.multiplyScalar( boxScale );
  77436. }
  77437. } else {
  77438. console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );
  77439. return;
  77440. }
  77441. } else {
  77442. return;
  77443. }
  77444. const targets = primitiveDef.targets;
  77445. if ( targets !== undefined ) {
  77446. const maxDisplacement = new Vector3();
  77447. const vector = new Vector3();
  77448. for ( let i = 0, il = targets.length; i < il; i ++ ) {
  77449. const target = targets[ i ];
  77450. if ( target.POSITION !== undefined ) {
  77451. const accessor = parser.json.accessors[ target.POSITION ];
  77452. const min = accessor.min;
  77453. const max = accessor.max;
  77454. // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.
  77455. if ( min !== undefined && max !== undefined ) {
  77456. // we need to get max of absolute components because target weight is [-1,1]
  77457. vector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) );
  77458. vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );
  77459. vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );
  77460. if ( accessor.normalized ) {
  77461. const boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );
  77462. vector.multiplyScalar( boxScale );
  77463. }
  77464. // Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative
  77465. // to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets
  77466. // are used to implement key-frame animations and as such only two are active at a time - this results in very large
  77467. // boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size.
  77468. maxDisplacement.max( vector );
  77469. } else {
  77470. console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );
  77471. }
  77472. }
  77473. }
  77474. // As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets.
  77475. box.expandByVector( maxDisplacement );
  77476. }
  77477. geometry.boundingBox = box;
  77478. const sphere = new Sphere();
  77479. box.getCenter( sphere.center );
  77480. sphere.radius = box.min.distanceTo( box.max ) / 2;
  77481. geometry.boundingSphere = sphere;
  77482. }
  77483. /**
  77484. * @param {BufferGeometry} geometry
  77485. * @param {GLTF.Primitive} primitiveDef
  77486. * @param {GLTFParser} parser
  77487. * @return {Promise<BufferGeometry>}
  77488. */
  77489. function addPrimitiveAttributes( geometry, primitiveDef, parser ) {
  77490. const attributes = primitiveDef.attributes;
  77491. const pending = [];
  77492. function assignAttributeAccessor( accessorIndex, attributeName ) {
  77493. return parser.getDependency( 'accessor', accessorIndex )
  77494. .then( function ( accessor ) {
  77495. geometry.setAttribute( attributeName, accessor );
  77496. } );
  77497. }
  77498. for ( const gltfAttributeName in attributes ) {
  77499. const threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();
  77500. // Skip attributes already provided by e.g. Draco extension.
  77501. if ( threeAttributeName in geometry.attributes ) continue;
  77502. pending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );
  77503. }
  77504. if ( primitiveDef.indices !== undefined && ! geometry.index ) {
  77505. const accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {
  77506. geometry.setIndex( accessor );
  77507. } );
  77508. pending.push( accessor );
  77509. }
  77510. assignExtrasToUserData( geometry, primitiveDef );
  77511. computeBounds( geometry, primitiveDef, parser );
  77512. return Promise.all( pending ).then( function () {
  77513. return primitiveDef.targets !== undefined
  77514. ? addMorphTargets( geometry, primitiveDef.targets, parser )
  77515. : geometry;
  77516. } );
  77517. }
  77518. /**
  77519. * @param {BufferGeometry} geometry
  77520. * @param {Number} drawMode
  77521. * @return {BufferGeometry}
  77522. */
  77523. function toTrianglesDrawMode( geometry, drawMode ) {
  77524. let index = geometry.getIndex();
  77525. // generate index if not present
  77526. if ( index === null ) {
  77527. const indices = [];
  77528. const position = geometry.getAttribute( 'position' );
  77529. if ( position !== undefined ) {
  77530. for ( let i = 0; i < position.count; i ++ ) {
  77531. indices.push( i );
  77532. }
  77533. geometry.setIndex( indices );
  77534. index = geometry.getIndex();
  77535. } else {
  77536. console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
  77537. return geometry;
  77538. }
  77539. }
  77540. //
  77541. const numberOfTriangles = index.count - 2;
  77542. const newIndices = [];
  77543. if ( drawMode === TriangleFanDrawMode ) {
  77544. // gl.TRIANGLE_FAN
  77545. for ( let i = 1; i <= numberOfTriangles; i ++ ) {
  77546. newIndices.push( index.getX( 0 ) );
  77547. newIndices.push( index.getX( i ) );
  77548. newIndices.push( index.getX( i + 1 ) );
  77549. }
  77550. } else {
  77551. // gl.TRIANGLE_STRIP
  77552. for ( let i = 0; i < numberOfTriangles; i ++ ) {
  77553. if ( i % 2 === 0 ) {
  77554. newIndices.push( index.getX( i ) );
  77555. newIndices.push( index.getX( i + 1 ) );
  77556. newIndices.push( index.getX( i + 2 ) );
  77557. } else {
  77558. newIndices.push( index.getX( i + 2 ) );
  77559. newIndices.push( index.getX( i + 1 ) );
  77560. newIndices.push( index.getX( i ) );
  77561. }
  77562. }
  77563. }
  77564. if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {
  77565. console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );
  77566. }
  77567. // build final geometry
  77568. const newGeometry = geometry.clone();
  77569. newGeometry.setIndex( newIndices );
  77570. return newGeometry;
  77571. }
  77572. let globalThis = window; //add 有的app没有globalThis. 2023.1
  77573. /*! *****************************************************************************
  77574. Copyright (c) Microsoft Corporation.
  77575. Permission to use, copy, modify, and/or distribute this software for any
  77576. purpose with or without fee is hereby granted.
  77577. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  77578. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  77579. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  77580. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  77581. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  77582. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  77583. PERFORMANCE OF THIS SOFTWARE.
  77584. ***************************************************************************** */
  77585. window.visiVertexCount = 0;
  77586. window.visiGeoCount = 0;
  77587. const maxVertexVisi = 5e6;
  77588. const maxTexVisi = 500;
  77589. function __awaiter(thisArg, _arguments, P, generator) {
  77590. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  77591. return new (P || (P = Promise))(function (resolve, reject) {
  77592. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  77593. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  77594. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  77595. step((generator = generator.apply(thisArg, _arguments || [])).next());
  77596. });
  77597. }
  77598. function assert$7(condition, message) {
  77599. if (!condition) {
  77600. throw new Error(message || 'loader assertion failed.');
  77601. }
  77602. }
  77603. const isBrowser$2 = Boolean(typeof process !== 'object' || String(process) !== '[object process]' || process.browser);
  77604. const matches$1 = typeof process !== 'undefined' && process.version && /v([0-9]*)/.exec(process.version);
  77605. matches$1 && parseFloat(matches$1[1]) || 0;
  77606. const VERSION$8 = "3.1.4" ;
  77607. function assert$6(condition, message) {
  77608. if (!condition) {
  77609. throw new Error(message || 'loaders.gl assertion failed.');
  77610. }
  77611. }
  77612. const globals$1 = {
  77613. self: typeof self !== 'undefined' && self,
  77614. window: typeof window !== 'undefined' && window,
  77615. global: typeof global !== 'undefined' && global,
  77616. document: typeof document !== 'undefined' && document
  77617. };
  77618. const global_ = globals$1.global || globals$1.self || globals$1.window || {};
  77619. const isBrowser$1 = typeof process !== 'object' || String(process) !== '[object process]' || process.browser;
  77620. const isWorker = typeof importScripts === 'function';
  77621. const isMobile = typeof window !== 'undefined' && typeof window.orientation !== 'undefined';
  77622. const matches = typeof process !== 'undefined' && process.version && /v([0-9]*)/.exec(process.version);
  77623. matches && parseFloat(matches[1]) || 0;
  77624. function _defineProperty(obj, key, value) {
  77625. if (key in obj) {
  77626. Object.defineProperty(obj, key, {
  77627. value: value,
  77628. enumerable: true,
  77629. configurable: true,
  77630. writable: true
  77631. });
  77632. } else {
  77633. obj[key] = value;
  77634. }
  77635. return obj;
  77636. }
  77637. class WorkerJob {
  77638. constructor(jobName, workerThread) {
  77639. _defineProperty(this, "name", void 0);
  77640. _defineProperty(this, "workerThread", void 0);
  77641. _defineProperty(this, "isRunning", void 0);
  77642. _defineProperty(this, "result", void 0);
  77643. _defineProperty(this, "_resolve", void 0);
  77644. _defineProperty(this, "_reject", void 0);
  77645. this.name = jobName;
  77646. this.workerThread = workerThread;
  77647. this.isRunning = true;
  77648. this._resolve = () => {};
  77649. this._reject = () => {};
  77650. this.result = new Promise((resolve, reject) => {
  77651. this._resolve = resolve;
  77652. this._reject = reject;
  77653. });
  77654. }
  77655. postMessage(type, payload) {
  77656. this.workerThread.postMessage({
  77657. source: 'loaders.gl',
  77658. type,
  77659. payload
  77660. });
  77661. }
  77662. done(value) {
  77663. assert$6(this.isRunning);
  77664. this.isRunning = false;
  77665. this._resolve(value);
  77666. }
  77667. error(error) {
  77668. assert$6(this.isRunning);
  77669. this.isRunning = false;
  77670. this._reject(error);
  77671. }
  77672. }
  77673. const workerURLCache = new Map();
  77674. function getLoadableWorkerURL(props) {
  77675. assert$6(props.source && !props.url || !props.source && props.url);
  77676. let workerURL = workerURLCache.get(props.source || props.url);
  77677. if (!workerURL) {
  77678. if (props.url) {
  77679. workerURL = getLoadableWorkerURLFromURL(props.url);
  77680. workerURLCache.set(props.url, workerURL);
  77681. }
  77682. if (props.source) {
  77683. workerURL = getLoadableWorkerURLFromSource(props.source);
  77684. workerURLCache.set(props.source, workerURL);
  77685. }
  77686. }
  77687. assert$6(workerURL);
  77688. return workerURL;
  77689. }
  77690. function getLoadableWorkerURLFromURL(url) {
  77691. if (!url.startsWith('http')) {
  77692. return url;
  77693. }
  77694. const workerSource = buildScriptSource(url);
  77695. return getLoadableWorkerURLFromSource(workerSource);
  77696. }
  77697. function getLoadableWorkerURLFromSource(workerSource) {
  77698. const blob = new Blob([workerSource], {
  77699. type: 'application/javascript'
  77700. });
  77701. return URL.createObjectURL(blob);
  77702. }
  77703. function buildScriptSource(workerUrl) {
  77704. return "try {\n importScripts('".concat(workerUrl, "');\n} catch (error) {\n console.error(error);\n throw error;\n}");
  77705. }
  77706. function getTransferList(object, recursive = true, transfers) {
  77707. const transfersSet = transfers || new Set();
  77708. if (!object) ; else if (isTransferable(object)) {
  77709. transfersSet.add(object);
  77710. } else if (isTransferable(object.buffer)) {
  77711. transfersSet.add(object.buffer);
  77712. } else if (ArrayBuffer.isView(object)) ; else if (recursive && typeof object === 'object') {
  77713. for (const key in object) {
  77714. getTransferList(object[key], recursive, transfersSet);
  77715. }
  77716. }
  77717. return transfers === undefined ? Array.from(transfersSet) : [];
  77718. }
  77719. function isTransferable(object) {
  77720. if (!object) {
  77721. return false;
  77722. }
  77723. if (object instanceof ArrayBuffer) {
  77724. return true;
  77725. }
  77726. if (typeof MessagePort !== 'undefined' && object instanceof MessagePort) {
  77727. return true;
  77728. }
  77729. if (typeof ImageBitmap !== 'undefined' && object instanceof ImageBitmap) {
  77730. return true;
  77731. }
  77732. if (typeof OffscreenCanvas !== 'undefined' && object instanceof OffscreenCanvas) {
  77733. return true;
  77734. }
  77735. return false;
  77736. }
  77737. const NOOP = () => {};
  77738. class WorkerThread {
  77739. static isSupported() {
  77740. return typeof Worker !== 'undefined';
  77741. }
  77742. constructor(props) {
  77743. _defineProperty(this, "name", void 0);
  77744. _defineProperty(this, "source", void 0);
  77745. _defineProperty(this, "url", void 0);
  77746. _defineProperty(this, "terminated", false);
  77747. _defineProperty(this, "worker", void 0);
  77748. _defineProperty(this, "onMessage", void 0);
  77749. _defineProperty(this, "onError", void 0);
  77750. _defineProperty(this, "_loadableURL", '');
  77751. const {
  77752. name,
  77753. source,
  77754. url
  77755. } = props;
  77756. assert$6(source || url);
  77757. this.name = name;
  77758. this.source = source;
  77759. this.url = url;
  77760. this.onMessage = NOOP;
  77761. this.onError = error => console.log(error);
  77762. this.worker = this._createBrowserWorker();
  77763. }
  77764. destroy() {
  77765. this.onMessage = NOOP;
  77766. this.onError = NOOP;
  77767. this.worker.terminate();
  77768. this.terminated = true;
  77769. }
  77770. get isRunning() {
  77771. return Boolean(this.onMessage);
  77772. }
  77773. postMessage(data, transferList) {
  77774. transferList = transferList || getTransferList(data);
  77775. this.worker.postMessage(data, transferList);
  77776. }
  77777. _getErrorFromErrorEvent(event) {
  77778. let message = 'Failed to load ';
  77779. message += "worker ".concat(this.name, " from ").concat(this.url, ". ");
  77780. if (event.message) {
  77781. message += "".concat(event.message, " in ");
  77782. }
  77783. if (event.lineno) {
  77784. message += ":".concat(event.lineno, ":").concat(event.colno);
  77785. }
  77786. return new Error(message);
  77787. }
  77788. _createBrowserWorker() {
  77789. this._loadableURL = getLoadableWorkerURL({
  77790. source: this.source,
  77791. url: this.url
  77792. });
  77793. const worker = new Worker(this._loadableURL, {
  77794. name: this.name
  77795. });
  77796. worker.onmessage = event => {
  77797. if (!event.data) {
  77798. this.onError(new Error('No data received'));
  77799. } else {
  77800. this.onMessage(event.data);
  77801. }
  77802. };
  77803. worker.onerror = error => {
  77804. this.onError(this._getErrorFromErrorEvent(error));
  77805. this.terminated = true;
  77806. };
  77807. worker.onmessageerror = event => console.error(event);
  77808. return worker;
  77809. }
  77810. }
  77811. class WorkerPool$2 {
  77812. constructor(props) {
  77813. _defineProperty(this, "name", 'unnamed');
  77814. _defineProperty(this, "source", void 0);
  77815. _defineProperty(this, "url", void 0);
  77816. _defineProperty(this, "maxConcurrency", 1);
  77817. _defineProperty(this, "maxMobileConcurrency", 1);
  77818. _defineProperty(this, "onDebug", () => {});
  77819. _defineProperty(this, "reuseWorkers", true);
  77820. _defineProperty(this, "props", {});
  77821. _defineProperty(this, "jobQueue", []);
  77822. _defineProperty(this, "idleQueue", []);
  77823. _defineProperty(this, "count", 0);
  77824. _defineProperty(this, "isDestroyed", false);
  77825. this.source = props.source;
  77826. this.url = props.url;
  77827. this.setProps(props);
  77828. }
  77829. destroy() {
  77830. this.idleQueue.forEach(worker => worker.destroy());
  77831. this.isDestroyed = true;
  77832. }
  77833. setProps(props) {
  77834. this.props = { ...this.props,
  77835. ...props
  77836. };
  77837. if (props.name !== undefined) {
  77838. this.name = props.name;
  77839. }
  77840. if (props.maxConcurrency !== undefined) {
  77841. this.maxConcurrency = props.maxConcurrency;
  77842. }
  77843. if (props.maxMobileConcurrency !== undefined) {
  77844. this.maxMobileConcurrency = props.maxMobileConcurrency;
  77845. }
  77846. if (props.reuseWorkers !== undefined) {
  77847. this.reuseWorkers = props.reuseWorkers;
  77848. }
  77849. if (props.onDebug !== undefined) {
  77850. this.onDebug = props.onDebug;
  77851. }
  77852. }
  77853. async startJob(name, onMessage = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
  77854. const startPromise = new Promise(onStart => {
  77855. this.jobQueue.push({
  77856. name,
  77857. onMessage,
  77858. onError,
  77859. onStart
  77860. });
  77861. return this;
  77862. });
  77863. this._startQueuedJob();
  77864. return await startPromise;
  77865. }
  77866. async _startQueuedJob() {
  77867. if (!this.jobQueue.length) {
  77868. return;
  77869. }
  77870. const workerThread = this._getAvailableWorker();
  77871. if (!workerThread) {
  77872. return;
  77873. }
  77874. const queuedJob = this.jobQueue.shift();
  77875. if (queuedJob) {
  77876. this.onDebug({
  77877. message: 'Starting job',
  77878. name: queuedJob.name,
  77879. workerThread,
  77880. backlog: this.jobQueue.length
  77881. });
  77882. const job = new WorkerJob(queuedJob.name, workerThread);
  77883. workerThread.onMessage = data => queuedJob.onMessage(job, data.type, data.payload);
  77884. workerThread.onError = error => queuedJob.onError(job, error);
  77885. queuedJob.onStart(job);
  77886. try {
  77887. await job.result;
  77888. } finally {
  77889. this.returnWorkerToQueue(workerThread);
  77890. }
  77891. }
  77892. }
  77893. returnWorkerToQueue(worker) {
  77894. const shouldDestroyWorker = this.isDestroyed || !this.reuseWorkers || this.count > this._getMaxConcurrency();
  77895. if (shouldDestroyWorker) {
  77896. worker.destroy();
  77897. this.count--;
  77898. } else {
  77899. this.idleQueue.push(worker);
  77900. }
  77901. if (!this.isDestroyed) {
  77902. this._startQueuedJob();
  77903. }
  77904. }
  77905. _getAvailableWorker() {
  77906. if (this.idleQueue.length > 0) {
  77907. return this.idleQueue.shift() || null;
  77908. }
  77909. if (this.count < this._getMaxConcurrency()) {
  77910. this.count++;
  77911. const name = "".concat(this.name.toLowerCase(), " (#").concat(this.count, " of ").concat(this.maxConcurrency, ")");
  77912. return new WorkerThread({
  77913. name,
  77914. source: this.source,
  77915. url: this.url
  77916. });
  77917. }
  77918. return null;
  77919. }
  77920. _getMaxConcurrency() {
  77921. return isMobile ? this.maxMobileConcurrency : this.maxConcurrency;
  77922. }
  77923. }
  77924. const DEFAULT_PROPS$3 = {
  77925. maxConcurrency: 3,
  77926. maxMobileConcurrency: 1,
  77927. onDebug: () => {},
  77928. reuseWorkers: true
  77929. };
  77930. class WorkerFarm {
  77931. static isSupported() {
  77932. return WorkerThread.isSupported();
  77933. }
  77934. static getWorkerFarm(props = {}) {
  77935. WorkerFarm._workerFarm = WorkerFarm._workerFarm || new WorkerFarm({});
  77936. WorkerFarm._workerFarm.setProps(props);
  77937. return WorkerFarm._workerFarm;
  77938. }
  77939. constructor(props) {
  77940. _defineProperty(this, "props", void 0);
  77941. _defineProperty(this, "workerPools", new Map());
  77942. this.props = { ...DEFAULT_PROPS$3
  77943. };
  77944. this.setProps(props);
  77945. this.workerPools = new Map();
  77946. }
  77947. destroy() {
  77948. for (const workerPool of this.workerPools.values()) {
  77949. workerPool.destroy();
  77950. }
  77951. }
  77952. setProps(props) {
  77953. this.props = { ...this.props,
  77954. ...props
  77955. };
  77956. for (const workerPool of this.workerPools.values()) {
  77957. workerPool.setProps(this._getWorkerPoolProps());
  77958. }
  77959. }
  77960. getWorkerPool(options) {
  77961. const {
  77962. name,
  77963. source,
  77964. url
  77965. } = options;
  77966. let workerPool = this.workerPools.get(name);
  77967. if (!workerPool) {
  77968. workerPool = new WorkerPool$2({
  77969. name,
  77970. source,
  77971. url
  77972. });
  77973. workerPool.setProps(this._getWorkerPoolProps());
  77974. this.workerPools.set(name, workerPool);
  77975. }
  77976. return workerPool;
  77977. }
  77978. _getWorkerPoolProps() {
  77979. return {
  77980. maxConcurrency: this.props.maxConcurrency,
  77981. maxMobileConcurrency: this.props.maxMobileConcurrency,
  77982. reuseWorkers: this.props.reuseWorkers,
  77983. onDebug: this.props.onDebug
  77984. };
  77985. }
  77986. }
  77987. _defineProperty(WorkerFarm, "_workerFarm", void 0);
  77988. const NPM_TAG = 'latest';
  77989. function getWorkerURL(worker, options = {}) {
  77990. const workerOptions = options[worker.id] || {};
  77991. const workerFile = "".concat(worker.id, "-worker.js");
  77992. let url = workerOptions.workerUrl;
  77993. if (!url && worker.id === 'compression') {
  77994. url = options.workerUrl;
  77995. }
  77996. if (options._workerType === 'test') {
  77997. url = "modules/".concat(worker.module, "/dist/").concat(workerFile);
  77998. }
  77999. if (!url) {
  78000. let version = worker.version;
  78001. if (version === 'latest') {
  78002. version = NPM_TAG;
  78003. }
  78004. const versionTag = version ? "@".concat(version) : '';
  78005. url = "https://unpkg.com/@loaders.gl/".concat(worker.module).concat(versionTag, "/dist/").concat(workerFile);
  78006. }
  78007. assert$6(url);
  78008. return url;
  78009. }
  78010. function validateWorkerVersion(worker, coreVersion = VERSION$8) {
  78011. assert$6(worker, 'no worker provided');
  78012. const workerVersion = worker.version;
  78013. if (!coreVersion || !workerVersion) {
  78014. return false;
  78015. }
  78016. return true;
  78017. }
  78018. var ChildProcessProxy = {};
  78019. var node = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), ChildProcessProxy, {
  78020. 'default': ChildProcessProxy
  78021. }));
  78022. const VERSION$7 = "3.1.4" ;
  78023. const loadLibraryPromises = {};
  78024. async function loadLibrary(libraryUrl, moduleName = null, options = {}) {
  78025. if (moduleName) {
  78026. libraryUrl = getLibraryUrl(libraryUrl, moduleName, options);
  78027. }
  78028. loadLibraryPromises[libraryUrl] = loadLibraryPromises[libraryUrl] || loadLibraryFromFile(libraryUrl);
  78029. return await loadLibraryPromises[libraryUrl];
  78030. }
  78031. function getLibraryUrl(library, moduleName, options) {
  78032. if (library.startsWith('http')) {
  78033. return library;
  78034. }
  78035. const modules = options.modules || {};
  78036. if (modules[library]) {
  78037. return modules[library];
  78038. }
  78039. if (!isBrowser$1) {
  78040. return "modules/".concat(moduleName, "/dist/libs/").concat(library);
  78041. }
  78042. if (options.CDN) {
  78043. assert$6(options.CDN.startsWith('http'));
  78044. return "".concat(options.CDN, "/").concat(moduleName, "@").concat(VERSION$7, "/dist/libs/").concat(library);
  78045. }
  78046. if (isWorker) {
  78047. return "../src/libs/".concat(library);
  78048. }
  78049. return "modules/".concat(moduleName, "/src/libs/").concat(library);
  78050. }
  78051. async function loadLibraryFromFile(libraryUrl) {
  78052. if (libraryUrl.endsWith('wasm')) {
  78053. const response = await fetch(libraryUrl);
  78054. return await response.arrayBuffer();
  78055. }
  78056. if (!isBrowser$1) {
  78057. try {
  78058. return node && ChildProcessProxy.requireFromFile && (await ChildProcessProxy.requireFromFile(libraryUrl));
  78059. } catch {
  78060. return null;
  78061. }
  78062. }
  78063. if (isWorker) {
  78064. return importScripts(libraryUrl);
  78065. }
  78066. const response = await fetch(libraryUrl);
  78067. const scriptSource = await response.text();
  78068. return loadLibraryFromString(scriptSource, libraryUrl);
  78069. }
  78070. function loadLibraryFromString(scriptSource, id) {
  78071. if (!isBrowser$1) {
  78072. return ChildProcessProxy.requireFromString && ChildProcessProxy.requireFromString(scriptSource, id);
  78073. }
  78074. if (isWorker) {
  78075. eval.call(global_, scriptSource);
  78076. return null;
  78077. }
  78078. const script = document.createElement('script');
  78079. script.id = id;
  78080. try {
  78081. script.appendChild(document.createTextNode(scriptSource));
  78082. } catch (e) {
  78083. script.text = scriptSource;
  78084. }
  78085. document.body.appendChild(script);
  78086. return null;
  78087. }
  78088. function canParseWithWorker(loader, options) {
  78089. if (!WorkerFarm.isSupported()) {
  78090. return false;
  78091. }
  78092. return loader.worker && (options === null || options === void 0 ? void 0 : options.worker);
  78093. }
  78094. async function parseWithWorker(loader, data, options, context, parseOnMainThread) {
  78095. const name = loader.id;
  78096. const url = getWorkerURL(loader, options);
  78097. const workerFarm = WorkerFarm.getWorkerFarm(options);
  78098. const workerPool = workerFarm.getWorkerPool({
  78099. name,
  78100. url
  78101. });
  78102. options = JSON.parse(JSON.stringify(options));
  78103. const job = await workerPool.startJob('process-on-worker', onMessage.bind(null, parseOnMainThread));
  78104. job.postMessage('process', {
  78105. input: data,
  78106. options
  78107. });
  78108. const result = await job.result;
  78109. return await result.result;
  78110. }
  78111. async function onMessage(parseOnMainThread, job, type, payload) {
  78112. switch (type) {
  78113. case 'done':
  78114. job.done(payload);
  78115. break;
  78116. case 'error':
  78117. job.error(new Error(payload.error));
  78118. break;
  78119. case 'process':
  78120. const {
  78121. id,
  78122. input,
  78123. options
  78124. } = payload;
  78125. try {
  78126. const result = await parseOnMainThread(input, options);
  78127. job.postMessage('done', {
  78128. id,
  78129. result
  78130. });
  78131. } catch (error) {
  78132. const message = error instanceof Error ? error.message : 'unknown error';
  78133. job.postMessage('error', {
  78134. id,
  78135. error: message
  78136. });
  78137. }
  78138. break;
  78139. default:
  78140. console.warn("parse-with-worker unknown message ".concat(type));
  78141. }
  78142. }
  78143. function getFirstCharacters$1(data, length = 5) {
  78144. if (typeof data === 'string') {
  78145. return data.slice(0, length);
  78146. } else if (ArrayBuffer.isView(data)) {
  78147. return getMagicString$3(data.buffer, data.byteOffset, length);
  78148. } else if (data instanceof ArrayBuffer) {
  78149. const byteOffset = 0;
  78150. return getMagicString$3(data, byteOffset, length);
  78151. }
  78152. return '';
  78153. }
  78154. function getMagicString$3(arrayBuffer, byteOffset, length) {
  78155. if (arrayBuffer.byteLength <= byteOffset + length) {
  78156. return '';
  78157. }
  78158. const dataView = new DataView(arrayBuffer);
  78159. let magic = '';
  78160. for (let i = 0; i < length; i++) {
  78161. magic += String.fromCharCode(dataView.getUint8(byteOffset + i));
  78162. }
  78163. return magic;
  78164. }
  78165. function parseJSON(string) {
  78166. try {
  78167. return JSON.parse(string);
  78168. } catch (_) {
  78169. throw new Error("Failed to parse JSON from data starting with \"".concat(getFirstCharacters$1(string), "\""));
  78170. }
  78171. }
  78172. function isBuffer$1(value) {
  78173. return value && typeof value === 'object' && value.isBuffer;
  78174. }
  78175. function bufferToArrayBuffer(buffer) {
  78176. if (isBuffer$1(buffer)) {
  78177. const typedArray = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.length);
  78178. return typedArray.slice().buffer;
  78179. }
  78180. return buffer;
  78181. }
  78182. function toArrayBuffer(data) {
  78183. if (isBuffer$1(data)) {
  78184. return bufferToArrayBuffer(data);
  78185. }
  78186. if (data instanceof ArrayBuffer) {
  78187. return data;
  78188. }
  78189. if (ArrayBuffer.isView(data)) {
  78190. if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
  78191. return data.buffer;
  78192. }
  78193. return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
  78194. }
  78195. if (typeof data === 'string') {
  78196. const text = data;
  78197. const uint8Array = new TextEncoder().encode(text);
  78198. return uint8Array.buffer;
  78199. }
  78200. if (data && typeof data === 'object' && data._toArrayBuffer) {
  78201. return data._toArrayBuffer();
  78202. }
  78203. throw new Error('toArrayBuffer');
  78204. }
  78205. function compareArrayBuffers(arrayBuffer1, arrayBuffer2, byteLength) {
  78206. byteLength = byteLength || arrayBuffer1.byteLength;
  78207. if (arrayBuffer1.byteLength < byteLength || arrayBuffer2.byteLength < byteLength) {
  78208. return false;
  78209. }
  78210. const array1 = new Uint8Array(arrayBuffer1);
  78211. const array2 = new Uint8Array(arrayBuffer2);
  78212. for (let i = 0; i < array1.length; ++i) {
  78213. if (array1[i] !== array2[i]) {
  78214. return false;
  78215. }
  78216. }
  78217. return true;
  78218. }
  78219. function concatenateArrayBuffers(...sources) {
  78220. const sourceArrays = sources.map(source2 => source2 instanceof ArrayBuffer ? new Uint8Array(source2) : source2);
  78221. const byteLength = sourceArrays.reduce((length, typedArray) => length + typedArray.byteLength, 0);
  78222. const result = new Uint8Array(byteLength);
  78223. let offset = 0;
  78224. for (const sourceArray of sourceArrays) {
  78225. result.set(sourceArray, offset);
  78226. offset += sourceArray.byteLength;
  78227. }
  78228. return result.buffer;
  78229. }
  78230. function sliceArrayBuffer(arrayBuffer, byteOffset, byteLength) {
  78231. const subArray = byteLength !== undefined ? new Uint8Array(arrayBuffer).subarray(byteOffset, byteOffset + byteLength) : new Uint8Array(arrayBuffer).subarray(byteOffset);
  78232. const arrayCopy = new Uint8Array(subArray);
  78233. return arrayCopy.buffer;
  78234. }
  78235. function padToNBytes(byteLength, padding) {
  78236. assert$7(byteLength >= 0);
  78237. assert$7(padding > 0);
  78238. return byteLength + (padding - 1) & ~(padding - 1);
  78239. }
  78240. function copyToArray(source, target, targetOffset) {
  78241. let sourceArray;
  78242. if (source instanceof ArrayBuffer) {
  78243. sourceArray = new Uint8Array(source);
  78244. } else {
  78245. const srcByteOffset = source.byteOffset;
  78246. const srcByteLength = source.byteLength;
  78247. sourceArray = new Uint8Array(source.buffer || source.arrayBuffer, srcByteOffset, srcByteLength);
  78248. }
  78249. target.set(sourceArray, targetOffset);
  78250. return targetOffset + padToNBytes(sourceArray.byteLength, 4);
  78251. }
  78252. async function concatenateArrayBuffersAsync(asyncIterator) {
  78253. const arrayBuffers = [];
  78254. for await (const chunk of asyncIterator) {
  78255. arrayBuffers.push(chunk);
  78256. }
  78257. return concatenateArrayBuffers(...arrayBuffers);
  78258. }
  78259. function getHiResTimestamp$1() {
  78260. let timestamp;
  78261. if (typeof window !== 'undefined' && window.performance) {
  78262. timestamp = window.performance.now();
  78263. } else if (typeof process !== 'undefined' && process.hrtime) {
  78264. const timeParts = process.hrtime();
  78265. timestamp = timeParts[0] * 1000 + timeParts[1] / 1e6;
  78266. } else {
  78267. timestamp = Date.now();
  78268. }
  78269. return timestamp;
  78270. }
  78271. class Stat {
  78272. constructor(name, type) {
  78273. _defineProperty(this, "name", void 0);
  78274. _defineProperty(this, "type", void 0);
  78275. _defineProperty(this, "sampleSize", 1);
  78276. _defineProperty(this, "time", void 0);
  78277. _defineProperty(this, "count", void 0);
  78278. _defineProperty(this, "samples", void 0);
  78279. _defineProperty(this, "lastTiming", void 0);
  78280. _defineProperty(this, "lastSampleTime", void 0);
  78281. _defineProperty(this, "lastSampleCount", void 0);
  78282. _defineProperty(this, "_count", 0);
  78283. _defineProperty(this, "_time", 0);
  78284. _defineProperty(this, "_samples", 0);
  78285. _defineProperty(this, "_startTime", 0);
  78286. _defineProperty(this, "_timerPending", false);
  78287. this.name = name;
  78288. this.type = type;
  78289. this.reset();
  78290. }
  78291. setSampleSize(samples) {
  78292. this.sampleSize = samples;
  78293. return this;
  78294. }
  78295. incrementCount() {
  78296. this.addCount(1);
  78297. return this;
  78298. }
  78299. decrementCount() {
  78300. this.subtractCount(1);
  78301. return this;
  78302. }
  78303. addCount(value) {
  78304. this._count += value;
  78305. this._samples++;
  78306. this._checkSampling();
  78307. return this;
  78308. }
  78309. subtractCount(value) {
  78310. this._count -= value;
  78311. this._samples++;
  78312. this._checkSampling();
  78313. return this;
  78314. }
  78315. addTime(time) {
  78316. this._time += time;
  78317. this.lastTiming = time;
  78318. this._samples++;
  78319. this._checkSampling();
  78320. return this;
  78321. }
  78322. timeStart() {
  78323. this._startTime = getHiResTimestamp$1();
  78324. this._timerPending = true;
  78325. return this;
  78326. }
  78327. timeEnd() {
  78328. if (!this._timerPending) {
  78329. return this;
  78330. }
  78331. this.addTime(getHiResTimestamp$1() - this._startTime);
  78332. this._timerPending = false;
  78333. this._checkSampling();
  78334. return this;
  78335. }
  78336. getSampleAverageCount() {
  78337. return this.sampleSize > 0 ? this.lastSampleCount / this.sampleSize : 0;
  78338. }
  78339. getSampleAverageTime() {
  78340. return this.sampleSize > 0 ? this.lastSampleTime / this.sampleSize : 0;
  78341. }
  78342. getSampleHz() {
  78343. return this.lastSampleTime > 0 ? this.sampleSize / (this.lastSampleTime / 1000) : 0;
  78344. }
  78345. getAverageCount() {
  78346. return this.samples > 0 ? this.count / this.samples : 0;
  78347. }
  78348. getAverageTime() {
  78349. return this.samples > 0 ? this.time / this.samples : 0;
  78350. }
  78351. getHz() {
  78352. return this.time > 0 ? this.samples / (this.time / 1000) : 0;
  78353. }
  78354. reset() {
  78355. this.time = 0;
  78356. this.count = 0;
  78357. this.samples = 0;
  78358. this.lastTiming = 0;
  78359. this.lastSampleTime = 0;
  78360. this.lastSampleCount = 0;
  78361. this._count = 0;
  78362. this._time = 0;
  78363. this._samples = 0;
  78364. this._startTime = 0;
  78365. this._timerPending = false;
  78366. return this;
  78367. }
  78368. _checkSampling() {
  78369. if (this._samples === this.sampleSize) {
  78370. this.lastSampleTime = this._time;
  78371. this.lastSampleCount = this._count;
  78372. this.count += this._count;
  78373. this.time += this._time;
  78374. this.samples += this._samples;
  78375. this._time = 0;
  78376. this._count = 0;
  78377. this._samples = 0;
  78378. }
  78379. }
  78380. }
  78381. class Stats$1 {
  78382. constructor(options) {
  78383. _defineProperty(this, "id", void 0);
  78384. _defineProperty(this, "stats", {});
  78385. this.id = options.id;
  78386. this.stats = {};
  78387. this._initializeStats(options.stats);
  78388. Object.seal(this);
  78389. }
  78390. get(name) {
  78391. let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'count';
  78392. return this._getOrCreate({
  78393. name,
  78394. type
  78395. });
  78396. }
  78397. get size() {
  78398. return Object.keys(this.stats).length;
  78399. }
  78400. reset() {
  78401. for (const key in this.stats) {
  78402. this.stats[key].reset();
  78403. }
  78404. return this;
  78405. }
  78406. forEach(fn) {
  78407. for (const key in this.stats) {
  78408. fn(this.stats[key]);
  78409. }
  78410. }
  78411. getTable() {
  78412. const table = {};
  78413. this.forEach(stat => {
  78414. table[stat.name] = {
  78415. time: stat.time || 0,
  78416. count: stat.count || 0,
  78417. average: stat.getAverageTime() || 0,
  78418. hz: stat.getHz() || 0
  78419. };
  78420. });
  78421. return table;
  78422. }
  78423. _initializeStats() {
  78424. let stats = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  78425. stats.forEach(stat => this._getOrCreate(stat));
  78426. }
  78427. _getOrCreate(stat) {
  78428. if (!stat || !stat.name) {
  78429. return null;
  78430. }
  78431. const {
  78432. name,
  78433. type
  78434. } = stat;
  78435. if (!this.stats[name]) {
  78436. if (stat instanceof Stat) {
  78437. this.stats[name] = stat;
  78438. } else {
  78439. this.stats[name] = new Stat(name, type);
  78440. }
  78441. }
  78442. return this.stats[name];
  78443. }
  78444. }
  78445. const STAT_QUEUED_REQUESTS = 'Queued Requests';
  78446. const STAT_ACTIVE_REQUESTS = 'Active Requests';
  78447. const STAT_CANCELLED_REQUESTS = 'Cancelled Requests';
  78448. const STAT_QUEUED_REQUESTS_EVER = 'Queued Requests Ever';
  78449. const STAT_ACTIVE_REQUESTS_EVER = 'Active Requests Ever';
  78450. const DEFAULT_PROPS$2 = {
  78451. id: 'request-scheduler',
  78452. throttleRequests: true,
  78453. maxRequests: 6
  78454. };
  78455. class RequestScheduler {
  78456. constructor(props = {}) {
  78457. _defineProperty(this, "props", void 0);
  78458. _defineProperty(this, "stats", void 0);
  78459. _defineProperty(this, "activeRequestCount", 0);
  78460. _defineProperty(this, "requestQueue", []);
  78461. _defineProperty(this, "requestMap", new Map());
  78462. _defineProperty(this, "deferredUpdate", null);
  78463. this.props = { ...DEFAULT_PROPS$2,
  78464. ...props
  78465. };
  78466. this.stats = new Stats$1({
  78467. id: this.props.id
  78468. });
  78469. this.stats.get(STAT_QUEUED_REQUESTS);
  78470. this.stats.get(STAT_ACTIVE_REQUESTS);
  78471. this.stats.get(STAT_CANCELLED_REQUESTS);
  78472. this.stats.get(STAT_QUEUED_REQUESTS_EVER);
  78473. this.stats.get(STAT_ACTIVE_REQUESTS_EVER);
  78474. }
  78475. scheduleRequest(handle, getPriority = () => 0) {
  78476. if (!this.props.throttleRequests) {
  78477. return Promise.resolve({
  78478. done: () => {}
  78479. });
  78480. }
  78481. if (this.requestMap.has(handle)) {
  78482. return this.requestMap.get(handle);
  78483. }
  78484. const request = {
  78485. handle,
  78486. priority: 0,
  78487. getPriority
  78488. };
  78489. const promise = new Promise(resolve => {
  78490. request.resolve = resolve;
  78491. return request;
  78492. });
  78493. this.requestQueue.push(request);
  78494. this.requestMap.set(handle, promise);
  78495. this._issueNewRequests();
  78496. return promise;
  78497. }
  78498. _issueRequest(request) {
  78499. const {
  78500. handle,
  78501. resolve
  78502. } = request;
  78503. let isDone = false;
  78504. const done = () => {
  78505. if (!isDone) {
  78506. isDone = true;
  78507. this.requestMap.delete(handle);
  78508. this.activeRequestCount--;
  78509. this._issueNewRequests();
  78510. }
  78511. };
  78512. this.activeRequestCount++;
  78513. return resolve ? resolve({
  78514. done
  78515. }) : Promise.resolve({
  78516. done
  78517. });
  78518. }
  78519. _issueNewRequests() {
  78520. if (!this.deferredUpdate) {
  78521. this.deferredUpdate = setTimeout(() => this._issueNewRequestsAsync(), 0);
  78522. }
  78523. }
  78524. _issueNewRequestsAsync() {
  78525. this.deferredUpdate = null;
  78526. const freeSlots = Math.max(this.props.maxRequests - this.activeRequestCount, 0);
  78527. if (freeSlots === 0) {
  78528. return;
  78529. }
  78530. this._updateAllRequests();
  78531. for (let i = 0; i < freeSlots; ++i) {
  78532. const request = this.requestQueue.shift();
  78533. if (request) {
  78534. this._issueRequest(request);
  78535. }
  78536. }
  78537. }
  78538. _updateAllRequests() {
  78539. const requestQueue = this.requestQueue;
  78540. for (let i = 0; i < requestQueue.length; ++i) {
  78541. const request = requestQueue[i];
  78542. if (!this._updateRequest(request)) {
  78543. requestQueue.splice(i, 1);
  78544. this.requestMap.delete(request.handle);
  78545. i--;
  78546. }
  78547. }
  78548. requestQueue.sort((a, b) => a.priority - b.priority);
  78549. }
  78550. _updateRequest(request) {
  78551. request.priority = request.getPriority(request.handle);
  78552. if (request.priority < 0) {
  78553. request.resolve(null);
  78554. return false;
  78555. }
  78556. return true;
  78557. }
  78558. }
  78559. let pathPrefix = '';
  78560. const fileAliases = {};
  78561. function resolvePath(filename) {
  78562. for (const alias in fileAliases) {
  78563. if (filename.startsWith(alias)) {
  78564. const replacement = fileAliases[alias];
  78565. filename = filename.replace(alias, replacement);
  78566. }
  78567. }
  78568. if (!filename.startsWith('http://') && !filename.startsWith('https://')) {
  78569. filename = "".concat(pathPrefix).concat(filename);
  78570. }
  78571. return filename;
  78572. }
  78573. function filename(url) {
  78574. const slashIndex = url && url.lastIndexOf('/');
  78575. return slashIndex >= 0 ? url.substr(slashIndex + 1) : '';
  78576. }
  78577. function dirname(url) {
  78578. const slashIndex = url && url.lastIndexOf('/');
  78579. return slashIndex >= 0 ? url.substr(0, slashIndex) : '';
  78580. }
  78581. const isBoolean = x => typeof x === 'boolean';
  78582. const isFunction = x => typeof x === 'function';
  78583. const isObject = x => x !== null && typeof x === 'object';
  78584. const isPureObject = x => isObject(x) && x.constructor === {}.constructor;
  78585. const isIterable = x => x && typeof x[Symbol.iterator] === 'function';
  78586. const isAsyncIterable = x => x && typeof x[Symbol.asyncIterator] === 'function';
  78587. const isResponse = x => typeof Response !== 'undefined' && x instanceof Response || x && x.arrayBuffer && x.text && x.json;
  78588. const isBlob = x => typeof Blob !== 'undefined' && x instanceof Blob;
  78589. const isBuffer = x => x && typeof x === 'object' && x.isBuffer;
  78590. const isReadableDOMStream = x => typeof ReadableStream !== 'undefined' && x instanceof ReadableStream || isObject(x) && isFunction(x.tee) && isFunction(x.cancel) && isFunction(x.getReader);
  78591. const isReadableNodeStream = x => isObject(x) && isFunction(x.read) && isFunction(x.pipe) && isBoolean(x.readable);
  78592. const isReadableStream = x => isReadableDOMStream(x) || isReadableNodeStream(x);
  78593. const DATA_URL_PATTERN = /^data:([-\w.]+\/[-\w.+]+)(;|,)/;
  78594. const MIME_TYPE_PATTERN = /^([-\w.]+\/[-\w.+]+)/;
  78595. function parseMIMEType(mimeString) {
  78596. const matches = MIME_TYPE_PATTERN.exec(mimeString);
  78597. if (matches) {
  78598. return matches[1];
  78599. }
  78600. return mimeString;
  78601. }
  78602. function parseMIMETypeFromURL(url) {
  78603. const matches = DATA_URL_PATTERN.exec(url);
  78604. if (matches) {
  78605. return matches[1];
  78606. }
  78607. return '';
  78608. }
  78609. const QUERY_STRING_PATTERN = /\?.*/;
  78610. function getResourceUrlAndType(resource) {
  78611. if (isResponse(resource)) {
  78612. const url = stripQueryString(resource.url || '');
  78613. const contentTypeHeader = resource.headers.get('content-type') || '';
  78614. return {
  78615. url,
  78616. type: parseMIMEType(contentTypeHeader) || parseMIMETypeFromURL(url)
  78617. };
  78618. }
  78619. if (isBlob(resource)) {
  78620. return {
  78621. url: stripQueryString(resource.name || ''),
  78622. type: resource.type || ''
  78623. };
  78624. }
  78625. if (typeof resource === 'string') {
  78626. return {
  78627. url: stripQueryString(resource),
  78628. type: parseMIMETypeFromURL(resource)
  78629. };
  78630. }
  78631. return {
  78632. url: '',
  78633. type: ''
  78634. };
  78635. }
  78636. function getResourceContentLength(resource) {
  78637. if (isResponse(resource)) {
  78638. return resource.headers['content-length'] || -1;
  78639. }
  78640. if (isBlob(resource)) {
  78641. return resource.size;
  78642. }
  78643. if (typeof resource === 'string') {
  78644. return resource.length;
  78645. }
  78646. if (resource instanceof ArrayBuffer) {
  78647. return resource.byteLength;
  78648. }
  78649. if (ArrayBuffer.isView(resource)) {
  78650. return resource.byteLength;
  78651. }
  78652. return -1;
  78653. }
  78654. function stripQueryString(url) {
  78655. return url.replace(QUERY_STRING_PATTERN, '');
  78656. }
  78657. async function makeResponse(resource) {
  78658. if (isResponse(resource)) {
  78659. return resource;
  78660. }
  78661. const headers = {};
  78662. const contentLength = getResourceContentLength(resource);
  78663. if (contentLength >= 0) {
  78664. headers['content-length'] = String(contentLength);
  78665. }
  78666. const {
  78667. url,
  78668. type
  78669. } = getResourceUrlAndType(resource);
  78670. if (type) {
  78671. headers['content-type'] = type;
  78672. }
  78673. const initialDataUrl = await getInitialDataUrl(resource);
  78674. if (initialDataUrl) {
  78675. headers['x-first-bytes'] = initialDataUrl;
  78676. }
  78677. if (typeof resource === 'string') {
  78678. resource = new TextEncoder().encode(resource);
  78679. }
  78680. const response = new Response(resource, {
  78681. headers
  78682. });
  78683. Object.defineProperty(response, 'url', {
  78684. value: url
  78685. });
  78686. return response;
  78687. }
  78688. async function checkResponse(response) {
  78689. if (!response.ok) {
  78690. const message = await getResponseError(response);
  78691. throw new Error(message);
  78692. }
  78693. }
  78694. async function getResponseError(response) {
  78695. let message = "Failed to fetch resource ".concat(response.url, " (").concat(response.status, "): ");
  78696. try {
  78697. const contentType = response.headers.get('Content-Type');
  78698. let text = response.statusText;
  78699. if (contentType.includes('application/json')) {
  78700. text += " ".concat(await response.text());
  78701. }
  78702. message += text;
  78703. message = message.length > 60 ? "".concat(message.slice(60), "...") : message;
  78704. } catch (error) {}
  78705. return message;
  78706. }
  78707. async function getInitialDataUrl(resource) {
  78708. const INITIAL_DATA_LENGTH = 5;
  78709. if (typeof resource === 'string') {
  78710. return "data:,".concat(resource.slice(0, INITIAL_DATA_LENGTH));
  78711. }
  78712. if (resource instanceof Blob) {
  78713. const blobSlice = resource.slice(0, 5);
  78714. return await new Promise(resolve => {
  78715. const reader = new FileReader();
  78716. reader.onload = event => {
  78717. var _event$target;
  78718. return resolve(event === null || event === void 0 ? void 0 : (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.result);
  78719. };
  78720. reader.readAsDataURL(blobSlice);
  78721. });
  78722. }
  78723. if (resource instanceof ArrayBuffer) {
  78724. const slice = resource.slice(0, INITIAL_DATA_LENGTH);
  78725. const base64 = arrayBufferToBase64(slice);
  78726. return "data:base64,".concat(base64);
  78727. }
  78728. return null;
  78729. }
  78730. function arrayBufferToBase64(buffer) {
  78731. let binary = '';
  78732. const bytes = new Uint8Array(buffer);
  78733. for (let i = 0; i < bytes.byteLength; i++) {
  78734. binary += String.fromCharCode(bytes[i]);
  78735. }
  78736. return btoa(binary);
  78737. }
  78738. async function fetchFile(url, options) {
  78739. if (typeof url === 'string') {
  78740. url = resolvePath(url);
  78741. let fetchOptions = options;
  78742. if (options !== null && options !== void 0 && options.fetch && typeof (options === null || options === void 0 ? void 0 : options.fetch) !== 'function') {
  78743. fetchOptions = options.fetch;
  78744. }
  78745. return await fetch(url, fetchOptions);
  78746. }
  78747. return await makeResponse(url);
  78748. }
  78749. function isElectron(mockUserAgent) {
  78750. if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') {
  78751. return true;
  78752. }
  78753. if (typeof process !== 'undefined' && typeof process.versions === 'object' && Boolean(process.versions.electron)) {
  78754. return true;
  78755. }
  78756. const realUserAgent = typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent;
  78757. const userAgent = mockUserAgent || realUserAgent;
  78758. if (userAgent && userAgent.indexOf('Electron') >= 0) {
  78759. return true;
  78760. }
  78761. return false;
  78762. }
  78763. function isBrowser() {
  78764. const isNode = typeof process === 'object' && String(process) === '[object process]' && !process.browser;
  78765. return !isNode || isElectron();
  78766. }
  78767. const globals = {
  78768. self: typeof self !== 'undefined' && self,
  78769. window: typeof window !== 'undefined' && window,
  78770. global: typeof global !== 'undefined' && global,
  78771. document: typeof document !== 'undefined' && document,
  78772. process: typeof process === 'object' && process
  78773. };
  78774. const window_ = globals.window || globals.self || globals.global;
  78775. const process_ = globals.process || {};
  78776. const VERSION$6 = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'untranspiled source';
  78777. isBrowser();
  78778. function getStorage(type) {
  78779. try {
  78780. const storage = window[type];
  78781. const x = '__storage_test__';
  78782. storage.setItem(x, x);
  78783. storage.removeItem(x);
  78784. return storage;
  78785. } catch (e) {
  78786. return null;
  78787. }
  78788. }
  78789. class LocalStorage {
  78790. constructor(id) {
  78791. let defaultSettings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  78792. let type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'sessionStorage';
  78793. _defineProperty(this, "storage", void 0);
  78794. _defineProperty(this, "id", void 0);
  78795. _defineProperty(this, "config", {});
  78796. this.storage = getStorage(type);
  78797. this.id = id;
  78798. this.config = {};
  78799. Object.assign(this.config, defaultSettings);
  78800. this._loadConfiguration();
  78801. }
  78802. getConfiguration() {
  78803. return this.config;
  78804. }
  78805. setConfiguration(configuration) {
  78806. this.config = {};
  78807. return this.updateConfiguration(configuration);
  78808. }
  78809. updateConfiguration(configuration) {
  78810. Object.assign(this.config, configuration);
  78811. if (this.storage) {
  78812. const serialized = JSON.stringify(this.config);
  78813. this.storage.setItem(this.id, serialized);
  78814. }
  78815. return this;
  78816. }
  78817. _loadConfiguration() {
  78818. let configuration = {};
  78819. if (this.storage) {
  78820. const serializedConfiguration = this.storage.getItem(this.id);
  78821. configuration = serializedConfiguration ? JSON.parse(serializedConfiguration) : {};
  78822. }
  78823. Object.assign(this.config, configuration);
  78824. return this;
  78825. }
  78826. }
  78827. function formatTime(ms) {
  78828. let formatted;
  78829. if (ms < 10) {
  78830. formatted = "".concat(ms.toFixed(2), "ms");
  78831. } else if (ms < 100) {
  78832. formatted = "".concat(ms.toFixed(1), "ms");
  78833. } else if (ms < 1000) {
  78834. formatted = "".concat(ms.toFixed(0), "ms");
  78835. } else {
  78836. formatted = "".concat((ms / 1000).toFixed(2), "s");
  78837. }
  78838. return formatted;
  78839. }
  78840. function leftPad(string) {
  78841. let length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 8;
  78842. const padLength = Math.max(length - string.length, 0);
  78843. return "".concat(' '.repeat(padLength)).concat(string);
  78844. }
  78845. function formatImage(image, message, scale) {
  78846. let maxWidth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 600;
  78847. const imageUrl = image.src.replace(/\(/g, '%28').replace(/\)/g, '%29');
  78848. if (image.width > maxWidth) {
  78849. scale = Math.min(scale, maxWidth / image.width);
  78850. }
  78851. const width = image.width * scale;
  78852. const height = image.height * scale;
  78853. const style = ['font-size:1px;', "padding:".concat(Math.floor(height / 2), "px ").concat(Math.floor(width / 2), "px;"), "line-height:".concat(height, "px;"), "background:url(".concat(imageUrl, ");"), "background-size:".concat(width, "px ").concat(height, "px;"), 'color:transparent;'].join('');
  78854. return ["".concat(message, " %c+"), style];
  78855. }
  78856. let COLOR;
  78857. (function (COLOR) {
  78858. COLOR[COLOR["BLACK"] = 30] = "BLACK";
  78859. COLOR[COLOR["RED"] = 31] = "RED";
  78860. COLOR[COLOR["GREEN"] = 32] = "GREEN";
  78861. COLOR[COLOR["YELLOW"] = 33] = "YELLOW";
  78862. COLOR[COLOR["BLUE"] = 34] = "BLUE";
  78863. COLOR[COLOR["MAGENTA"] = 35] = "MAGENTA";
  78864. COLOR[COLOR["CYAN"] = 36] = "CYAN";
  78865. COLOR[COLOR["WHITE"] = 37] = "WHITE";
  78866. COLOR[COLOR["BRIGHT_BLACK"] = 90] = "BRIGHT_BLACK";
  78867. COLOR[COLOR["BRIGHT_RED"] = 91] = "BRIGHT_RED";
  78868. COLOR[COLOR["BRIGHT_GREEN"] = 92] = "BRIGHT_GREEN";
  78869. COLOR[COLOR["BRIGHT_YELLOW"] = 93] = "BRIGHT_YELLOW";
  78870. COLOR[COLOR["BRIGHT_BLUE"] = 94] = "BRIGHT_BLUE";
  78871. COLOR[COLOR["BRIGHT_MAGENTA"] = 95] = "BRIGHT_MAGENTA";
  78872. COLOR[COLOR["BRIGHT_CYAN"] = 96] = "BRIGHT_CYAN";
  78873. COLOR[COLOR["BRIGHT_WHITE"] = 97] = "BRIGHT_WHITE";
  78874. })(COLOR || (COLOR = {}));
  78875. function getColor$1(color) {
  78876. return typeof color === 'string' ? COLOR[color.toUpperCase()] || COLOR.WHITE : color;
  78877. }
  78878. function addColor(string, color, background) {
  78879. if (!isBrowser && typeof string === 'string') {
  78880. if (color) {
  78881. color = getColor$1(color);
  78882. string = "\x1B[".concat(color, "m").concat(string, "\x1B[39m");
  78883. }
  78884. if (background) {
  78885. color = getColor$1(background);
  78886. string = "\x1B[".concat(background + 10, "m").concat(string, "\x1B[49m");
  78887. }
  78888. }
  78889. return string;
  78890. }
  78891. function autobind(obj) {
  78892. let predefined = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ['constructor'];
  78893. const proto = Object.getPrototypeOf(obj);
  78894. const propNames = Object.getOwnPropertyNames(proto);
  78895. for (const key of propNames) {
  78896. if (typeof obj[key] === 'function') {
  78897. if (!predefined.find(name => key === name)) {
  78898. obj[key] = obj[key].bind(obj);
  78899. }
  78900. }
  78901. }
  78902. }
  78903. function assert$5(condition, message) {
  78904. if (!condition) {
  78905. throw new Error(message || 'Assertion failed');
  78906. }
  78907. }
  78908. function getHiResTimestamp() {
  78909. let timestamp;
  78910. if (isBrowser && 'performance' in window_) {
  78911. var _window$performance, _window$performance$n;
  78912. timestamp = window_ === null || window_ === void 0 ? void 0 : (_window$performance = window_.performance) === null || _window$performance === void 0 ? void 0 : (_window$performance$n = _window$performance.now) === null || _window$performance$n === void 0 ? void 0 : _window$performance$n.call(_window$performance);
  78913. } else if ('hrtime' in process_) {
  78914. var _process$hrtime;
  78915. const timeParts = process_ === null || process_ === void 0 ? void 0 : (_process$hrtime = process_.hrtime) === null || _process$hrtime === void 0 ? void 0 : _process$hrtime.call(process_);
  78916. timestamp = timeParts[0] * 1000 + timeParts[1] / 1e6;
  78917. } else {
  78918. timestamp = Date.now();
  78919. }
  78920. return timestamp;
  78921. }
  78922. const originalConsole = {
  78923. debug: isBrowser ? console.debug || console.log : console.log,
  78924. log: console.log,
  78925. info: console.info,
  78926. warn: console.warn,
  78927. error: console.error
  78928. };
  78929. const DEFAULT_SETTINGS = {
  78930. enabled: true,
  78931. level: 0
  78932. };
  78933. function noop$1() {}
  78934. const cache = {};
  78935. const ONCE = {
  78936. once: true
  78937. };
  78938. class Log {
  78939. constructor() {
  78940. let {
  78941. id
  78942. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
  78943. id: ''
  78944. };
  78945. _defineProperty(this, "id", void 0);
  78946. _defineProperty(this, "VERSION", VERSION$6);
  78947. _defineProperty(this, "_startTs", getHiResTimestamp());
  78948. _defineProperty(this, "_deltaTs", getHiResTimestamp());
  78949. _defineProperty(this, "_storage", void 0);
  78950. _defineProperty(this, "userData", {});
  78951. _defineProperty(this, "LOG_THROTTLE_TIMEOUT", 0);
  78952. this.id = id;
  78953. this._storage = new LocalStorage("__probe-".concat(this.id, "__"), DEFAULT_SETTINGS);
  78954. this.userData = {};
  78955. this.timeStamp("".concat(this.id, " started"));
  78956. autobind(this);
  78957. Object.seal(this);
  78958. }
  78959. set level(newLevel) {
  78960. this.setLevel(newLevel);
  78961. }
  78962. get level() {
  78963. return this.getLevel();
  78964. }
  78965. isEnabled() {
  78966. return this._storage.config.enabled;
  78967. }
  78968. getLevel() {
  78969. return this._storage.config.level;
  78970. }
  78971. getTotal() {
  78972. return Number((getHiResTimestamp() - this._startTs).toPrecision(10));
  78973. }
  78974. getDelta() {
  78975. return Number((getHiResTimestamp() - this._deltaTs).toPrecision(10));
  78976. }
  78977. set priority(newPriority) {
  78978. this.level = newPriority;
  78979. }
  78980. get priority() {
  78981. return this.level;
  78982. }
  78983. getPriority() {
  78984. return this.level;
  78985. }
  78986. enable() {
  78987. let enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  78988. this._storage.updateConfiguration({
  78989. enabled
  78990. });
  78991. return this;
  78992. }
  78993. setLevel(level) {
  78994. this._storage.updateConfiguration({
  78995. level
  78996. });
  78997. return this;
  78998. }
  78999. get(setting) {
  79000. return this._storage.config[setting];
  79001. }
  79002. set(setting, value) {
  79003. this._storage.updateConfiguration({
  79004. [setting]: value
  79005. });
  79006. }
  79007. settings() {
  79008. if (console.table) {
  79009. console.table(this._storage.config);
  79010. } else {
  79011. console.log(this._storage.config);
  79012. }
  79013. }
  79014. assert(condition, message) {
  79015. assert$5(condition, message);
  79016. }
  79017. warn(message) {
  79018. return this._getLogFunction(0, message, originalConsole.warn, arguments, ONCE);
  79019. }
  79020. error(message) {
  79021. return this._getLogFunction(0, message, originalConsole.error, arguments);
  79022. }
  79023. deprecated(oldUsage, newUsage) {
  79024. return this.warn("`".concat(oldUsage, "` is deprecated and will be removed in a later version. Use `").concat(newUsage, "` instead"));
  79025. }
  79026. removed(oldUsage, newUsage) {
  79027. return this.error("`".concat(oldUsage, "` has been removed. Use `").concat(newUsage, "` instead"));
  79028. }
  79029. probe(logLevel, message) {
  79030. return this._getLogFunction(logLevel, message, originalConsole.log, arguments, {
  79031. time: true,
  79032. once: true
  79033. });
  79034. }
  79035. log(logLevel, message) {
  79036. return this._getLogFunction(logLevel, message, originalConsole.debug, arguments);
  79037. }
  79038. info(logLevel, message) {
  79039. return this._getLogFunction(logLevel, message, console.info, arguments);
  79040. }
  79041. once(logLevel, message) {
  79042. for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
  79043. args[_key - 2] = arguments[_key];
  79044. }
  79045. return this._getLogFunction(logLevel, message, originalConsole.debug || originalConsole.info, arguments, ONCE);
  79046. }
  79047. table(logLevel, table, columns) {
  79048. if (table) {
  79049. return this._getLogFunction(logLevel, table, console.table || noop$1, columns && [columns], {
  79050. tag: getTableHeader(table)
  79051. });
  79052. }
  79053. return noop$1;
  79054. }
  79055. image(_ref) {
  79056. let {
  79057. logLevel,
  79058. priority,
  79059. image,
  79060. message = '',
  79061. scale = 1
  79062. } = _ref;
  79063. if (!this._shouldLog(logLevel || priority)) {
  79064. return noop$1;
  79065. }
  79066. return isBrowser ? logImageInBrowser({
  79067. image,
  79068. message,
  79069. scale
  79070. }) : logImageInNode({
  79071. image,
  79072. message,
  79073. scale
  79074. });
  79075. }
  79076. time(logLevel, message) {
  79077. return this._getLogFunction(logLevel, message, console.time ? console.time : console.info);
  79078. }
  79079. timeEnd(logLevel, message) {
  79080. return this._getLogFunction(logLevel, message, console.timeEnd ? console.timeEnd : console.info);
  79081. }
  79082. timeStamp(logLevel, message) {
  79083. return this._getLogFunction(logLevel, message, console.timeStamp || noop$1);
  79084. }
  79085. group(logLevel, message) {
  79086. let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
  79087. collapsed: false
  79088. };
  79089. const options = normalizeArguments({
  79090. logLevel,
  79091. message,
  79092. opts
  79093. });
  79094. const {
  79095. collapsed
  79096. } = opts;
  79097. options.method = (collapsed ? console.groupCollapsed : console.group) || console.info;
  79098. return this._getLogFunction(options);
  79099. }
  79100. groupCollapsed(logLevel, message) {
  79101. let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  79102. return this.group(logLevel, message, Object.assign({}, opts, {
  79103. collapsed: true
  79104. }));
  79105. }
  79106. groupEnd(logLevel) {
  79107. return this._getLogFunction(logLevel, '', console.groupEnd || noop$1);
  79108. }
  79109. withGroup(logLevel, message, func) {
  79110. this.group(logLevel, message)();
  79111. try {
  79112. func();
  79113. } finally {
  79114. this.groupEnd(logLevel)();
  79115. }
  79116. }
  79117. trace() {
  79118. if (console.trace) {
  79119. console.trace();
  79120. }
  79121. }
  79122. _shouldLog(logLevel) {
  79123. return this.isEnabled() && this.getLevel() >= normalizeLogLevel(logLevel);
  79124. }
  79125. _getLogFunction(logLevel, message, method, args, opts) {
  79126. if (this._shouldLog(logLevel)) {
  79127. opts = normalizeArguments({
  79128. logLevel,
  79129. message,
  79130. args,
  79131. opts
  79132. });
  79133. method = method || opts.method;
  79134. assert$5(method);
  79135. opts.total = this.getTotal();
  79136. opts.delta = this.getDelta();
  79137. this._deltaTs = getHiResTimestamp();
  79138. const tag = opts.tag || opts.message;
  79139. if (opts.once) {
  79140. if (!cache[tag]) {
  79141. cache[tag] = getHiResTimestamp();
  79142. } else {
  79143. return noop$1;
  79144. }
  79145. }
  79146. message = decorateMessage(this.id, opts.message, opts);
  79147. return method.bind(console, message, ...opts.args);
  79148. }
  79149. return noop$1;
  79150. }
  79151. }
  79152. _defineProperty(Log, "VERSION", VERSION$6);
  79153. function normalizeLogLevel(logLevel) {
  79154. if (!logLevel) {
  79155. return 0;
  79156. }
  79157. let resolvedLevel;
  79158. switch (typeof logLevel) {
  79159. case 'number':
  79160. resolvedLevel = logLevel;
  79161. break;
  79162. case 'object':
  79163. resolvedLevel = logLevel.logLevel || logLevel.priority || 0;
  79164. break;
  79165. default:
  79166. return 0;
  79167. }
  79168. assert$5(Number.isFinite(resolvedLevel) && resolvedLevel >= 0);
  79169. return resolvedLevel;
  79170. }
  79171. function normalizeArguments(opts) {
  79172. const {
  79173. logLevel,
  79174. message
  79175. } = opts;
  79176. opts.logLevel = normalizeLogLevel(logLevel);
  79177. const args = opts.args ? Array.from(opts.args) : [];
  79178. while (args.length && args.shift() !== message) {}
  79179. switch (typeof logLevel) {
  79180. case 'string':
  79181. case 'function':
  79182. if (message !== undefined) {
  79183. args.unshift(message);
  79184. }
  79185. opts.message = logLevel;
  79186. break;
  79187. case 'object':
  79188. Object.assign(opts, logLevel);
  79189. break;
  79190. }
  79191. if (typeof opts.message === 'function') {
  79192. opts.message = opts.message();
  79193. }
  79194. const messageType = typeof opts.message;
  79195. assert$5(messageType === 'string' || messageType === 'object');
  79196. return Object.assign(opts, {
  79197. args
  79198. }, opts.opts);
  79199. }
  79200. function decorateMessage(id, message, opts) {
  79201. if (typeof message === 'string') {
  79202. const time = opts.time ? leftPad(formatTime(opts.total)) : '';
  79203. message = opts.time ? "".concat(id, ": ").concat(time, " ").concat(message) : "".concat(id, ": ").concat(message);
  79204. message = addColor(message, opts.color, opts.background);
  79205. }
  79206. return message;
  79207. }
  79208. function logImageInNode(_ref2) {
  79209. let {
  79210. image,
  79211. message = '',
  79212. scale = 1
  79213. } = _ref2;
  79214. let asciify = null;
  79215. try {
  79216. asciify = module.require('asciify-image');
  79217. } catch (error) {}
  79218. if (asciify) {
  79219. return () => asciify(image, {
  79220. fit: 'box',
  79221. width: "".concat(Math.round(80 * scale), "%")
  79222. }).then(data => console.log(data));
  79223. }
  79224. return noop$1;
  79225. }
  79226. function logImageInBrowser(_ref3) {
  79227. let {
  79228. image,
  79229. message = '',
  79230. scale = 1
  79231. } = _ref3;
  79232. if (typeof image === 'string') {
  79233. const img = new Image();
  79234. img.onload = () => {
  79235. const args = formatImage(img, message, scale);
  79236. console.log(...args);
  79237. };
  79238. img.src = image;
  79239. return noop$1;
  79240. }
  79241. const element = image.nodeName || '';
  79242. if (element.toLowerCase() === 'img') {
  79243. console.log(...formatImage(image, message, scale));
  79244. return noop$1;
  79245. }
  79246. if (element.toLowerCase() === 'canvas') {
  79247. const img = new Image();
  79248. img.onload = () => console.log(...formatImage(img, message, scale));
  79249. img.src = image.toDataURL();
  79250. return noop$1;
  79251. }
  79252. return noop$1;
  79253. }
  79254. function getTableHeader(table) {
  79255. for (const key in table) {
  79256. for (const title in table[key]) {
  79257. return title || 'untitled';
  79258. }
  79259. }
  79260. return 'empty';
  79261. }
  79262. const probeLog = new Log({
  79263. id: 'loaders.gl'
  79264. });
  79265. class NullLog {
  79266. log() {
  79267. return () => {};
  79268. }
  79269. info() {
  79270. return () => {};
  79271. }
  79272. warn() {
  79273. return () => {};
  79274. }
  79275. error() {
  79276. return () => {};
  79277. }
  79278. }
  79279. class ConsoleLog {
  79280. constructor() {
  79281. _defineProperty(this, "console", void 0);
  79282. this.console = console;
  79283. }
  79284. log(...args) {
  79285. return this.console.log.bind(this.console, ...args);
  79286. }
  79287. info(...args) {
  79288. return this.console.info.bind(this.console, ...args);
  79289. }
  79290. warn(...args) {
  79291. return this.console.warn.bind(this.console, ...args);
  79292. }
  79293. error(...args) {
  79294. return this.console.error.bind(this.console, ...args);
  79295. }
  79296. }
  79297. const DEFAULT_LOADER_OPTIONS = {
  79298. fetch: null,
  79299. mimeType: undefined,
  79300. nothrow: false,
  79301. log: new ConsoleLog(),
  79302. CDN: 'https://unpkg.com/@loaders.gl',
  79303. worker: true,
  79304. maxConcurrency: 3,
  79305. maxMobileConcurrency: 1,
  79306. reuseWorkers: true,
  79307. _workerType: '',
  79308. limit: 0,
  79309. _limitMB: 0,
  79310. batchSize: 'auto',
  79311. batchDebounceMs: 0,
  79312. metadata: false,
  79313. transforms: []
  79314. };
  79315. const REMOVED_LOADER_OPTIONS = {
  79316. throws: 'nothrow',
  79317. dataType: '(no longer used)',
  79318. uri: 'baseUri',
  79319. method: 'fetch.method',
  79320. headers: 'fetch.headers',
  79321. body: 'fetch.body',
  79322. mode: 'fetch.mode',
  79323. credentials: 'fetch.credentials',
  79324. cache: 'fetch.cache',
  79325. redirect: 'fetch.redirect',
  79326. referrer: 'fetch.referrer',
  79327. referrerPolicy: 'fetch.referrerPolicy',
  79328. integrity: 'fetch.integrity',
  79329. keepalive: 'fetch.keepalive',
  79330. signal: 'fetch.signal'
  79331. };
  79332. function getGlobalLoaderState() {
  79333. globalThis.loaders = globalThis.loaders || {};
  79334. const {
  79335. loaders
  79336. } = globalThis;
  79337. loaders._state = loaders._state || {};
  79338. return loaders._state;
  79339. }
  79340. const getGlobalLoaderOptions = () => {
  79341. const state = getGlobalLoaderState();
  79342. state.globalOptions = state.globalOptions || { ...DEFAULT_LOADER_OPTIONS
  79343. };
  79344. return state.globalOptions;
  79345. };
  79346. function normalizeOptions(options, loader, loaders, url) {
  79347. loaders = loaders || [];
  79348. loaders = Array.isArray(loaders) ? loaders : [loaders];
  79349. validateOptions(options, loaders);
  79350. return normalizeOptionsInternal(loader, options, url);
  79351. }
  79352. function getFetchFunction(options, context) {
  79353. const globalOptions = getGlobalLoaderOptions();
  79354. const fetchOptions = options || globalOptions;
  79355. if (typeof fetchOptions.fetch === 'function') {
  79356. return fetchOptions.fetch;
  79357. }
  79358. if (isObject(fetchOptions.fetch)) {
  79359. return url => fetchFile(url, fetchOptions);
  79360. }
  79361. if (context !== null && context !== void 0 && context.fetch) {
  79362. return context === null || context === void 0 ? void 0 : context.fetch;
  79363. }
  79364. return fetchFile;
  79365. }
  79366. function validateOptions(options, loaders) {
  79367. validateOptionsObject(options, null, DEFAULT_LOADER_OPTIONS, REMOVED_LOADER_OPTIONS, loaders);
  79368. for (const loader of loaders) {
  79369. const idOptions = options && options[loader.id] || {};
  79370. const loaderOptions = loader.options && loader.options[loader.id] || {};
  79371. const deprecatedOptions = loader.deprecatedOptions && loader.deprecatedOptions[loader.id] || {};
  79372. validateOptionsObject(idOptions, loader.id, loaderOptions, deprecatedOptions, loaders);
  79373. }
  79374. }
  79375. function validateOptionsObject(options, id, defaultOptions, deprecatedOptions, loaders) {
  79376. const loaderName = id || 'Top level';
  79377. const prefix = id ? "".concat(id, ".") : '';
  79378. for (const key in options) {
  79379. const isSubOptions = !id && isObject(options[key]);
  79380. const isBaseUriOption = key === 'baseUri' && !id;
  79381. const isWorkerUrlOption = key === 'workerUrl' && id;
  79382. if (!(key in defaultOptions) && !isBaseUriOption && !isWorkerUrlOption) {
  79383. if (key in deprecatedOptions) {
  79384. probeLog.warn("".concat(loaderName, " loader option '").concat(prefix).concat(key, "' no longer supported, use '").concat(deprecatedOptions[key], "'"))();
  79385. } else if (!isSubOptions) {
  79386. const suggestion = findSimilarOption(key, loaders);
  79387. probeLog.warn("".concat(loaderName, " loader option '").concat(prefix).concat(key, "' not recognized. ").concat(suggestion))();
  79388. }
  79389. }
  79390. }
  79391. }
  79392. function findSimilarOption(optionKey, loaders) {
  79393. const lowerCaseOptionKey = optionKey.toLowerCase();
  79394. let bestSuggestion = '';
  79395. for (const loader of loaders) {
  79396. for (const key in loader.options) {
  79397. if (optionKey === key) {
  79398. return "Did you mean '".concat(loader.id, ".").concat(key, "'?");
  79399. }
  79400. const lowerCaseKey = key.toLowerCase();
  79401. const isPartialMatch = lowerCaseOptionKey.startsWith(lowerCaseKey) || lowerCaseKey.startsWith(lowerCaseOptionKey);
  79402. if (isPartialMatch) {
  79403. bestSuggestion = bestSuggestion || "Did you mean '".concat(loader.id, ".").concat(key, "'?");
  79404. }
  79405. }
  79406. }
  79407. return bestSuggestion;
  79408. }
  79409. function normalizeOptionsInternal(loader, options, url) {
  79410. const loaderDefaultOptions = loader.options || {};
  79411. const mergedOptions = { ...loaderDefaultOptions
  79412. };
  79413. addUrlOptions(mergedOptions, url);
  79414. if (mergedOptions.log === null) {
  79415. mergedOptions.log = new NullLog();
  79416. }
  79417. mergeNestedFields(mergedOptions, getGlobalLoaderOptions());
  79418. mergeNestedFields(mergedOptions, options);
  79419. return mergedOptions;
  79420. }
  79421. function mergeNestedFields(mergedOptions, options) {
  79422. for (const key in options) {
  79423. if (key in options) {
  79424. const value = options[key];
  79425. if (isPureObject(value) && isPureObject(mergedOptions[key])) {
  79426. mergedOptions[key] = { ...mergedOptions[key],
  79427. ...options[key]
  79428. };
  79429. } else {
  79430. mergedOptions[key] = options[key];
  79431. }
  79432. }
  79433. }
  79434. }
  79435. function addUrlOptions(options, url) {
  79436. if (url && !('baseUri' in options)) {
  79437. options.baseUri = url;
  79438. }
  79439. }
  79440. function isLoaderObject(loader) {
  79441. var _loader;
  79442. if (!loader) {
  79443. return false;
  79444. }
  79445. if (Array.isArray(loader)) {
  79446. loader = loader[0];
  79447. }
  79448. const hasExtensions = Array.isArray((_loader = loader) === null || _loader === void 0 ? void 0 : _loader.extensions);
  79449. return hasExtensions;
  79450. }
  79451. function normalizeLoader(loader) {
  79452. var _loader2, _loader3;
  79453. assert$7(loader, 'null loader');
  79454. assert$7(isLoaderObject(loader), 'invalid loader');
  79455. let options;
  79456. if (Array.isArray(loader)) {
  79457. options = loader[1];
  79458. loader = loader[0];
  79459. loader = { ...loader,
  79460. options: { ...loader.options,
  79461. ...options
  79462. }
  79463. };
  79464. }
  79465. if ((_loader2 = loader) !== null && _loader2 !== void 0 && _loader2.parseTextSync || (_loader3 = loader) !== null && _loader3 !== void 0 && _loader3.parseText) {
  79466. loader.text = true;
  79467. }
  79468. if (!loader.text) {
  79469. loader.binary = true;
  79470. }
  79471. return loader;
  79472. }
  79473. const getGlobalLoaderRegistry = () => {
  79474. const state = getGlobalLoaderState();
  79475. state.loaderRegistry = state.loaderRegistry || [];
  79476. return state.loaderRegistry;
  79477. };
  79478. function getRegisteredLoaders() {
  79479. return getGlobalLoaderRegistry();
  79480. }
  79481. const EXT_PATTERN = /\.([^.]+)$/;
  79482. async function selectLoader(data, loaders = [], options, context) {
  79483. if (!validHTTPResponse(data)) {
  79484. return null;
  79485. }
  79486. let loader = selectLoaderSync(data, loaders, { ...options,
  79487. nothrow: true
  79488. }, context);
  79489. if (loader) {
  79490. return loader;
  79491. }
  79492. if (isBlob(data)) {
  79493. data = await data.slice(0, 10).arrayBuffer();
  79494. loader = selectLoaderSync(data, loaders, options, context);
  79495. }
  79496. if (!loader && !(options !== null && options !== void 0 && options.nothrow)) {
  79497. throw new Error(getNoValidLoaderMessage(data));
  79498. }
  79499. return loader;
  79500. }
  79501. function selectLoaderSync(data, loaders = [], options, context) {
  79502. if (!validHTTPResponse(data)) {
  79503. return null;
  79504. }
  79505. if (loaders && !Array.isArray(loaders)) {
  79506. return normalizeLoader(loaders);
  79507. }
  79508. let candidateLoaders = [];
  79509. if (loaders) {
  79510. candidateLoaders = candidateLoaders.concat(loaders);
  79511. }
  79512. if (!(options !== null && options !== void 0 && options.ignoreRegisteredLoaders)) {
  79513. candidateLoaders.push(...getRegisteredLoaders());
  79514. }
  79515. normalizeLoaders(candidateLoaders);
  79516. const loader = selectLoaderInternal(data, candidateLoaders, options, context);
  79517. if (!loader && !(options !== null && options !== void 0 && options.nothrow)) {
  79518. throw new Error(getNoValidLoaderMessage(data));
  79519. }
  79520. return loader;
  79521. }
  79522. function selectLoaderInternal(data, loaders, options, context) {
  79523. const {
  79524. url,
  79525. type
  79526. } = getResourceUrlAndType(data);
  79527. const testUrl = url || (context === null || context === void 0 ? void 0 : context.url);
  79528. let loader = null;
  79529. if (options !== null && options !== void 0 && options.mimeType) {
  79530. loader = findLoaderByMIMEType(loaders, options === null || options === void 0 ? void 0 : options.mimeType);
  79531. }
  79532. loader = loader || findLoaderByUrl(loaders, testUrl);
  79533. loader = loader || findLoaderByMIMEType(loaders, type);
  79534. loader = loader || findLoaderByInitialBytes(loaders, data);
  79535. loader = loader || findLoaderByMIMEType(loaders, options === null || options === void 0 ? void 0 : options.fallbackMimeType);
  79536. return loader;
  79537. }
  79538. function validHTTPResponse(data) {
  79539. if (data instanceof Response) {
  79540. if (data.status === 204) {
  79541. return false;
  79542. }
  79543. }
  79544. return true;
  79545. }
  79546. function getNoValidLoaderMessage(data) {
  79547. const {
  79548. url,
  79549. type
  79550. } = getResourceUrlAndType(data);
  79551. let message = 'No valid loader found (';
  79552. message += url ? "".concat(filename(url), ", ") : 'no url provided, ';
  79553. message += "MIME type: ".concat(type ? "\"".concat(type, "\"") : 'not provided', ", ");
  79554. const firstCharacters = data ? getFirstCharacters(data) : '';
  79555. message += firstCharacters ? " first bytes: \"".concat(firstCharacters, "\"") : 'first bytes: not available';
  79556. message += ')';
  79557. return message;
  79558. }
  79559. function normalizeLoaders(loaders) {
  79560. for (const loader of loaders) {
  79561. normalizeLoader(loader);
  79562. }
  79563. }
  79564. function findLoaderByUrl(loaders, url) {
  79565. const match = url && EXT_PATTERN.exec(url);
  79566. const extension = match && match[1];
  79567. return extension ? findLoaderByExtension(loaders, extension) : null;
  79568. }
  79569. function findLoaderByExtension(loaders, extension) {
  79570. extension = extension.toLowerCase();
  79571. for (const loader of loaders) {
  79572. for (const loaderExtension of loader.extensions) {
  79573. if (loaderExtension.toLowerCase() === extension) {
  79574. return loader;
  79575. }
  79576. }
  79577. }
  79578. return null;
  79579. }
  79580. function findLoaderByMIMEType(loaders, mimeType) {
  79581. for (const loader of loaders) {
  79582. if (loader.mimeTypes && loader.mimeTypes.includes(mimeType)) {
  79583. return loader;
  79584. }
  79585. if (mimeType === "application/x.".concat(loader.id)) {
  79586. return loader;
  79587. }
  79588. }
  79589. return null;
  79590. }
  79591. function findLoaderByInitialBytes(loaders, data) {
  79592. if (!data) {
  79593. return null;
  79594. }
  79595. for (const loader of loaders) {
  79596. if (typeof data === 'string') {
  79597. if (testDataAgainstText(data, loader)) {
  79598. return loader;
  79599. }
  79600. } else if (ArrayBuffer.isView(data)) {
  79601. if (testDataAgainstBinary(data.buffer, data.byteOffset, loader)) {
  79602. return loader;
  79603. }
  79604. } else if (data instanceof ArrayBuffer) {
  79605. const byteOffset = 0;
  79606. if (testDataAgainstBinary(data, byteOffset, loader)) {
  79607. return loader;
  79608. }
  79609. }
  79610. }
  79611. return null;
  79612. }
  79613. function testDataAgainstText(data, loader) {
  79614. if (loader.testText) {
  79615. return loader.testText(data);
  79616. }
  79617. const tests = Array.isArray(loader.tests) ? loader.tests : [loader.tests];
  79618. return tests.some(test => data.startsWith(test));
  79619. }
  79620. function testDataAgainstBinary(data, byteOffset, loader) {
  79621. const tests = Array.isArray(loader.tests) ? loader.tests : [loader.tests];
  79622. return tests.some(test => testBinary(data, byteOffset, loader, test));
  79623. }
  79624. function testBinary(data, byteOffset, loader, test) {
  79625. if (test instanceof ArrayBuffer) {
  79626. return compareArrayBuffers(test, data, test.byteLength);
  79627. }
  79628. switch (typeof test) {
  79629. case 'function':
  79630. return test(data, loader);
  79631. case 'string':
  79632. const magic = getMagicString$2(data, byteOffset, test.length);
  79633. return test === magic;
  79634. default:
  79635. return false;
  79636. }
  79637. }
  79638. function getFirstCharacters(data, length = 5) {
  79639. if (typeof data === 'string') {
  79640. return data.slice(0, length);
  79641. } else if (ArrayBuffer.isView(data)) {
  79642. return getMagicString$2(data.buffer, data.byteOffset, length);
  79643. } else if (data instanceof ArrayBuffer) {
  79644. const byteOffset = 0;
  79645. return getMagicString$2(data, byteOffset, length);
  79646. }
  79647. return '';
  79648. }
  79649. function getMagicString$2(arrayBuffer, byteOffset, length) {
  79650. if (arrayBuffer.byteLength < byteOffset + length) {
  79651. return '';
  79652. }
  79653. const dataView = new DataView(arrayBuffer);
  79654. let magic = '';
  79655. for (let i = 0; i < length; i++) {
  79656. magic += String.fromCharCode(dataView.getUint8(byteOffset + i));
  79657. }
  79658. return magic;
  79659. }
  79660. const DEFAULT_CHUNK_SIZE$2 = 256 * 1024;
  79661. function* makeStringIterator(string, options) {
  79662. const chunkSize = (options === null || options === void 0 ? void 0 : options.chunkSize) || DEFAULT_CHUNK_SIZE$2;
  79663. let offset = 0;
  79664. const textEncoder = new TextEncoder();
  79665. while (offset < string.length) {
  79666. const chunkLength = Math.min(string.length - offset, chunkSize);
  79667. const chunk = string.slice(offset, offset + chunkLength);
  79668. offset += chunkLength;
  79669. yield textEncoder.encode(chunk);
  79670. }
  79671. }
  79672. const DEFAULT_CHUNK_SIZE$1 = 256 * 1024;
  79673. function* makeArrayBufferIterator(arrayBuffer, options = {}) {
  79674. const {
  79675. chunkSize = DEFAULT_CHUNK_SIZE$1
  79676. } = options;
  79677. let byteOffset = 0;
  79678. while (byteOffset < arrayBuffer.byteLength) {
  79679. const chunkByteLength = Math.min(arrayBuffer.byteLength - byteOffset, chunkSize);
  79680. const chunk = new ArrayBuffer(chunkByteLength);
  79681. const sourceArray = new Uint8Array(arrayBuffer, byteOffset, chunkByteLength);
  79682. const chunkArray = new Uint8Array(chunk);
  79683. chunkArray.set(sourceArray);
  79684. byteOffset += chunkByteLength;
  79685. yield chunk;
  79686. }
  79687. }
  79688. const DEFAULT_CHUNK_SIZE = 1024 * 1024;
  79689. async function* makeBlobIterator(blob, options) {
  79690. const chunkSize = (options === null || options === void 0 ? void 0 : options.chunkSize) || DEFAULT_CHUNK_SIZE;
  79691. let offset = 0;
  79692. while (offset < blob.size) {
  79693. const end = offset + chunkSize;
  79694. const chunk = await blob.slice(offset, end).arrayBuffer();
  79695. offset = end;
  79696. yield chunk;
  79697. }
  79698. }
  79699. function makeStreamIterator(stream, options) {
  79700. return isBrowser$2 ? makeBrowserStreamIterator(stream, options) : makeNodeStreamIterator(stream);
  79701. }
  79702. async function* makeBrowserStreamIterator(stream, options) {
  79703. const reader = stream.getReader();
  79704. let nextBatchPromise;
  79705. try {
  79706. while (true) {
  79707. const currentBatchPromise = nextBatchPromise || reader.read();
  79708. if (options !== null && options !== void 0 && options._streamReadAhead) {
  79709. nextBatchPromise = reader.read();
  79710. }
  79711. const {
  79712. done,
  79713. value
  79714. } = await currentBatchPromise;
  79715. if (done) {
  79716. return;
  79717. }
  79718. yield toArrayBuffer(value);
  79719. }
  79720. } catch (error) {
  79721. reader.releaseLock();
  79722. }
  79723. }
  79724. async function* makeNodeStreamIterator(stream, options) {
  79725. for await (const chunk of stream) {
  79726. yield toArrayBuffer(chunk);
  79727. }
  79728. }
  79729. function makeIterator(data, options) {
  79730. if (typeof data === 'string') {
  79731. return makeStringIterator(data, options);
  79732. }
  79733. if (data instanceof ArrayBuffer) {
  79734. return makeArrayBufferIterator(data, options);
  79735. }
  79736. if (isBlob(data)) {
  79737. return makeBlobIterator(data, options);
  79738. }
  79739. if (isReadableStream(data)) {
  79740. return makeStreamIterator(data, options);
  79741. }
  79742. if (isResponse(data)) {
  79743. const response = data;
  79744. return makeStreamIterator(response.body, options);
  79745. }
  79746. throw new Error('makeIterator');
  79747. }
  79748. const ERR_DATA = 'Cannot convert supplied data type';
  79749. function getArrayBufferOrStringFromDataSync(data, loader, options) {
  79750. if (loader.text && typeof data === 'string') {
  79751. return data;
  79752. }
  79753. if (isBuffer(data)) {
  79754. data = data.buffer;
  79755. }
  79756. if (data instanceof ArrayBuffer) {
  79757. const arrayBuffer = data;
  79758. if (loader.text && !loader.binary) {
  79759. const textDecoder = new TextDecoder('utf8');
  79760. return textDecoder.decode(arrayBuffer);
  79761. }
  79762. return arrayBuffer;
  79763. }
  79764. if (ArrayBuffer.isView(data)) {
  79765. if (loader.text && !loader.binary) {
  79766. const textDecoder = new TextDecoder('utf8');
  79767. return textDecoder.decode(data);
  79768. }
  79769. let arrayBuffer = data.buffer;
  79770. const byteLength = data.byteLength || data.length;
  79771. if (data.byteOffset !== 0 || byteLength !== arrayBuffer.byteLength) {
  79772. arrayBuffer = arrayBuffer.slice(data.byteOffset, data.byteOffset + byteLength);
  79773. }
  79774. return arrayBuffer;
  79775. }
  79776. throw new Error(ERR_DATA);
  79777. }
  79778. async function getArrayBufferOrStringFromData(data, loader, options) {
  79779. const isArrayBuffer = data instanceof ArrayBuffer || ArrayBuffer.isView(data);
  79780. if (typeof data === 'string' || isArrayBuffer) {
  79781. return getArrayBufferOrStringFromDataSync(data, loader);
  79782. }
  79783. if (isBlob(data)) {
  79784. data = await makeResponse(data);
  79785. }
  79786. if (isResponse(data)) {
  79787. const response = data;
  79788. await checkResponse(response);
  79789. return loader.binary ? await response.arrayBuffer() : await response.text();
  79790. }
  79791. if (isReadableStream(data)) {
  79792. data = makeIterator(data, options);
  79793. }
  79794. if (isIterable(data) || isAsyncIterable(data)) {
  79795. return concatenateArrayBuffersAsync(data);
  79796. }
  79797. throw new Error(ERR_DATA);
  79798. }
  79799. function getLoaderContext(context, options, previousContext = null) {
  79800. if (previousContext) {
  79801. return previousContext;
  79802. }
  79803. const resolvedContext = {
  79804. fetch: getFetchFunction(options, context),
  79805. ...context
  79806. };
  79807. if (!Array.isArray(resolvedContext.loaders)) {
  79808. resolvedContext.loaders = null;
  79809. }
  79810. return resolvedContext;
  79811. }
  79812. function getLoadersFromContext(loaders, context) {
  79813. if (!context && loaders && !Array.isArray(loaders)) {
  79814. return loaders;
  79815. }
  79816. let candidateLoaders;
  79817. if (loaders) {
  79818. candidateLoaders = Array.isArray(loaders) ? loaders : [loaders];
  79819. }
  79820. if (context && context.loaders) {
  79821. const contextLoaders = Array.isArray(context.loaders) ? context.loaders : [context.loaders];
  79822. candidateLoaders = candidateLoaders ? [...candidateLoaders, ...contextLoaders] : contextLoaders;
  79823. }
  79824. return candidateLoaders && candidateLoaders.length ? candidateLoaders : null;
  79825. }
  79826. async function parse$3(data, loaders, options, context) {
  79827. assert$6(!context || typeof context === 'object');
  79828. if (loaders && !Array.isArray(loaders) && !isLoaderObject(loaders)) {
  79829. context = undefined;
  79830. options = loaders;
  79831. loaders = undefined;
  79832. }
  79833. data = await data;
  79834. options = options || {};
  79835. const {
  79836. url
  79837. } = getResourceUrlAndType(data);
  79838. const typedLoaders = loaders;
  79839. const candidateLoaders = getLoadersFromContext(typedLoaders, context);
  79840. const loader = await selectLoader(data, candidateLoaders, options);
  79841. if (!loader) {
  79842. return null;
  79843. }
  79844. options = normalizeOptions(options, loader, candidateLoaders, url);
  79845. context = getLoaderContext({
  79846. url,
  79847. parse: parse$3,
  79848. loaders: candidateLoaders
  79849. }, options, context);
  79850. return await parseWithLoader(loader, data, options, context);
  79851. }
  79852. async function parseWithLoader(loader, data, options, context) {
  79853. validateWorkerVersion(loader);
  79854. data = await getArrayBufferOrStringFromData(data, loader, options);
  79855. if (loader.parseTextSync && typeof data === 'string') {
  79856. options.dataType = 'text';
  79857. return loader.parseTextSync(data, options, context, loader);
  79858. }
  79859. if (canParseWithWorker(loader, options)) {
  79860. return await parseWithWorker(loader, data, options, context, parse$3);
  79861. }
  79862. if (loader.parseText && typeof data === 'string') {
  79863. return await loader.parseText(data, options, context, loader);
  79864. }
  79865. if (loader.parse) {
  79866. return await loader.parse(data, options, context, loader);
  79867. }
  79868. assert$6(!loader.parseSync);
  79869. throw new Error("".concat(loader.id, " loader - no parser found and worker is disabled"));
  79870. }
  79871. async function load(url, loaders, options, context) {
  79872. if (!Array.isArray(loaders) && !isLoaderObject(loaders)) {
  79873. options = loaders;
  79874. loaders = undefined;
  79875. }
  79876. const fetch = getFetchFunction(options);
  79877. let data = url;
  79878. if (typeof url === 'string') {
  79879. data = await fetch(url);
  79880. }
  79881. if (isBlob(url)) {
  79882. data = await fetch(url);
  79883. }
  79884. return await parse$3(data, loaders, options);
  79885. }
  79886. function assert$4(condition, message) {
  79887. if (!condition) {
  79888. throw new Error("math.gl assertion ".concat(message));
  79889. }
  79890. }
  79891. const RADIANS_TO_DEGREES = 1 / Math.PI * 180;
  79892. const DEGREES_TO_RADIANS = 1 / 180 * Math.PI;
  79893. const config$2 = {};
  79894. config$2.EPSILON = 1e-12;
  79895. config$2.debug = false;
  79896. config$2.precision = 4;
  79897. config$2.printTypes = false;
  79898. config$2.printDegrees = false;
  79899. config$2.printRowMajor = true;
  79900. function round(value) {
  79901. return Math.round(value / config$2.EPSILON) * config$2.EPSILON;
  79902. }
  79903. function formatValue(value, {
  79904. precision = config$2.precision || 4
  79905. } = {}) {
  79906. value = round(value);
  79907. return "".concat(parseFloat(value.toPrecision(precision)));
  79908. }
  79909. function isArray(value) {
  79910. return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
  79911. }
  79912. function duplicateArray(array) {
  79913. return array.clone ? array.clone() : new Array(array.length);
  79914. }
  79915. function map$1(value, func, result) {
  79916. if (isArray(value)) {
  79917. result = result || duplicateArray(value);
  79918. for (let i = 0; i < result.length && i < value.length; ++i) {
  79919. result[i] = func(value[i], i, result);
  79920. }
  79921. return result;
  79922. }
  79923. return func(value);
  79924. }
  79925. function toRadians(degrees) {
  79926. return radians(degrees);
  79927. }
  79928. function toDegrees(radians) {
  79929. return degrees(radians);
  79930. }
  79931. function radians(degrees, result) {
  79932. return map$1(degrees, degrees => degrees * DEGREES_TO_RADIANS, result);
  79933. }
  79934. function degrees(radians, result) {
  79935. return map$1(radians, radians => radians * RADIANS_TO_DEGREES, result);
  79936. }
  79937. function clamp(value, min, max) {
  79938. return map$1(value, value => Math.max(min, Math.min(max, value)));
  79939. }
  79940. function equals$1(a, b, epsilon) {
  79941. const oldEpsilon = config$2.EPSILON;
  79942. if (epsilon) {
  79943. config$2.EPSILON = epsilon;
  79944. }
  79945. try {
  79946. if (a === b) {
  79947. return true;
  79948. }
  79949. if (isArray(a) && isArray(b)) {
  79950. if (a.length !== b.length) {
  79951. return false;
  79952. }
  79953. for (let i = 0; i < a.length; ++i) {
  79954. if (!equals$1(a[i], b[i])) {
  79955. return false;
  79956. }
  79957. }
  79958. return true;
  79959. }
  79960. if (a && a.equals) {
  79961. return a.equals(b);
  79962. }
  79963. if (b && b.equals) {
  79964. return b.equals(a);
  79965. }
  79966. if (Number.isFinite(a) && Number.isFinite(b)) {
  79967. return Math.abs(a - b) <= config$2.EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));
  79968. }
  79969. return false;
  79970. } finally {
  79971. config$2.EPSILON = oldEpsilon;
  79972. }
  79973. }
  79974. function _extendableBuiltin(cls) {
  79975. function ExtendableBuiltin() {
  79976. var instance = Reflect.construct(cls, Array.from(arguments));
  79977. Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
  79978. return instance;
  79979. }
  79980. ExtendableBuiltin.prototype = Object.create(cls.prototype, {
  79981. constructor: {
  79982. value: cls,
  79983. enumerable: false,
  79984. writable: true,
  79985. configurable: true
  79986. }
  79987. });
  79988. if (Object.setPrototypeOf) {
  79989. Object.setPrototypeOf(ExtendableBuiltin, cls);
  79990. } else {
  79991. ExtendableBuiltin.__proto__ = cls;
  79992. }
  79993. return ExtendableBuiltin;
  79994. }
  79995. class MathArray extends _extendableBuiltin(Array) {
  79996. get ELEMENTS() {
  79997. assert$4(false);
  79998. return 0;
  79999. }
  80000. clone() {
  80001. return new this.constructor().copy(this);
  80002. }
  80003. from(arrayOrObject) {
  80004. return Array.isArray(arrayOrObject) ? this.copy(arrayOrObject) : this.fromObject(arrayOrObject);
  80005. }
  80006. fromArray(array, offset = 0) {
  80007. for (let i = 0; i < this.ELEMENTS; ++i) {
  80008. this[i] = array[i + offset];
  80009. }
  80010. return this.check();
  80011. }
  80012. to(arrayOrObject) {
  80013. if (arrayOrObject === this) {
  80014. return this;
  80015. }
  80016. return isArray(arrayOrObject) ? this.toArray(arrayOrObject) : this.toObject(arrayOrObject);
  80017. }
  80018. toTarget(target) {
  80019. return target ? this.to(target) : this;
  80020. }
  80021. toArray(array = [], offset = 0) {
  80022. for (let i = 0; i < this.ELEMENTS; ++i) {
  80023. array[offset + i] = this[i];
  80024. }
  80025. return array;
  80026. }
  80027. toFloat32Array() {
  80028. return new Float32Array(this);
  80029. }
  80030. toString() {
  80031. return this.formatString(config$2);
  80032. }
  80033. formatString(opts) {
  80034. let string = '';
  80035. for (let i = 0; i < this.ELEMENTS; ++i) {
  80036. string += (i > 0 ? ', ' : '') + formatValue(this[i], opts);
  80037. }
  80038. return "".concat(opts.printTypes ? this.constructor.name : '', "[").concat(string, "]");
  80039. }
  80040. equals(array) {
  80041. if (!array || this.length !== array.length) {
  80042. return false;
  80043. }
  80044. for (let i = 0; i < this.ELEMENTS; ++i) {
  80045. if (!equals$1(this[i], array[i])) {
  80046. return false;
  80047. }
  80048. }
  80049. return true;
  80050. }
  80051. exactEquals(array) {
  80052. if (!array || this.length !== array.length) {
  80053. return false;
  80054. }
  80055. for (let i = 0; i < this.ELEMENTS; ++i) {
  80056. if (this[i] !== array[i]) {
  80057. return false;
  80058. }
  80059. }
  80060. return true;
  80061. }
  80062. negate() {
  80063. for (let i = 0; i < this.ELEMENTS; ++i) {
  80064. this[i] = -this[i];
  80065. }
  80066. return this.check();
  80067. }
  80068. lerp(a, b, t) {
  80069. if (t === undefined) {
  80070. t = b;
  80071. b = a;
  80072. a = this;
  80073. }
  80074. for (let i = 0; i < this.ELEMENTS; ++i) {
  80075. const ai = a[i];
  80076. this[i] = ai + t * (b[i] - ai);
  80077. }
  80078. return this.check();
  80079. }
  80080. min(vector) {
  80081. for (let i = 0; i < this.ELEMENTS; ++i) {
  80082. this[i] = Math.min(vector[i], this[i]);
  80083. }
  80084. return this.check();
  80085. }
  80086. max(vector) {
  80087. for (let i = 0; i < this.ELEMENTS; ++i) {
  80088. this[i] = Math.max(vector[i], this[i]);
  80089. }
  80090. return this.check();
  80091. }
  80092. clamp(minVector, maxVector) {
  80093. for (let i = 0; i < this.ELEMENTS; ++i) {
  80094. this[i] = Math.min(Math.max(this[i], minVector[i]), maxVector[i]);
  80095. }
  80096. return this.check();
  80097. }
  80098. add(...vectors) {
  80099. for (const vector of vectors) {
  80100. for (let i = 0; i < this.ELEMENTS; ++i) {
  80101. this[i] += vector[i];
  80102. }
  80103. }
  80104. return this.check();
  80105. }
  80106. subtract(...vectors) {
  80107. for (const vector of vectors) {
  80108. for (let i = 0; i < this.ELEMENTS; ++i) {
  80109. this[i] -= vector[i];
  80110. }
  80111. }
  80112. return this.check();
  80113. }
  80114. scale(scale) {
  80115. if (Array.isArray(scale)) {
  80116. return this.multiply(scale);
  80117. }
  80118. for (let i = 0; i < this.ELEMENTS; ++i) {
  80119. this[i] *= scale;
  80120. }
  80121. return this.check();
  80122. }
  80123. sub(a) {
  80124. return this.subtract(a);
  80125. }
  80126. setScalar(a) {
  80127. for (let i = 0; i < this.ELEMENTS; ++i) {
  80128. this[i] = a;
  80129. }
  80130. return this.check();
  80131. }
  80132. addScalar(a) {
  80133. for (let i = 0; i < this.ELEMENTS; ++i) {
  80134. this[i] += a;
  80135. }
  80136. return this.check();
  80137. }
  80138. subScalar(a) {
  80139. return this.addScalar(-a);
  80140. }
  80141. multiplyScalar(scalar) {
  80142. for (let i = 0; i < this.ELEMENTS; ++i) {
  80143. this[i] *= scalar;
  80144. }
  80145. return this.check();
  80146. }
  80147. divideScalar(a) {
  80148. return this.scale(1 / a);
  80149. }
  80150. clampScalar(min, max) {
  80151. for (let i = 0; i < this.ELEMENTS; ++i) {
  80152. this[i] = Math.min(Math.max(this[i], min), max);
  80153. }
  80154. return this.check();
  80155. }
  80156. multiplyByScalar(scalar) {
  80157. return this.scale(scalar);
  80158. }
  80159. get elements() {
  80160. return this;
  80161. }
  80162. check() {
  80163. if (config$2.debug && !this.validate()) {
  80164. throw new Error("math.gl: ".concat(this.constructor.name, " some fields set to invalid numbers'"));
  80165. }
  80166. return this;
  80167. }
  80168. validate() {
  80169. let valid = this.length === this.ELEMENTS;
  80170. for (let i = 0; i < this.ELEMENTS; ++i) {
  80171. valid = valid && Number.isFinite(this[i]);
  80172. }
  80173. return valid;
  80174. }
  80175. }
  80176. function validateVector(v, length) {
  80177. if (v.length !== length) {
  80178. return false;
  80179. }
  80180. for (let i = 0; i < v.length; ++i) {
  80181. if (!Number.isFinite(v[i])) {
  80182. return false;
  80183. }
  80184. }
  80185. return true;
  80186. }
  80187. function checkNumber(value) {
  80188. if (!Number.isFinite(value)) {
  80189. throw new Error("Invalid number ".concat(value));
  80190. }
  80191. return value;
  80192. }
  80193. function checkVector(v, length, callerName = '') {
  80194. if (config$2.debug && !validateVector(v, length)) {
  80195. throw new Error("math.gl: ".concat(callerName, " some fields set to invalid numbers'"));
  80196. }
  80197. return v;
  80198. }
  80199. const map = {};
  80200. function deprecated(method, version) {
  80201. if (!map[method]) {
  80202. map[method] = true;
  80203. console.warn("".concat(method, " has been removed in version ").concat(version, ", see upgrade guide for more information"));
  80204. }
  80205. }
  80206. class Vector extends MathArray {
  80207. get ELEMENTS() {
  80208. assert$4(false);
  80209. return 0;
  80210. }
  80211. copy(vector) {
  80212. assert$4(false);
  80213. return this;
  80214. }
  80215. get x() {
  80216. return this[0];
  80217. }
  80218. set x(value) {
  80219. this[0] = checkNumber(value);
  80220. }
  80221. get y() {
  80222. return this[1];
  80223. }
  80224. set y(value) {
  80225. this[1] = checkNumber(value);
  80226. }
  80227. len() {
  80228. return Math.sqrt(this.lengthSquared());
  80229. }
  80230. magnitude() {
  80231. return this.len();
  80232. }
  80233. lengthSquared() {
  80234. let length = 0;
  80235. for (let i = 0; i < this.ELEMENTS; ++i) {
  80236. length += this[i] * this[i];
  80237. }
  80238. return length;
  80239. }
  80240. magnitudeSquared() {
  80241. return this.lengthSquared();
  80242. }
  80243. distance(mathArray) {
  80244. return Math.sqrt(this.distanceSquared(mathArray));
  80245. }
  80246. distanceSquared(mathArray) {
  80247. let length = 0;
  80248. for (let i = 0; i < this.ELEMENTS; ++i) {
  80249. const dist = this[i] - mathArray[i];
  80250. length += dist * dist;
  80251. }
  80252. return checkNumber(length);
  80253. }
  80254. dot(mathArray) {
  80255. let product = 0;
  80256. for (let i = 0; i < this.ELEMENTS; ++i) {
  80257. product += this[i] * mathArray[i];
  80258. }
  80259. return checkNumber(product);
  80260. }
  80261. normalize() {
  80262. const length = this.magnitude();
  80263. if (length !== 0) {
  80264. for (let i = 0; i < this.ELEMENTS; ++i) {
  80265. this[i] /= length;
  80266. }
  80267. }
  80268. return this.check();
  80269. }
  80270. multiply(...vectors) {
  80271. for (const vector of vectors) {
  80272. for (let i = 0; i < this.ELEMENTS; ++i) {
  80273. this[i] *= vector[i];
  80274. }
  80275. }
  80276. return this.check();
  80277. }
  80278. divide(...vectors) {
  80279. for (const vector of vectors) {
  80280. for (let i = 0; i < this.ELEMENTS; ++i) {
  80281. this[i] /= vector[i];
  80282. }
  80283. }
  80284. return this.check();
  80285. }
  80286. lengthSq() {
  80287. return this.lengthSquared();
  80288. }
  80289. distanceTo(vector) {
  80290. return this.distance(vector);
  80291. }
  80292. distanceToSquared(vector) {
  80293. return this.distanceSquared(vector);
  80294. }
  80295. getComponent(i) {
  80296. assert$4(i >= 0 && i < this.ELEMENTS, 'index is out of range');
  80297. return checkNumber(this[i]);
  80298. }
  80299. setComponent(i, value) {
  80300. assert$4(i >= 0 && i < this.ELEMENTS, 'index is out of range');
  80301. this[i] = value;
  80302. return this.check();
  80303. }
  80304. addVectors(a, b) {
  80305. return this.copy(a).add(b);
  80306. }
  80307. subVectors(a, b) {
  80308. return this.copy(a).subtract(b);
  80309. }
  80310. multiplyVectors(a, b) {
  80311. return this.copy(a).multiply(b);
  80312. }
  80313. addScaledVector(a, b) {
  80314. return this.add(new this.constructor(a).multiplyScalar(b));
  80315. }
  80316. }
  80317. /**
  80318. * Common utilities
  80319. * @module glMatrix
  80320. */
  80321. // Configuration Constants
  80322. var EPSILON = 0.000001;
  80323. var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
  80324. if (!Math.hypot) Math.hypot = function () {
  80325. var y = 0,
  80326. i = arguments.length;
  80327. while (i--) {
  80328. y += arguments[i] * arguments[i];
  80329. }
  80330. return Math.sqrt(y);
  80331. };
  80332. /**
  80333. * 2 Dimensional Vector
  80334. * @module vec2
  80335. */
  80336. /**
  80337. * Creates a new, empty vec2
  80338. *
  80339. * @returns {vec2} a new 2D vector
  80340. */
  80341. function create$4() {
  80342. var out = new ARRAY_TYPE(2);
  80343. if (ARRAY_TYPE != Float32Array) {
  80344. out[0] = 0;
  80345. out[1] = 0;
  80346. }
  80347. return out;
  80348. }
  80349. /**
  80350. * Transforms the vec2 with a mat2
  80351. *
  80352. * @param {vec2} out the receiving vector
  80353. * @param {ReadonlyVec2} a the vector to transform
  80354. * @param {ReadonlyMat2} m matrix to transform with
  80355. * @returns {vec2} out
  80356. */
  80357. function transformMat2(out, a, m) {
  80358. var x = a[0],
  80359. y = a[1];
  80360. out[0] = m[0] * x + m[2] * y;
  80361. out[1] = m[1] * x + m[3] * y;
  80362. return out;
  80363. }
  80364. /**
  80365. * Transforms the vec2 with a mat2d
  80366. *
  80367. * @param {vec2} out the receiving vector
  80368. * @param {ReadonlyVec2} a the vector to transform
  80369. * @param {ReadonlyMat2d} m matrix to transform with
  80370. * @returns {vec2} out
  80371. */
  80372. function transformMat2d(out, a, m) {
  80373. var x = a[0],
  80374. y = a[1];
  80375. out[0] = m[0] * x + m[2] * y + m[4];
  80376. out[1] = m[1] * x + m[3] * y + m[5];
  80377. return out;
  80378. }
  80379. /**
  80380. * Transforms the vec2 with a mat3
  80381. * 3rd vector component is implicitly '1'
  80382. *
  80383. * @param {vec2} out the receiving vector
  80384. * @param {ReadonlyVec2} a the vector to transform
  80385. * @param {ReadonlyMat3} m matrix to transform with
  80386. * @returns {vec2} out
  80387. */
  80388. function transformMat3$1(out, a, m) {
  80389. var x = a[0],
  80390. y = a[1];
  80391. out[0] = m[0] * x + m[3] * y + m[6];
  80392. out[1] = m[1] * x + m[4] * y + m[7];
  80393. return out;
  80394. }
  80395. /**
  80396. * Transforms the vec2 with a mat4
  80397. * 3rd vector component is implicitly '0'
  80398. * 4th vector component is implicitly '1'
  80399. *
  80400. * @param {vec2} out the receiving vector
  80401. * @param {ReadonlyVec2} a the vector to transform
  80402. * @param {ReadonlyMat4} m matrix to transform with
  80403. * @returns {vec2} out
  80404. */
  80405. function transformMat4$2(out, a, m) {
  80406. var x = a[0];
  80407. var y = a[1];
  80408. out[0] = m[0] * x + m[4] * y + m[12];
  80409. out[1] = m[1] * x + m[5] * y + m[13];
  80410. return out;
  80411. }
  80412. /**
  80413. * Perform some operation over an array of vec2s.
  80414. *
  80415. * @param {Array} a the array of vectors to iterate over
  80416. * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
  80417. * @param {Number} offset Number of elements to skip at the beginning of the array
  80418. * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
  80419. * @param {Function} fn Function to call for each vector in the array
  80420. * @param {Object} [arg] additional argument to pass to fn
  80421. * @returns {Array} a
  80422. * @function
  80423. */
  80424. (function () {
  80425. var vec = create$4();
  80426. return function (a, stride, offset, count, fn, arg) {
  80427. var i, l;
  80428. if (!stride) {
  80429. stride = 2;
  80430. }
  80431. if (!offset) {
  80432. offset = 0;
  80433. }
  80434. if (count) {
  80435. l = Math.min(count * stride + offset, a.length);
  80436. } else {
  80437. l = a.length;
  80438. }
  80439. for (i = offset; i < l; i += stride) {
  80440. vec[0] = a[i];
  80441. vec[1] = a[i + 1];
  80442. fn(vec, vec, arg);
  80443. a[i] = vec[0];
  80444. a[i + 1] = vec[1];
  80445. }
  80446. return a;
  80447. };
  80448. })();
  80449. function vec2_transformMat4AsVector(out, a, m) {
  80450. const x = a[0];
  80451. const y = a[1];
  80452. const w = m[3] * x + m[7] * y || 1.0;
  80453. out[0] = (m[0] * x + m[4] * y) / w;
  80454. out[1] = (m[1] * x + m[5] * y) / w;
  80455. return out;
  80456. }
  80457. function vec3_transformMat4AsVector(out, a, m) {
  80458. const x = a[0];
  80459. const y = a[1];
  80460. const z = a[2];
  80461. const w = m[3] * x + m[7] * y + m[11] * z || 1.0;
  80462. out[0] = (m[0] * x + m[4] * y + m[8] * z) / w;
  80463. out[1] = (m[1] * x + m[5] * y + m[9] * z) / w;
  80464. out[2] = (m[2] * x + m[6] * y + m[10] * z) / w;
  80465. return out;
  80466. }
  80467. function vec3_transformMat2(out, a, m) {
  80468. const x = a[0];
  80469. const y = a[1];
  80470. out[0] = m[0] * x + m[2] * y;
  80471. out[1] = m[1] * x + m[3] * y;
  80472. out[2] = a[2];
  80473. return out;
  80474. }
  80475. function vec4_transformMat3(out, a, m) {
  80476. const x = a[0];
  80477. const y = a[1];
  80478. const z = a[2];
  80479. out[0] = m[0] * x + m[3] * y + m[6] * z;
  80480. out[1] = m[1] * x + m[4] * y + m[7] * z;
  80481. out[2] = m[2] * x + m[5] * y + m[8] * z;
  80482. out[3] = a[3];
  80483. return out;
  80484. }
  80485. class Vector2$1 extends Vector {
  80486. constructor(x = 0, y = 0) {
  80487. super(2);
  80488. if (isArray(x) && arguments.length === 1) {
  80489. this.copy(x);
  80490. } else {
  80491. if (config$2.debug) {
  80492. checkNumber(x);
  80493. checkNumber(y);
  80494. }
  80495. this[0] = x;
  80496. this[1] = y;
  80497. }
  80498. }
  80499. set(x, y) {
  80500. this[0] = x;
  80501. this[1] = y;
  80502. return this.check();
  80503. }
  80504. copy(array) {
  80505. this[0] = array[0];
  80506. this[1] = array[1];
  80507. return this.check();
  80508. }
  80509. fromObject(object) {
  80510. if (config$2.debug) {
  80511. checkNumber(object.x);
  80512. checkNumber(object.y);
  80513. }
  80514. this[0] = object.x;
  80515. this[1] = object.y;
  80516. return this.check();
  80517. }
  80518. toObject(object) {
  80519. object.x = this[0];
  80520. object.y = this[1];
  80521. return object;
  80522. }
  80523. get ELEMENTS() {
  80524. return 2;
  80525. }
  80526. horizontalAngle() {
  80527. return Math.atan2(this.y, this.x);
  80528. }
  80529. verticalAngle() {
  80530. return Math.atan2(this.x, this.y);
  80531. }
  80532. transform(matrix4) {
  80533. return this.transformAsPoint(matrix4);
  80534. }
  80535. transformAsPoint(matrix4) {
  80536. transformMat4$2(this, this, matrix4);
  80537. return this.check();
  80538. }
  80539. transformAsVector(matrix4) {
  80540. vec2_transformMat4AsVector(this, this, matrix4);
  80541. return this.check();
  80542. }
  80543. transformByMatrix3(matrix3) {
  80544. transformMat3$1(this, this, matrix3);
  80545. return this.check();
  80546. }
  80547. transformByMatrix2x3(matrix2x3) {
  80548. transformMat2d(this, this, matrix2x3);
  80549. return this.check();
  80550. }
  80551. transformByMatrix2(matrix2) {
  80552. transformMat2(this, this, matrix2);
  80553. return this.check();
  80554. }
  80555. }
  80556. /**
  80557. * 3 Dimensional Vector
  80558. * @module vec3
  80559. */
  80560. /**
  80561. * Creates a new, empty vec3
  80562. *
  80563. * @returns {vec3} a new 3D vector
  80564. */
  80565. function create$3() {
  80566. var out = new ARRAY_TYPE(3);
  80567. if (ARRAY_TYPE != Float32Array) {
  80568. out[0] = 0;
  80569. out[1] = 0;
  80570. out[2] = 0;
  80571. }
  80572. return out;
  80573. }
  80574. /**
  80575. * Calculates the length of a vec3
  80576. *
  80577. * @param {ReadonlyVec3} a vector to calculate length of
  80578. * @returns {Number} length of a
  80579. */
  80580. function length$2(a) {
  80581. var x = a[0];
  80582. var y = a[1];
  80583. var z = a[2];
  80584. return Math.hypot(x, y, z);
  80585. }
  80586. /**
  80587. * Creates a new vec3 initialized with the given values
  80588. *
  80589. * @param {Number} x X component
  80590. * @param {Number} y Y component
  80591. * @param {Number} z Z component
  80592. * @returns {vec3} a new 3D vector
  80593. */
  80594. function fromValues(x, y, z) {
  80595. var out = new ARRAY_TYPE(3);
  80596. out[0] = x;
  80597. out[1] = y;
  80598. out[2] = z;
  80599. return out;
  80600. }
  80601. /**
  80602. * Normalize a vec3
  80603. *
  80604. * @param {vec3} out the receiving vector
  80605. * @param {ReadonlyVec3} a vector to normalize
  80606. * @returns {vec3} out
  80607. */
  80608. function normalize$2(out, a) {
  80609. var x = a[0];
  80610. var y = a[1];
  80611. var z = a[2];
  80612. var len = x * x + y * y + z * z;
  80613. if (len > 0) {
  80614. //TODO: evaluate use of glm_invsqrt here?
  80615. len = 1 / Math.sqrt(len);
  80616. }
  80617. out[0] = a[0] * len;
  80618. out[1] = a[1] * len;
  80619. out[2] = a[2] * len;
  80620. return out;
  80621. }
  80622. /**
  80623. * Calculates the dot product of two vec3's
  80624. *
  80625. * @param {ReadonlyVec3} a the first operand
  80626. * @param {ReadonlyVec3} b the second operand
  80627. * @returns {Number} dot product of a and b
  80628. */
  80629. function dot$2(a, b) {
  80630. return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
  80631. }
  80632. /**
  80633. * Computes the cross product of two vec3's
  80634. *
  80635. * @param {vec3} out the receiving vector
  80636. * @param {ReadonlyVec3} a the first operand
  80637. * @param {ReadonlyVec3} b the second operand
  80638. * @returns {vec3} out
  80639. */
  80640. function cross(out, a, b) {
  80641. var ax = a[0],
  80642. ay = a[1],
  80643. az = a[2];
  80644. var bx = b[0],
  80645. by = b[1],
  80646. bz = b[2];
  80647. out[0] = ay * bz - az * by;
  80648. out[1] = az * bx - ax * bz;
  80649. out[2] = ax * by - ay * bx;
  80650. return out;
  80651. }
  80652. /**
  80653. * Transforms the vec3 with a mat4.
  80654. * 4th vector component is implicitly '1'
  80655. *
  80656. * @param {vec3} out the receiving vector
  80657. * @param {ReadonlyVec3} a the vector to transform
  80658. * @param {ReadonlyMat4} m matrix to transform with
  80659. * @returns {vec3} out
  80660. */
  80661. function transformMat4$1(out, a, m) {
  80662. var x = a[0],
  80663. y = a[1],
  80664. z = a[2];
  80665. var w = m[3] * x + m[7] * y + m[11] * z + m[15];
  80666. w = w || 1.0;
  80667. out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
  80668. out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
  80669. out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
  80670. return out;
  80671. }
  80672. /**
  80673. * Transforms the vec3 with a mat3.
  80674. *
  80675. * @param {vec3} out the receiving vector
  80676. * @param {ReadonlyVec3} a the vector to transform
  80677. * @param {ReadonlyMat3} m the 3x3 matrix to transform with
  80678. * @returns {vec3} out
  80679. */
  80680. function transformMat3(out, a, m) {
  80681. var x = a[0],
  80682. y = a[1],
  80683. z = a[2];
  80684. out[0] = x * m[0] + y * m[3] + z * m[6];
  80685. out[1] = x * m[1] + y * m[4] + z * m[7];
  80686. out[2] = x * m[2] + y * m[5] + z * m[8];
  80687. return out;
  80688. }
  80689. /**
  80690. * Transforms the vec3 with a quat
  80691. * Can also be used for dual quaternions. (Multiply it with the real part)
  80692. *
  80693. * @param {vec3} out the receiving vector
  80694. * @param {ReadonlyVec3} a the vector to transform
  80695. * @param {ReadonlyQuat} q quaternion to transform with
  80696. * @returns {vec3} out
  80697. */
  80698. function transformQuat$1(out, a, q) {
  80699. // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed
  80700. var qx = q[0],
  80701. qy = q[1],
  80702. qz = q[2],
  80703. qw = q[3];
  80704. var x = a[0],
  80705. y = a[1],
  80706. z = a[2]; // var qvec = [qx, qy, qz];
  80707. // var uv = vec3.cross([], qvec, a);
  80708. var uvx = qy * z - qz * y,
  80709. uvy = qz * x - qx * z,
  80710. uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);
  80711. var uuvx = qy * uvz - qz * uvy,
  80712. uuvy = qz * uvx - qx * uvz,
  80713. uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);
  80714. var w2 = qw * 2;
  80715. uvx *= w2;
  80716. uvy *= w2;
  80717. uvz *= w2; // vec3.scale(uuv, uuv, 2);
  80718. uuvx *= 2;
  80719. uuvy *= 2;
  80720. uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));
  80721. out[0] = x + uvx + uuvx;
  80722. out[1] = y + uvy + uuvy;
  80723. out[2] = z + uvz + uuvz;
  80724. return out;
  80725. }
  80726. /**
  80727. * Rotate a 3D vector around the x-axis
  80728. * @param {vec3} out The receiving vec3
  80729. * @param {ReadonlyVec3} a The vec3 point to rotate
  80730. * @param {ReadonlyVec3} b The origin of the rotation
  80731. * @param {Number} rad The angle of rotation in radians
  80732. * @returns {vec3} out
  80733. */
  80734. function rotateX$2(out, a, b, rad) {
  80735. var p = [],
  80736. r = []; //Translate point to the origin
  80737. p[0] = a[0] - b[0];
  80738. p[1] = a[1] - b[1];
  80739. p[2] = a[2] - b[2]; //perform rotation
  80740. r[0] = p[0];
  80741. r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);
  80742. r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad); //translate to correct position
  80743. out[0] = r[0] + b[0];
  80744. out[1] = r[1] + b[1];
  80745. out[2] = r[2] + b[2];
  80746. return out;
  80747. }
  80748. /**
  80749. * Rotate a 3D vector around the y-axis
  80750. * @param {vec3} out The receiving vec3
  80751. * @param {ReadonlyVec3} a The vec3 point to rotate
  80752. * @param {ReadonlyVec3} b The origin of the rotation
  80753. * @param {Number} rad The angle of rotation in radians
  80754. * @returns {vec3} out
  80755. */
  80756. function rotateY$2(out, a, b, rad) {
  80757. var p = [],
  80758. r = []; //Translate point to the origin
  80759. p[0] = a[0] - b[0];
  80760. p[1] = a[1] - b[1];
  80761. p[2] = a[2] - b[2]; //perform rotation
  80762. r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);
  80763. r[1] = p[1];
  80764. r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad); //translate to correct position
  80765. out[0] = r[0] + b[0];
  80766. out[1] = r[1] + b[1];
  80767. out[2] = r[2] + b[2];
  80768. return out;
  80769. }
  80770. /**
  80771. * Rotate a 3D vector around the z-axis
  80772. * @param {vec3} out The receiving vec3
  80773. * @param {ReadonlyVec3} a The vec3 point to rotate
  80774. * @param {ReadonlyVec3} b The origin of the rotation
  80775. * @param {Number} rad The angle of rotation in radians
  80776. * @returns {vec3} out
  80777. */
  80778. function rotateZ$2(out, a, b, rad) {
  80779. var p = [],
  80780. r = []; //Translate point to the origin
  80781. p[0] = a[0] - b[0];
  80782. p[1] = a[1] - b[1];
  80783. p[2] = a[2] - b[2]; //perform rotation
  80784. r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);
  80785. r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);
  80786. r[2] = p[2]; //translate to correct position
  80787. out[0] = r[0] + b[0];
  80788. out[1] = r[1] + b[1];
  80789. out[2] = r[2] + b[2];
  80790. return out;
  80791. }
  80792. /**
  80793. * Get the angle between two 3D vectors
  80794. * @param {ReadonlyVec3} a The first operand
  80795. * @param {ReadonlyVec3} b The second operand
  80796. * @returns {Number} The angle in radians
  80797. */
  80798. function angle$1(a, b) {
  80799. var ax = a[0],
  80800. ay = a[1],
  80801. az = a[2],
  80802. bx = b[0],
  80803. by = b[1],
  80804. bz = b[2],
  80805. mag1 = Math.sqrt(ax * ax + ay * ay + az * az),
  80806. mag2 = Math.sqrt(bx * bx + by * by + bz * bz),
  80807. mag = mag1 * mag2,
  80808. cosine = mag && dot$2(a, b) / mag;
  80809. return Math.acos(Math.min(Math.max(cosine, -1), 1));
  80810. }
  80811. /**
  80812. * Alias for {@link vec3.length}
  80813. * @function
  80814. */
  80815. var len = length$2;
  80816. /**
  80817. * Perform some operation over an array of vec3s.
  80818. *
  80819. * @param {Array} a the array of vectors to iterate over
  80820. * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
  80821. * @param {Number} offset Number of elements to skip at the beginning of the array
  80822. * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
  80823. * @param {Function} fn Function to call for each vector in the array
  80824. * @param {Object} [arg] additional argument to pass to fn
  80825. * @returns {Array} a
  80826. * @function
  80827. */
  80828. (function () {
  80829. var vec = create$3();
  80830. return function (a, stride, offset, count, fn, arg) {
  80831. var i, l;
  80832. if (!stride) {
  80833. stride = 3;
  80834. }
  80835. if (!offset) {
  80836. offset = 0;
  80837. }
  80838. if (count) {
  80839. l = Math.min(count * stride + offset, a.length);
  80840. } else {
  80841. l = a.length;
  80842. }
  80843. for (i = offset; i < l; i += stride) {
  80844. vec[0] = a[i];
  80845. vec[1] = a[i + 1];
  80846. vec[2] = a[i + 2];
  80847. fn(vec, vec, arg);
  80848. a[i] = vec[0];
  80849. a[i + 1] = vec[1];
  80850. a[i + 2] = vec[2];
  80851. }
  80852. return a;
  80853. };
  80854. })();
  80855. const ORIGIN = [0, 0, 0];
  80856. const constants$2 = {};
  80857. class Vector3$1 extends Vector {
  80858. static get ZERO() {
  80859. return constants$2.ZERO = constants$2.ZERO || Object.freeze(new Vector3$1(0, 0, 0, 0));
  80860. }
  80861. constructor(x = 0, y = 0, z = 0) {
  80862. super(-0, -0, -0);
  80863. if (arguments.length === 1 && isArray(x)) {
  80864. this.copy(x);
  80865. } else {
  80866. if (config$2.debug) {
  80867. checkNumber(x);
  80868. checkNumber(y);
  80869. checkNumber(z);
  80870. }
  80871. this[0] = x;
  80872. this[1] = y;
  80873. this[2] = z;
  80874. }
  80875. }
  80876. set(x, y, z) {
  80877. this[0] = x;
  80878. this[1] = y;
  80879. this[2] = z;
  80880. return this.check();
  80881. }
  80882. copy(array) {
  80883. this[0] = array[0];
  80884. this[1] = array[1];
  80885. this[2] = array[2];
  80886. return this.check();
  80887. }
  80888. fromObject(object) {
  80889. if (config$2.debug) {
  80890. checkNumber(object.x);
  80891. checkNumber(object.y);
  80892. checkNumber(object.z);
  80893. }
  80894. this[0] = object.x;
  80895. this[1] = object.y;
  80896. this[2] = object.z;
  80897. return this.check();
  80898. }
  80899. toObject(object) {
  80900. object.x = this[0];
  80901. object.y = this[1];
  80902. object.z = this[2];
  80903. return object;
  80904. }
  80905. get ELEMENTS() {
  80906. return 3;
  80907. }
  80908. get z() {
  80909. return this[2];
  80910. }
  80911. set z(value) {
  80912. this[2] = checkNumber(value);
  80913. }
  80914. angle(vector) {
  80915. return angle$1(this, vector);
  80916. }
  80917. cross(vector) {
  80918. cross(this, this, vector);
  80919. return this.check();
  80920. }
  80921. rotateX({
  80922. radians,
  80923. origin = ORIGIN
  80924. }) {
  80925. rotateX$2(this, this, origin, radians);
  80926. return this.check();
  80927. }
  80928. rotateY({
  80929. radians,
  80930. origin = ORIGIN
  80931. }) {
  80932. rotateY$2(this, this, origin, radians);
  80933. return this.check();
  80934. }
  80935. rotateZ({
  80936. radians,
  80937. origin = ORIGIN
  80938. }) {
  80939. rotateZ$2(this, this, origin, radians);
  80940. return this.check();
  80941. }
  80942. transform(matrix4) {
  80943. return this.transformAsPoint(matrix4);
  80944. }
  80945. transformAsPoint(matrix4) {
  80946. transformMat4$1(this, this, matrix4);
  80947. return this.check();
  80948. }
  80949. transformAsVector(matrix4) {
  80950. vec3_transformMat4AsVector(this, this, matrix4);
  80951. return this.check();
  80952. }
  80953. transformByMatrix3(matrix3) {
  80954. transformMat3(this, this, matrix3);
  80955. return this.check();
  80956. }
  80957. transformByMatrix2(matrix2) {
  80958. vec3_transformMat2(this, this, matrix2);
  80959. return this.check();
  80960. }
  80961. transformByQuaternion(quaternion) {
  80962. transformQuat$1(this, this, quaternion);
  80963. return this.check();
  80964. }
  80965. }
  80966. class Matrix extends MathArray {
  80967. get ELEMENTS() {
  80968. assert$4(false);
  80969. return 0;
  80970. }
  80971. get RANK() {
  80972. assert$4(false);
  80973. return 0;
  80974. }
  80975. toString() {
  80976. let string = '[';
  80977. if (config$2.printRowMajor) {
  80978. string += 'row-major:';
  80979. for (let row = 0; row < this.RANK; ++row) {
  80980. for (let col = 0; col < this.RANK; ++col) {
  80981. string += " ".concat(this[col * this.RANK + row]);
  80982. }
  80983. }
  80984. } else {
  80985. string += 'column-major:';
  80986. for (let i = 0; i < this.ELEMENTS; ++i) {
  80987. string += " ".concat(this[i]);
  80988. }
  80989. }
  80990. string += ']';
  80991. return string;
  80992. }
  80993. getElementIndex(row, col) {
  80994. return col * this.RANK + row;
  80995. }
  80996. getElement(row, col) {
  80997. return this[col * this.RANK + row];
  80998. }
  80999. setElement(row, col, value) {
  81000. this[col * this.RANK + row] = checkNumber(value);
  81001. return this;
  81002. }
  81003. getColumn(columnIndex, result = new Array(this.RANK).fill(-0)) {
  81004. const firstIndex = columnIndex * this.RANK;
  81005. for (let i = 0; i < this.RANK; ++i) {
  81006. result[i] = this[firstIndex + i];
  81007. }
  81008. return result;
  81009. }
  81010. setColumn(columnIndex, columnVector) {
  81011. const firstIndex = columnIndex * this.RANK;
  81012. for (let i = 0; i < this.RANK; ++i) {
  81013. this[firstIndex + i] = columnVector[i];
  81014. }
  81015. return this;
  81016. }
  81017. }
  81018. /**
  81019. * 3x3 Matrix
  81020. * @module mat3
  81021. */
  81022. /**
  81023. * Creates a new identity mat3
  81024. *
  81025. * @returns {mat3} a new 3x3 matrix
  81026. */
  81027. function create$2() {
  81028. var out = new ARRAY_TYPE(9);
  81029. if (ARRAY_TYPE != Float32Array) {
  81030. out[1] = 0;
  81031. out[2] = 0;
  81032. out[3] = 0;
  81033. out[5] = 0;
  81034. out[6] = 0;
  81035. out[7] = 0;
  81036. }
  81037. out[0] = 1;
  81038. out[4] = 1;
  81039. out[8] = 1;
  81040. return out;
  81041. }
  81042. /**
  81043. * Transpose the values of a mat3
  81044. *
  81045. * @param {mat3} out the receiving matrix
  81046. * @param {ReadonlyMat3} a the source matrix
  81047. * @returns {mat3} out
  81048. */
  81049. function transpose$1(out, a) {
  81050. // If we are transposing ourselves we can skip a few steps but have to cache some values
  81051. if (out === a) {
  81052. var a01 = a[1],
  81053. a02 = a[2],
  81054. a12 = a[5];
  81055. out[1] = a[3];
  81056. out[2] = a[6];
  81057. out[3] = a01;
  81058. out[5] = a[7];
  81059. out[6] = a02;
  81060. out[7] = a12;
  81061. } else {
  81062. out[0] = a[0];
  81063. out[1] = a[3];
  81064. out[2] = a[6];
  81065. out[3] = a[1];
  81066. out[4] = a[4];
  81067. out[5] = a[7];
  81068. out[6] = a[2];
  81069. out[7] = a[5];
  81070. out[8] = a[8];
  81071. }
  81072. return out;
  81073. }
  81074. /**
  81075. * Inverts a mat3
  81076. *
  81077. * @param {mat3} out the receiving matrix
  81078. * @param {ReadonlyMat3} a the source matrix
  81079. * @returns {mat3} out
  81080. */
  81081. function invert$2(out, a) {
  81082. var a00 = a[0],
  81083. a01 = a[1],
  81084. a02 = a[2];
  81085. var a10 = a[3],
  81086. a11 = a[4],
  81087. a12 = a[5];
  81088. var a20 = a[6],
  81089. a21 = a[7],
  81090. a22 = a[8];
  81091. var b01 = a22 * a11 - a12 * a21;
  81092. var b11 = -a22 * a10 + a12 * a20;
  81093. var b21 = a21 * a10 - a11 * a20; // Calculate the determinant
  81094. var det = a00 * b01 + a01 * b11 + a02 * b21;
  81095. if (!det) {
  81096. return null;
  81097. }
  81098. det = 1.0 / det;
  81099. out[0] = b01 * det;
  81100. out[1] = (-a22 * a01 + a02 * a21) * det;
  81101. out[2] = (a12 * a01 - a02 * a11) * det;
  81102. out[3] = b11 * det;
  81103. out[4] = (a22 * a00 - a02 * a20) * det;
  81104. out[5] = (-a12 * a00 + a02 * a10) * det;
  81105. out[6] = b21 * det;
  81106. out[7] = (-a21 * a00 + a01 * a20) * det;
  81107. out[8] = (a11 * a00 - a01 * a10) * det;
  81108. return out;
  81109. }
  81110. /**
  81111. * Calculates the determinant of a mat3
  81112. *
  81113. * @param {ReadonlyMat3} a the source matrix
  81114. * @returns {Number} determinant of a
  81115. */
  81116. function determinant$1(a) {
  81117. var a00 = a[0],
  81118. a01 = a[1],
  81119. a02 = a[2];
  81120. var a10 = a[3],
  81121. a11 = a[4],
  81122. a12 = a[5];
  81123. var a20 = a[6],
  81124. a21 = a[7],
  81125. a22 = a[8];
  81126. return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
  81127. }
  81128. /**
  81129. * Multiplies two mat3's
  81130. *
  81131. * @param {mat3} out the receiving matrix
  81132. * @param {ReadonlyMat3} a the first operand
  81133. * @param {ReadonlyMat3} b the second operand
  81134. * @returns {mat3} out
  81135. */
  81136. function multiply$2(out, a, b) {
  81137. var a00 = a[0],
  81138. a01 = a[1],
  81139. a02 = a[2];
  81140. var a10 = a[3],
  81141. a11 = a[4],
  81142. a12 = a[5];
  81143. var a20 = a[6],
  81144. a21 = a[7],
  81145. a22 = a[8];
  81146. var b00 = b[0],
  81147. b01 = b[1],
  81148. b02 = b[2];
  81149. var b10 = b[3],
  81150. b11 = b[4],
  81151. b12 = b[5];
  81152. var b20 = b[6],
  81153. b21 = b[7],
  81154. b22 = b[8];
  81155. out[0] = b00 * a00 + b01 * a10 + b02 * a20;
  81156. out[1] = b00 * a01 + b01 * a11 + b02 * a21;
  81157. out[2] = b00 * a02 + b01 * a12 + b02 * a22;
  81158. out[3] = b10 * a00 + b11 * a10 + b12 * a20;
  81159. out[4] = b10 * a01 + b11 * a11 + b12 * a21;
  81160. out[5] = b10 * a02 + b11 * a12 + b12 * a22;
  81161. out[6] = b20 * a00 + b21 * a10 + b22 * a20;
  81162. out[7] = b20 * a01 + b21 * a11 + b22 * a21;
  81163. out[8] = b20 * a02 + b21 * a12 + b22 * a22;
  81164. return out;
  81165. }
  81166. /**
  81167. * Translate a mat3 by the given vector
  81168. *
  81169. * @param {mat3} out the receiving matrix
  81170. * @param {ReadonlyMat3} a the matrix to translate
  81171. * @param {ReadonlyVec2} v vector to translate by
  81172. * @returns {mat3} out
  81173. */
  81174. function translate$1(out, a, v) {
  81175. var a00 = a[0],
  81176. a01 = a[1],
  81177. a02 = a[2],
  81178. a10 = a[3],
  81179. a11 = a[4],
  81180. a12 = a[5],
  81181. a20 = a[6],
  81182. a21 = a[7],
  81183. a22 = a[8],
  81184. x = v[0],
  81185. y = v[1];
  81186. out[0] = a00;
  81187. out[1] = a01;
  81188. out[2] = a02;
  81189. out[3] = a10;
  81190. out[4] = a11;
  81191. out[5] = a12;
  81192. out[6] = x * a00 + y * a10 + a20;
  81193. out[7] = x * a01 + y * a11 + a21;
  81194. out[8] = x * a02 + y * a12 + a22;
  81195. return out;
  81196. }
  81197. /**
  81198. * Rotates a mat3 by the given angle
  81199. *
  81200. * @param {mat3} out the receiving matrix
  81201. * @param {ReadonlyMat3} a the matrix to rotate
  81202. * @param {Number} rad the angle to rotate the matrix by
  81203. * @returns {mat3} out
  81204. */
  81205. function rotate$1(out, a, rad) {
  81206. var a00 = a[0],
  81207. a01 = a[1],
  81208. a02 = a[2],
  81209. a10 = a[3],
  81210. a11 = a[4],
  81211. a12 = a[5],
  81212. a20 = a[6],
  81213. a21 = a[7],
  81214. a22 = a[8],
  81215. s = Math.sin(rad),
  81216. c = Math.cos(rad);
  81217. out[0] = c * a00 + s * a10;
  81218. out[1] = c * a01 + s * a11;
  81219. out[2] = c * a02 + s * a12;
  81220. out[3] = c * a10 - s * a00;
  81221. out[4] = c * a11 - s * a01;
  81222. out[5] = c * a12 - s * a02;
  81223. out[6] = a20;
  81224. out[7] = a21;
  81225. out[8] = a22;
  81226. return out;
  81227. }
  81228. /**
  81229. * Scales the mat3 by the dimensions in the given vec2
  81230. *
  81231. * @param {mat3} out the receiving matrix
  81232. * @param {ReadonlyMat3} a the matrix to rotate
  81233. * @param {ReadonlyVec2} v the vec2 to scale the matrix by
  81234. * @returns {mat3} out
  81235. **/
  81236. function scale$3(out, a, v) {
  81237. var x = v[0],
  81238. y = v[1];
  81239. out[0] = x * a[0];
  81240. out[1] = x * a[1];
  81241. out[2] = x * a[2];
  81242. out[3] = y * a[3];
  81243. out[4] = y * a[4];
  81244. out[5] = y * a[5];
  81245. out[6] = a[6];
  81246. out[7] = a[7];
  81247. out[8] = a[8];
  81248. return out;
  81249. }
  81250. /**
  81251. * Calculates a 3x3 matrix from the given quaternion
  81252. *
  81253. * @param {mat3} out mat3 receiving operation result
  81254. * @param {ReadonlyQuat} q Quaternion to create matrix from
  81255. *
  81256. * @returns {mat3} out
  81257. */
  81258. function fromQuat$1(out, q) {
  81259. var x = q[0],
  81260. y = q[1],
  81261. z = q[2],
  81262. w = q[3];
  81263. var x2 = x + x;
  81264. var y2 = y + y;
  81265. var z2 = z + z;
  81266. var xx = x * x2;
  81267. var yx = y * x2;
  81268. var yy = y * y2;
  81269. var zx = z * x2;
  81270. var zy = z * y2;
  81271. var zz = z * z2;
  81272. var wx = w * x2;
  81273. var wy = w * y2;
  81274. var wz = w * z2;
  81275. out[0] = 1 - yy - zz;
  81276. out[3] = yx - wz;
  81277. out[6] = zx + wy;
  81278. out[1] = yx + wz;
  81279. out[4] = 1 - xx - zz;
  81280. out[7] = zy - wx;
  81281. out[2] = zx - wy;
  81282. out[5] = zy + wx;
  81283. out[8] = 1 - xx - yy;
  81284. return out;
  81285. }
  81286. const IDENTITY$1 = Object.freeze([1, 0, 0, 0, 1, 0, 0, 0, 1]);
  81287. const ZERO$1 = Object.freeze([0, 0, 0, 0, 0, 0, 0, 0, 0]);
  81288. const INDICES$1 = Object.freeze({
  81289. COL0ROW0: 0,
  81290. COL0ROW1: 1,
  81291. COL0ROW2: 2,
  81292. COL1ROW0: 3,
  81293. COL1ROW1: 4,
  81294. COL1ROW2: 5,
  81295. COL2ROW0: 6,
  81296. COL2ROW1: 7,
  81297. COL2ROW2: 8
  81298. });
  81299. const constants$1 = {};
  81300. class Matrix3$1 extends Matrix {
  81301. static get IDENTITY() {
  81302. constants$1.IDENTITY = constants$1.IDENTITY || Object.freeze(new Matrix3$1(IDENTITY$1));
  81303. return constants$1.IDENTITY;
  81304. }
  81305. static get ZERO() {
  81306. constants$1.ZERO = constants$1.ZERO || Object.freeze(new Matrix3$1(ZERO$1));
  81307. return constants$1.ZERO;
  81308. }
  81309. get ELEMENTS() {
  81310. return 9;
  81311. }
  81312. get RANK() {
  81313. return 3;
  81314. }
  81315. get INDICES() {
  81316. return INDICES$1;
  81317. }
  81318. constructor(array) {
  81319. super(-0, -0, -0, -0, -0, -0, -0, -0, -0);
  81320. if (arguments.length === 1 && Array.isArray(array)) {
  81321. this.copy(array);
  81322. } else {
  81323. this.identity();
  81324. }
  81325. }
  81326. copy(array) {
  81327. this[0] = array[0];
  81328. this[1] = array[1];
  81329. this[2] = array[2];
  81330. this[3] = array[3];
  81331. this[4] = array[4];
  81332. this[5] = array[5];
  81333. this[6] = array[6];
  81334. this[7] = array[7];
  81335. this[8] = array[8];
  81336. return this.check();
  81337. }
  81338. set(m00, m10, m20, m01, m11, m21, m02, m12, m22) {
  81339. this[0] = m00;
  81340. this[1] = m10;
  81341. this[2] = m20;
  81342. this[3] = m01;
  81343. this[4] = m11;
  81344. this[5] = m21;
  81345. this[6] = m02;
  81346. this[7] = m12;
  81347. this[8] = m22;
  81348. return this.check();
  81349. }
  81350. setRowMajor(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
  81351. this[0] = m00;
  81352. this[1] = m10;
  81353. this[2] = m20;
  81354. this[3] = m01;
  81355. this[4] = m11;
  81356. this[5] = m21;
  81357. this[6] = m02;
  81358. this[7] = m12;
  81359. this[8] = m22;
  81360. return this.check();
  81361. }
  81362. determinant() {
  81363. return determinant$1(this);
  81364. }
  81365. identity() {
  81366. return this.copy(IDENTITY$1);
  81367. }
  81368. fromQuaternion(q) {
  81369. fromQuat$1(this, q);
  81370. return this.check();
  81371. }
  81372. transpose() {
  81373. transpose$1(this, this);
  81374. return this.check();
  81375. }
  81376. invert() {
  81377. invert$2(this, this);
  81378. return this.check();
  81379. }
  81380. multiplyLeft(a) {
  81381. multiply$2(this, a, this);
  81382. return this.check();
  81383. }
  81384. multiplyRight(a) {
  81385. multiply$2(this, this, a);
  81386. return this.check();
  81387. }
  81388. rotate(radians) {
  81389. rotate$1(this, this, radians);
  81390. return this.check();
  81391. }
  81392. scale(factor) {
  81393. if (Array.isArray(factor)) {
  81394. scale$3(this, this, factor);
  81395. } else {
  81396. scale$3(this, this, [factor, factor, factor]);
  81397. }
  81398. return this.check();
  81399. }
  81400. translate(vec) {
  81401. translate$1(this, this, vec);
  81402. return this.check();
  81403. }
  81404. transform(vector, result) {
  81405. switch (vector.length) {
  81406. case 2:
  81407. result = transformMat3$1(result || [-0, -0], vector, this);
  81408. break;
  81409. case 3:
  81410. result = transformMat3(result || [-0, -0, -0], vector, this);
  81411. break;
  81412. case 4:
  81413. result = vec4_transformMat3(result || [-0, -0, -0, -0], vector, this);
  81414. break;
  81415. default:
  81416. throw new Error('Illegal vector');
  81417. }
  81418. checkVector(result, vector.length);
  81419. return result;
  81420. }
  81421. transformVector(vector, result) {
  81422. deprecated('Matrix3.transformVector');
  81423. return this.transform(vector, result);
  81424. }
  81425. transformVector2(vector, result) {
  81426. deprecated('Matrix3.transformVector');
  81427. return this.transform(vector, result);
  81428. }
  81429. transformVector3(vector, result) {
  81430. deprecated('Matrix3.transformVector');
  81431. return this.transform(vector, result);
  81432. }
  81433. }
  81434. /**
  81435. * Set a mat4 to the identity matrix
  81436. *
  81437. * @param {mat4} out the receiving matrix
  81438. * @returns {mat4} out
  81439. */
  81440. function identity$1(out) {
  81441. out[0] = 1;
  81442. out[1] = 0;
  81443. out[2] = 0;
  81444. out[3] = 0;
  81445. out[4] = 0;
  81446. out[5] = 1;
  81447. out[6] = 0;
  81448. out[7] = 0;
  81449. out[8] = 0;
  81450. out[9] = 0;
  81451. out[10] = 1;
  81452. out[11] = 0;
  81453. out[12] = 0;
  81454. out[13] = 0;
  81455. out[14] = 0;
  81456. out[15] = 1;
  81457. return out;
  81458. }
  81459. /**
  81460. * Transpose the values of a mat4
  81461. *
  81462. * @param {mat4} out the receiving matrix
  81463. * @param {ReadonlyMat4} a the source matrix
  81464. * @returns {mat4} out
  81465. */
  81466. function transpose(out, a) {
  81467. // If we are transposing ourselves we can skip a few steps but have to cache some values
  81468. if (out === a) {
  81469. var a01 = a[1],
  81470. a02 = a[2],
  81471. a03 = a[3];
  81472. var a12 = a[6],
  81473. a13 = a[7];
  81474. var a23 = a[11];
  81475. out[1] = a[4];
  81476. out[2] = a[8];
  81477. out[3] = a[12];
  81478. out[4] = a01;
  81479. out[6] = a[9];
  81480. out[7] = a[13];
  81481. out[8] = a02;
  81482. out[9] = a12;
  81483. out[11] = a[14];
  81484. out[12] = a03;
  81485. out[13] = a13;
  81486. out[14] = a23;
  81487. } else {
  81488. out[0] = a[0];
  81489. out[1] = a[4];
  81490. out[2] = a[8];
  81491. out[3] = a[12];
  81492. out[4] = a[1];
  81493. out[5] = a[5];
  81494. out[6] = a[9];
  81495. out[7] = a[13];
  81496. out[8] = a[2];
  81497. out[9] = a[6];
  81498. out[10] = a[10];
  81499. out[11] = a[14];
  81500. out[12] = a[3];
  81501. out[13] = a[7];
  81502. out[14] = a[11];
  81503. out[15] = a[15];
  81504. }
  81505. return out;
  81506. }
  81507. /**
  81508. * Inverts a mat4
  81509. *
  81510. * @param {mat4} out the receiving matrix
  81511. * @param {ReadonlyMat4} a the source matrix
  81512. * @returns {mat4} out
  81513. */
  81514. function invert$1(out, a) {
  81515. var a00 = a[0],
  81516. a01 = a[1],
  81517. a02 = a[2],
  81518. a03 = a[3];
  81519. var a10 = a[4],
  81520. a11 = a[5],
  81521. a12 = a[6],
  81522. a13 = a[7];
  81523. var a20 = a[8],
  81524. a21 = a[9],
  81525. a22 = a[10],
  81526. a23 = a[11];
  81527. var a30 = a[12],
  81528. a31 = a[13],
  81529. a32 = a[14],
  81530. a33 = a[15];
  81531. var b00 = a00 * a11 - a01 * a10;
  81532. var b01 = a00 * a12 - a02 * a10;
  81533. var b02 = a00 * a13 - a03 * a10;
  81534. var b03 = a01 * a12 - a02 * a11;
  81535. var b04 = a01 * a13 - a03 * a11;
  81536. var b05 = a02 * a13 - a03 * a12;
  81537. var b06 = a20 * a31 - a21 * a30;
  81538. var b07 = a20 * a32 - a22 * a30;
  81539. var b08 = a20 * a33 - a23 * a30;
  81540. var b09 = a21 * a32 - a22 * a31;
  81541. var b10 = a21 * a33 - a23 * a31;
  81542. var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
  81543. var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  81544. if (!det) {
  81545. return null;
  81546. }
  81547. det = 1.0 / det;
  81548. out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
  81549. out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
  81550. out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
  81551. out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
  81552. out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
  81553. out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
  81554. out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
  81555. out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
  81556. out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
  81557. out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
  81558. out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
  81559. out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
  81560. out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
  81561. out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
  81562. out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
  81563. out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  81564. return out;
  81565. }
  81566. /**
  81567. * Calculates the determinant of a mat4
  81568. *
  81569. * @param {ReadonlyMat4} a the source matrix
  81570. * @returns {Number} determinant of a
  81571. */
  81572. function determinant(a) {
  81573. var a00 = a[0],
  81574. a01 = a[1],
  81575. a02 = a[2],
  81576. a03 = a[3];
  81577. var a10 = a[4],
  81578. a11 = a[5],
  81579. a12 = a[6],
  81580. a13 = a[7];
  81581. var a20 = a[8],
  81582. a21 = a[9],
  81583. a22 = a[10],
  81584. a23 = a[11];
  81585. var a30 = a[12],
  81586. a31 = a[13],
  81587. a32 = a[14],
  81588. a33 = a[15];
  81589. var b00 = a00 * a11 - a01 * a10;
  81590. var b01 = a00 * a12 - a02 * a10;
  81591. var b02 = a00 * a13 - a03 * a10;
  81592. var b03 = a01 * a12 - a02 * a11;
  81593. var b04 = a01 * a13 - a03 * a11;
  81594. var b05 = a02 * a13 - a03 * a12;
  81595. var b06 = a20 * a31 - a21 * a30;
  81596. var b07 = a20 * a32 - a22 * a30;
  81597. var b08 = a20 * a33 - a23 * a30;
  81598. var b09 = a21 * a32 - a22 * a31;
  81599. var b10 = a21 * a33 - a23 * a31;
  81600. var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
  81601. return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  81602. }
  81603. /**
  81604. * Multiplies two mat4s
  81605. *
  81606. * @param {mat4} out the receiving matrix
  81607. * @param {ReadonlyMat4} a the first operand
  81608. * @param {ReadonlyMat4} b the second operand
  81609. * @returns {mat4} out
  81610. */
  81611. function multiply$1(out, a, b) {
  81612. var a00 = a[0],
  81613. a01 = a[1],
  81614. a02 = a[2],
  81615. a03 = a[3];
  81616. var a10 = a[4],
  81617. a11 = a[5],
  81618. a12 = a[6],
  81619. a13 = a[7];
  81620. var a20 = a[8],
  81621. a21 = a[9],
  81622. a22 = a[10],
  81623. a23 = a[11];
  81624. var a30 = a[12],
  81625. a31 = a[13],
  81626. a32 = a[14],
  81627. a33 = a[15]; // Cache only the current line of the second matrix
  81628. var b0 = b[0],
  81629. b1 = b[1],
  81630. b2 = b[2],
  81631. b3 = b[3];
  81632. out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  81633. out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  81634. out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  81635. out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  81636. b0 = b[4];
  81637. b1 = b[5];
  81638. b2 = b[6];
  81639. b3 = b[7];
  81640. out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  81641. out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  81642. out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  81643. out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  81644. b0 = b[8];
  81645. b1 = b[9];
  81646. b2 = b[10];
  81647. b3 = b[11];
  81648. out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  81649. out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  81650. out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  81651. out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  81652. b0 = b[12];
  81653. b1 = b[13];
  81654. b2 = b[14];
  81655. b3 = b[15];
  81656. out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  81657. out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  81658. out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  81659. out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  81660. return out;
  81661. }
  81662. /**
  81663. * Translate a mat4 by the given vector
  81664. *
  81665. * @param {mat4} out the receiving matrix
  81666. * @param {ReadonlyMat4} a the matrix to translate
  81667. * @param {ReadonlyVec3} v vector to translate by
  81668. * @returns {mat4} out
  81669. */
  81670. function translate(out, a, v) {
  81671. var x = v[0],
  81672. y = v[1],
  81673. z = v[2];
  81674. var a00, a01, a02, a03;
  81675. var a10, a11, a12, a13;
  81676. var a20, a21, a22, a23;
  81677. if (a === out) {
  81678. out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
  81679. out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
  81680. out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
  81681. out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
  81682. } else {
  81683. a00 = a[0];
  81684. a01 = a[1];
  81685. a02 = a[2];
  81686. a03 = a[3];
  81687. a10 = a[4];
  81688. a11 = a[5];
  81689. a12 = a[6];
  81690. a13 = a[7];
  81691. a20 = a[8];
  81692. a21 = a[9];
  81693. a22 = a[10];
  81694. a23 = a[11];
  81695. out[0] = a00;
  81696. out[1] = a01;
  81697. out[2] = a02;
  81698. out[3] = a03;
  81699. out[4] = a10;
  81700. out[5] = a11;
  81701. out[6] = a12;
  81702. out[7] = a13;
  81703. out[8] = a20;
  81704. out[9] = a21;
  81705. out[10] = a22;
  81706. out[11] = a23;
  81707. out[12] = a00 * x + a10 * y + a20 * z + a[12];
  81708. out[13] = a01 * x + a11 * y + a21 * z + a[13];
  81709. out[14] = a02 * x + a12 * y + a22 * z + a[14];
  81710. out[15] = a03 * x + a13 * y + a23 * z + a[15];
  81711. }
  81712. return out;
  81713. }
  81714. /**
  81715. * Scales the mat4 by the dimensions in the given vec3 not using vectorization
  81716. *
  81717. * @param {mat4} out the receiving matrix
  81718. * @param {ReadonlyMat4} a the matrix to scale
  81719. * @param {ReadonlyVec3} v the vec3 to scale the matrix by
  81720. * @returns {mat4} out
  81721. **/
  81722. function scale$2(out, a, v) {
  81723. var x = v[0],
  81724. y = v[1],
  81725. z = v[2];
  81726. out[0] = a[0] * x;
  81727. out[1] = a[1] * x;
  81728. out[2] = a[2] * x;
  81729. out[3] = a[3] * x;
  81730. out[4] = a[4] * y;
  81731. out[5] = a[5] * y;
  81732. out[6] = a[6] * y;
  81733. out[7] = a[7] * y;
  81734. out[8] = a[8] * z;
  81735. out[9] = a[9] * z;
  81736. out[10] = a[10] * z;
  81737. out[11] = a[11] * z;
  81738. out[12] = a[12];
  81739. out[13] = a[13];
  81740. out[14] = a[14];
  81741. out[15] = a[15];
  81742. return out;
  81743. }
  81744. /**
  81745. * Rotates a mat4 by the given angle around the given axis
  81746. *
  81747. * @param {mat4} out the receiving matrix
  81748. * @param {ReadonlyMat4} a the matrix to rotate
  81749. * @param {Number} rad the angle to rotate the matrix by
  81750. * @param {ReadonlyVec3} axis the axis to rotate around
  81751. * @returns {mat4} out
  81752. */
  81753. function rotate(out, a, rad, axis) {
  81754. var x = axis[0],
  81755. y = axis[1],
  81756. z = axis[2];
  81757. var len = Math.hypot(x, y, z);
  81758. var s, c, t;
  81759. var a00, a01, a02, a03;
  81760. var a10, a11, a12, a13;
  81761. var a20, a21, a22, a23;
  81762. var b00, b01, b02;
  81763. var b10, b11, b12;
  81764. var b20, b21, b22;
  81765. if (len < EPSILON) {
  81766. return null;
  81767. }
  81768. len = 1 / len;
  81769. x *= len;
  81770. y *= len;
  81771. z *= len;
  81772. s = Math.sin(rad);
  81773. c = Math.cos(rad);
  81774. t = 1 - c;
  81775. a00 = a[0];
  81776. a01 = a[1];
  81777. a02 = a[2];
  81778. a03 = a[3];
  81779. a10 = a[4];
  81780. a11 = a[5];
  81781. a12 = a[6];
  81782. a13 = a[7];
  81783. a20 = a[8];
  81784. a21 = a[9];
  81785. a22 = a[10];
  81786. a23 = a[11]; // Construct the elements of the rotation matrix
  81787. b00 = x * x * t + c;
  81788. b01 = y * x * t + z * s;
  81789. b02 = z * x * t - y * s;
  81790. b10 = x * y * t - z * s;
  81791. b11 = y * y * t + c;
  81792. b12 = z * y * t + x * s;
  81793. b20 = x * z * t + y * s;
  81794. b21 = y * z * t - x * s;
  81795. b22 = z * z * t + c; // Perform rotation-specific matrix multiplication
  81796. out[0] = a00 * b00 + a10 * b01 + a20 * b02;
  81797. out[1] = a01 * b00 + a11 * b01 + a21 * b02;
  81798. out[2] = a02 * b00 + a12 * b01 + a22 * b02;
  81799. out[3] = a03 * b00 + a13 * b01 + a23 * b02;
  81800. out[4] = a00 * b10 + a10 * b11 + a20 * b12;
  81801. out[5] = a01 * b10 + a11 * b11 + a21 * b12;
  81802. out[6] = a02 * b10 + a12 * b11 + a22 * b12;
  81803. out[7] = a03 * b10 + a13 * b11 + a23 * b12;
  81804. out[8] = a00 * b20 + a10 * b21 + a20 * b22;
  81805. out[9] = a01 * b20 + a11 * b21 + a21 * b22;
  81806. out[10] = a02 * b20 + a12 * b21 + a22 * b22;
  81807. out[11] = a03 * b20 + a13 * b21 + a23 * b22;
  81808. if (a !== out) {
  81809. // If the source and destination differ, copy the unchanged last row
  81810. out[12] = a[12];
  81811. out[13] = a[13];
  81812. out[14] = a[14];
  81813. out[15] = a[15];
  81814. }
  81815. return out;
  81816. }
  81817. /**
  81818. * Rotates a matrix by the given angle around the X axis
  81819. *
  81820. * @param {mat4} out the receiving matrix
  81821. * @param {ReadonlyMat4} a the matrix to rotate
  81822. * @param {Number} rad the angle to rotate the matrix by
  81823. * @returns {mat4} out
  81824. */
  81825. function rotateX$1(out, a, rad) {
  81826. var s = Math.sin(rad);
  81827. var c = Math.cos(rad);
  81828. var a10 = a[4];
  81829. var a11 = a[5];
  81830. var a12 = a[6];
  81831. var a13 = a[7];
  81832. var a20 = a[8];
  81833. var a21 = a[9];
  81834. var a22 = a[10];
  81835. var a23 = a[11];
  81836. if (a !== out) {
  81837. // If the source and destination differ, copy the unchanged rows
  81838. out[0] = a[0];
  81839. out[1] = a[1];
  81840. out[2] = a[2];
  81841. out[3] = a[3];
  81842. out[12] = a[12];
  81843. out[13] = a[13];
  81844. out[14] = a[14];
  81845. out[15] = a[15];
  81846. } // Perform axis-specific matrix multiplication
  81847. out[4] = a10 * c + a20 * s;
  81848. out[5] = a11 * c + a21 * s;
  81849. out[6] = a12 * c + a22 * s;
  81850. out[7] = a13 * c + a23 * s;
  81851. out[8] = a20 * c - a10 * s;
  81852. out[9] = a21 * c - a11 * s;
  81853. out[10] = a22 * c - a12 * s;
  81854. out[11] = a23 * c - a13 * s;
  81855. return out;
  81856. }
  81857. /**
  81858. * Rotates a matrix by the given angle around the Y axis
  81859. *
  81860. * @param {mat4} out the receiving matrix
  81861. * @param {ReadonlyMat4} a the matrix to rotate
  81862. * @param {Number} rad the angle to rotate the matrix by
  81863. * @returns {mat4} out
  81864. */
  81865. function rotateY$1(out, a, rad) {
  81866. var s = Math.sin(rad);
  81867. var c = Math.cos(rad);
  81868. var a00 = a[0];
  81869. var a01 = a[1];
  81870. var a02 = a[2];
  81871. var a03 = a[3];
  81872. var a20 = a[8];
  81873. var a21 = a[9];
  81874. var a22 = a[10];
  81875. var a23 = a[11];
  81876. if (a !== out) {
  81877. // If the source and destination differ, copy the unchanged rows
  81878. out[4] = a[4];
  81879. out[5] = a[5];
  81880. out[6] = a[6];
  81881. out[7] = a[7];
  81882. out[12] = a[12];
  81883. out[13] = a[13];
  81884. out[14] = a[14];
  81885. out[15] = a[15];
  81886. } // Perform axis-specific matrix multiplication
  81887. out[0] = a00 * c - a20 * s;
  81888. out[1] = a01 * c - a21 * s;
  81889. out[2] = a02 * c - a22 * s;
  81890. out[3] = a03 * c - a23 * s;
  81891. out[8] = a00 * s + a20 * c;
  81892. out[9] = a01 * s + a21 * c;
  81893. out[10] = a02 * s + a22 * c;
  81894. out[11] = a03 * s + a23 * c;
  81895. return out;
  81896. }
  81897. /**
  81898. * Rotates a matrix by the given angle around the Z axis
  81899. *
  81900. * @param {mat4} out the receiving matrix
  81901. * @param {ReadonlyMat4} a the matrix to rotate
  81902. * @param {Number} rad the angle to rotate the matrix by
  81903. * @returns {mat4} out
  81904. */
  81905. function rotateZ$1(out, a, rad) {
  81906. var s = Math.sin(rad);
  81907. var c = Math.cos(rad);
  81908. var a00 = a[0];
  81909. var a01 = a[1];
  81910. var a02 = a[2];
  81911. var a03 = a[3];
  81912. var a10 = a[4];
  81913. var a11 = a[5];
  81914. var a12 = a[6];
  81915. var a13 = a[7];
  81916. if (a !== out) {
  81917. // If the source and destination differ, copy the unchanged last row
  81918. out[8] = a[8];
  81919. out[9] = a[9];
  81920. out[10] = a[10];
  81921. out[11] = a[11];
  81922. out[12] = a[12];
  81923. out[13] = a[13];
  81924. out[14] = a[14];
  81925. out[15] = a[15];
  81926. } // Perform axis-specific matrix multiplication
  81927. out[0] = a00 * c + a10 * s;
  81928. out[1] = a01 * c + a11 * s;
  81929. out[2] = a02 * c + a12 * s;
  81930. out[3] = a03 * c + a13 * s;
  81931. out[4] = a10 * c - a00 * s;
  81932. out[5] = a11 * c - a01 * s;
  81933. out[6] = a12 * c - a02 * s;
  81934. out[7] = a13 * c - a03 * s;
  81935. return out;
  81936. }
  81937. /**
  81938. * Returns the scaling factor component of a transformation
  81939. * matrix. If a matrix is built with fromRotationTranslationScale
  81940. * with a normalized Quaternion paramter, the returned vector will be
  81941. * the same as the scaling vector
  81942. * originally supplied.
  81943. * @param {vec3} out Vector to receive scaling factor component
  81944. * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
  81945. * @return {vec3} out
  81946. */
  81947. function getScaling(out, mat) {
  81948. var m11 = mat[0];
  81949. var m12 = mat[1];
  81950. var m13 = mat[2];
  81951. var m21 = mat[4];
  81952. var m22 = mat[5];
  81953. var m23 = mat[6];
  81954. var m31 = mat[8];
  81955. var m32 = mat[9];
  81956. var m33 = mat[10];
  81957. out[0] = Math.hypot(m11, m12, m13);
  81958. out[1] = Math.hypot(m21, m22, m23);
  81959. out[2] = Math.hypot(m31, m32, m33);
  81960. return out;
  81961. }
  81962. /**
  81963. * Calculates a 4x4 matrix from the given quaternion
  81964. *
  81965. * @param {mat4} out mat4 receiving operation result
  81966. * @param {ReadonlyQuat} q Quaternion to create matrix from
  81967. *
  81968. * @returns {mat4} out
  81969. */
  81970. function fromQuat(out, q) {
  81971. var x = q[0],
  81972. y = q[1],
  81973. z = q[2],
  81974. w = q[3];
  81975. var x2 = x + x;
  81976. var y2 = y + y;
  81977. var z2 = z + z;
  81978. var xx = x * x2;
  81979. var yx = y * x2;
  81980. var yy = y * y2;
  81981. var zx = z * x2;
  81982. var zy = z * y2;
  81983. var zz = z * z2;
  81984. var wx = w * x2;
  81985. var wy = w * y2;
  81986. var wz = w * z2;
  81987. out[0] = 1 - yy - zz;
  81988. out[1] = yx + wz;
  81989. out[2] = zx - wy;
  81990. out[3] = 0;
  81991. out[4] = yx - wz;
  81992. out[5] = 1 - xx - zz;
  81993. out[6] = zy + wx;
  81994. out[7] = 0;
  81995. out[8] = zx + wy;
  81996. out[9] = zy - wx;
  81997. out[10] = 1 - xx - yy;
  81998. out[11] = 0;
  81999. out[12] = 0;
  82000. out[13] = 0;
  82001. out[14] = 0;
  82002. out[15] = 1;
  82003. return out;
  82004. }
  82005. /**
  82006. * Generates a frustum matrix with the given bounds
  82007. *
  82008. * @param {mat4} out mat4 frustum matrix will be written into
  82009. * @param {Number} left Left bound of the frustum
  82010. * @param {Number} right Right bound of the frustum
  82011. * @param {Number} bottom Bottom bound of the frustum
  82012. * @param {Number} top Top bound of the frustum
  82013. * @param {Number} near Near bound of the frustum
  82014. * @param {Number} far Far bound of the frustum
  82015. * @returns {mat4} out
  82016. */
  82017. function frustum(out, left, right, bottom, top, near, far) {
  82018. var rl = 1 / (right - left);
  82019. var tb = 1 / (top - bottom);
  82020. var nf = 1 / (near - far);
  82021. out[0] = near * 2 * rl;
  82022. out[1] = 0;
  82023. out[2] = 0;
  82024. out[3] = 0;
  82025. out[4] = 0;
  82026. out[5] = near * 2 * tb;
  82027. out[6] = 0;
  82028. out[7] = 0;
  82029. out[8] = (right + left) * rl;
  82030. out[9] = (top + bottom) * tb;
  82031. out[10] = (far + near) * nf;
  82032. out[11] = -1;
  82033. out[12] = 0;
  82034. out[13] = 0;
  82035. out[14] = far * near * 2 * nf;
  82036. out[15] = 0;
  82037. return out;
  82038. }
  82039. /**
  82040. * Generates a perspective projection matrix with the given bounds.
  82041. * Passing null/undefined/no value for far will generate infinite projection matrix.
  82042. *
  82043. * @param {mat4} out mat4 frustum matrix will be written into
  82044. * @param {number} fovy Vertical field of view in radians
  82045. * @param {number} aspect Aspect ratio. typically viewport width/height
  82046. * @param {number} near Near bound of the frustum
  82047. * @param {number} far Far bound of the frustum, can be null or Infinity
  82048. * @returns {mat4} out
  82049. */
  82050. function perspective(out, fovy, aspect, near, far) {
  82051. var f = 1.0 / Math.tan(fovy / 2),
  82052. nf;
  82053. out[0] = f / aspect;
  82054. out[1] = 0;
  82055. out[2] = 0;
  82056. out[3] = 0;
  82057. out[4] = 0;
  82058. out[5] = f;
  82059. out[6] = 0;
  82060. out[7] = 0;
  82061. out[8] = 0;
  82062. out[9] = 0;
  82063. out[11] = -1;
  82064. out[12] = 0;
  82065. out[13] = 0;
  82066. out[15] = 0;
  82067. if (far != null && far !== Infinity) {
  82068. nf = 1 / (near - far);
  82069. out[10] = (far + near) * nf;
  82070. out[14] = 2 * far * near * nf;
  82071. } else {
  82072. out[10] = -1;
  82073. out[14] = -2 * near;
  82074. }
  82075. return out;
  82076. }
  82077. /**
  82078. * Generates a orthogonal projection matrix with the given bounds
  82079. *
  82080. * @param {mat4} out mat4 frustum matrix will be written into
  82081. * @param {number} left Left bound of the frustum
  82082. * @param {number} right Right bound of the frustum
  82083. * @param {number} bottom Bottom bound of the frustum
  82084. * @param {number} top Top bound of the frustum
  82085. * @param {number} near Near bound of the frustum
  82086. * @param {number} far Far bound of the frustum
  82087. * @returns {mat4} out
  82088. */
  82089. function ortho(out, left, right, bottom, top, near, far) {
  82090. var lr = 1 / (left - right);
  82091. var bt = 1 / (bottom - top);
  82092. var nf = 1 / (near - far);
  82093. out[0] = -2 * lr;
  82094. out[1] = 0;
  82095. out[2] = 0;
  82096. out[3] = 0;
  82097. out[4] = 0;
  82098. out[5] = -2 * bt;
  82099. out[6] = 0;
  82100. out[7] = 0;
  82101. out[8] = 0;
  82102. out[9] = 0;
  82103. out[10] = 2 * nf;
  82104. out[11] = 0;
  82105. out[12] = (left + right) * lr;
  82106. out[13] = (top + bottom) * bt;
  82107. out[14] = (far + near) * nf;
  82108. out[15] = 1;
  82109. return out;
  82110. }
  82111. /**
  82112. * Generates a look-at matrix with the given eye position, focal point, and up axis.
  82113. * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
  82114. *
  82115. * @param {mat4} out mat4 frustum matrix will be written into
  82116. * @param {ReadonlyVec3} eye Position of the viewer
  82117. * @param {ReadonlyVec3} center Point the viewer is looking at
  82118. * @param {ReadonlyVec3} up vec3 pointing up
  82119. * @returns {mat4} out
  82120. */
  82121. function lookAt(out, eye, center, up) {
  82122. var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
  82123. var eyex = eye[0];
  82124. var eyey = eye[1];
  82125. var eyez = eye[2];
  82126. var upx = up[0];
  82127. var upy = up[1];
  82128. var upz = up[2];
  82129. var centerx = center[0];
  82130. var centery = center[1];
  82131. var centerz = center[2];
  82132. if (Math.abs(eyex - centerx) < EPSILON && Math.abs(eyey - centery) < EPSILON && Math.abs(eyez - centerz) < EPSILON) {
  82133. return identity$1(out);
  82134. }
  82135. z0 = eyex - centerx;
  82136. z1 = eyey - centery;
  82137. z2 = eyez - centerz;
  82138. len = 1 / Math.hypot(z0, z1, z2);
  82139. z0 *= len;
  82140. z1 *= len;
  82141. z2 *= len;
  82142. x0 = upy * z2 - upz * z1;
  82143. x1 = upz * z0 - upx * z2;
  82144. x2 = upx * z1 - upy * z0;
  82145. len = Math.hypot(x0, x1, x2);
  82146. if (!len) {
  82147. x0 = 0;
  82148. x1 = 0;
  82149. x2 = 0;
  82150. } else {
  82151. len = 1 / len;
  82152. x0 *= len;
  82153. x1 *= len;
  82154. x2 *= len;
  82155. }
  82156. y0 = z1 * x2 - z2 * x1;
  82157. y1 = z2 * x0 - z0 * x2;
  82158. y2 = z0 * x1 - z1 * x0;
  82159. len = Math.hypot(y0, y1, y2);
  82160. if (!len) {
  82161. y0 = 0;
  82162. y1 = 0;
  82163. y2 = 0;
  82164. } else {
  82165. len = 1 / len;
  82166. y0 *= len;
  82167. y1 *= len;
  82168. y2 *= len;
  82169. }
  82170. out[0] = x0;
  82171. out[1] = y0;
  82172. out[2] = z0;
  82173. out[3] = 0;
  82174. out[4] = x1;
  82175. out[5] = y1;
  82176. out[6] = z1;
  82177. out[7] = 0;
  82178. out[8] = x2;
  82179. out[9] = y2;
  82180. out[10] = z2;
  82181. out[11] = 0;
  82182. out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
  82183. out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
  82184. out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
  82185. out[15] = 1;
  82186. return out;
  82187. }
  82188. /**
  82189. * 4 Dimensional Vector
  82190. * @module vec4
  82191. */
  82192. /**
  82193. * Creates a new, empty vec4
  82194. *
  82195. * @returns {vec4} a new 4D vector
  82196. */
  82197. function create$1() {
  82198. var out = new ARRAY_TYPE(4);
  82199. if (ARRAY_TYPE != Float32Array) {
  82200. out[0] = 0;
  82201. out[1] = 0;
  82202. out[2] = 0;
  82203. out[3] = 0;
  82204. }
  82205. return out;
  82206. }
  82207. /**
  82208. * Adds two vec4's
  82209. *
  82210. * @param {vec4} out the receiving vector
  82211. * @param {ReadonlyVec4} a the first operand
  82212. * @param {ReadonlyVec4} b the second operand
  82213. * @returns {vec4} out
  82214. */
  82215. function add$1(out, a, b) {
  82216. out[0] = a[0] + b[0];
  82217. out[1] = a[1] + b[1];
  82218. out[2] = a[2] + b[2];
  82219. out[3] = a[3] + b[3];
  82220. return out;
  82221. }
  82222. /**
  82223. * Scales a vec4 by a scalar number
  82224. *
  82225. * @param {vec4} out the receiving vector
  82226. * @param {ReadonlyVec4} a the vector to scale
  82227. * @param {Number} b amount to scale the vector by
  82228. * @returns {vec4} out
  82229. */
  82230. function scale$1(out, a, b) {
  82231. out[0] = a[0] * b;
  82232. out[1] = a[1] * b;
  82233. out[2] = a[2] * b;
  82234. out[3] = a[3] * b;
  82235. return out;
  82236. }
  82237. /**
  82238. * Calculates the length of a vec4
  82239. *
  82240. * @param {ReadonlyVec4} a vector to calculate length of
  82241. * @returns {Number} length of a
  82242. */
  82243. function length$1(a) {
  82244. var x = a[0];
  82245. var y = a[1];
  82246. var z = a[2];
  82247. var w = a[3];
  82248. return Math.hypot(x, y, z, w);
  82249. }
  82250. /**
  82251. * Calculates the squared length of a vec4
  82252. *
  82253. * @param {ReadonlyVec4} a vector to calculate squared length of
  82254. * @returns {Number} squared length of a
  82255. */
  82256. function squaredLength$1(a) {
  82257. var x = a[0];
  82258. var y = a[1];
  82259. var z = a[2];
  82260. var w = a[3];
  82261. return x * x + y * y + z * z + w * w;
  82262. }
  82263. /**
  82264. * Normalize a vec4
  82265. *
  82266. * @param {vec4} out the receiving vector
  82267. * @param {ReadonlyVec4} a vector to normalize
  82268. * @returns {vec4} out
  82269. */
  82270. function normalize$1(out, a) {
  82271. var x = a[0];
  82272. var y = a[1];
  82273. var z = a[2];
  82274. var w = a[3];
  82275. var len = x * x + y * y + z * z + w * w;
  82276. if (len > 0) {
  82277. len = 1 / Math.sqrt(len);
  82278. }
  82279. out[0] = x * len;
  82280. out[1] = y * len;
  82281. out[2] = z * len;
  82282. out[3] = w * len;
  82283. return out;
  82284. }
  82285. /**
  82286. * Calculates the dot product of two vec4's
  82287. *
  82288. * @param {ReadonlyVec4} a the first operand
  82289. * @param {ReadonlyVec4} b the second operand
  82290. * @returns {Number} dot product of a and b
  82291. */
  82292. function dot$1(a, b) {
  82293. return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
  82294. }
  82295. /**
  82296. * Performs a linear interpolation between two vec4's
  82297. *
  82298. * @param {vec4} out the receiving vector
  82299. * @param {ReadonlyVec4} a the first operand
  82300. * @param {ReadonlyVec4} b the second operand
  82301. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  82302. * @returns {vec4} out
  82303. */
  82304. function lerp$1(out, a, b, t) {
  82305. var ax = a[0];
  82306. var ay = a[1];
  82307. var az = a[2];
  82308. var aw = a[3];
  82309. out[0] = ax + t * (b[0] - ax);
  82310. out[1] = ay + t * (b[1] - ay);
  82311. out[2] = az + t * (b[2] - az);
  82312. out[3] = aw + t * (b[3] - aw);
  82313. return out;
  82314. }
  82315. /**
  82316. * Transforms the vec4 with a mat4.
  82317. *
  82318. * @param {vec4} out the receiving vector
  82319. * @param {ReadonlyVec4} a the vector to transform
  82320. * @param {ReadonlyMat4} m matrix to transform with
  82321. * @returns {vec4} out
  82322. */
  82323. function transformMat4(out, a, m) {
  82324. var x = a[0],
  82325. y = a[1],
  82326. z = a[2],
  82327. w = a[3];
  82328. out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
  82329. out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
  82330. out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
  82331. out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
  82332. return out;
  82333. }
  82334. /**
  82335. * Transforms the vec4 with a quat
  82336. *
  82337. * @param {vec4} out the receiving vector
  82338. * @param {ReadonlyVec4} a the vector to transform
  82339. * @param {ReadonlyQuat} q quaternion to transform with
  82340. * @returns {vec4} out
  82341. */
  82342. function transformQuat(out, a, q) {
  82343. var x = a[0],
  82344. y = a[1],
  82345. z = a[2];
  82346. var qx = q[0],
  82347. qy = q[1],
  82348. qz = q[2],
  82349. qw = q[3]; // calculate quat * vec
  82350. var ix = qw * x + qy * z - qz * y;
  82351. var iy = qw * y + qz * x - qx * z;
  82352. var iz = qw * z + qx * y - qy * x;
  82353. var iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat
  82354. out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
  82355. out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
  82356. out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
  82357. out[3] = a[3];
  82358. return out;
  82359. }
  82360. /**
  82361. * Perform some operation over an array of vec4s.
  82362. *
  82363. * @param {Array} a the array of vectors to iterate over
  82364. * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
  82365. * @param {Number} offset Number of elements to skip at the beginning of the array
  82366. * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
  82367. * @param {Function} fn Function to call for each vector in the array
  82368. * @param {Object} [arg] additional argument to pass to fn
  82369. * @returns {Array} a
  82370. * @function
  82371. */
  82372. (function () {
  82373. var vec = create$1();
  82374. return function (a, stride, offset, count, fn, arg) {
  82375. var i, l;
  82376. if (!stride) {
  82377. stride = 4;
  82378. }
  82379. if (!offset) {
  82380. offset = 0;
  82381. }
  82382. if (count) {
  82383. l = Math.min(count * stride + offset, a.length);
  82384. } else {
  82385. l = a.length;
  82386. }
  82387. for (i = offset; i < l; i += stride) {
  82388. vec[0] = a[i];
  82389. vec[1] = a[i + 1];
  82390. vec[2] = a[i + 2];
  82391. vec[3] = a[i + 3];
  82392. fn(vec, vec, arg);
  82393. a[i] = vec[0];
  82394. a[i + 1] = vec[1];
  82395. a[i + 2] = vec[2];
  82396. a[i + 3] = vec[3];
  82397. }
  82398. return a;
  82399. };
  82400. })();
  82401. const IDENTITY = Object.freeze([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
  82402. const ZERO = Object.freeze([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
  82403. const INDICES = Object.freeze({
  82404. COL0ROW0: 0,
  82405. COL0ROW1: 1,
  82406. COL0ROW2: 2,
  82407. COL0ROW3: 3,
  82408. COL1ROW0: 4,
  82409. COL1ROW1: 5,
  82410. COL1ROW2: 6,
  82411. COL1ROW3: 7,
  82412. COL2ROW0: 8,
  82413. COL2ROW1: 9,
  82414. COL2ROW2: 10,
  82415. COL2ROW3: 11,
  82416. COL3ROW0: 12,
  82417. COL3ROW1: 13,
  82418. COL3ROW2: 14,
  82419. COL3ROW3: 15
  82420. });
  82421. const constants = {};
  82422. class Matrix4$1 extends Matrix {
  82423. static get IDENTITY() {
  82424. constants.IDENTITY = constants.IDENTITY || Object.freeze(new Matrix4$1(IDENTITY));
  82425. return constants.IDENTITY;
  82426. }
  82427. static get ZERO() {
  82428. constants.ZERO = constants.ZERO || Object.freeze(new Matrix4$1(ZERO));
  82429. return constants.ZERO;
  82430. }
  82431. get INDICES() {
  82432. return INDICES;
  82433. }
  82434. get ELEMENTS() {
  82435. return 16;
  82436. }
  82437. get RANK() {
  82438. return 4;
  82439. }
  82440. constructor(array) {
  82441. super(-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0);
  82442. if (arguments.length === 1 && Array.isArray(array)) {
  82443. this.copy(array);
  82444. } else {
  82445. this.identity();
  82446. }
  82447. }
  82448. copy(array) {
  82449. this[0] = array[0];
  82450. this[1] = array[1];
  82451. this[2] = array[2];
  82452. this[3] = array[3];
  82453. this[4] = array[4];
  82454. this[5] = array[5];
  82455. this[6] = array[6];
  82456. this[7] = array[7];
  82457. this[8] = array[8];
  82458. this[9] = array[9];
  82459. this[10] = array[10];
  82460. this[11] = array[11];
  82461. this[12] = array[12];
  82462. this[13] = array[13];
  82463. this[14] = array[14];
  82464. this[15] = array[15];
  82465. return this.check();
  82466. }
  82467. set(m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33) {
  82468. this[0] = m00;
  82469. this[1] = m10;
  82470. this[2] = m20;
  82471. this[3] = m30;
  82472. this[4] = m01;
  82473. this[5] = m11;
  82474. this[6] = m21;
  82475. this[7] = m31;
  82476. this[8] = m02;
  82477. this[9] = m12;
  82478. this[10] = m22;
  82479. this[11] = m32;
  82480. this[12] = m03;
  82481. this[13] = m13;
  82482. this[14] = m23;
  82483. this[15] = m33;
  82484. return this.check();
  82485. }
  82486. setRowMajor(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
  82487. this[0] = m00;
  82488. this[1] = m10;
  82489. this[2] = m20;
  82490. this[3] = m30;
  82491. this[4] = m01;
  82492. this[5] = m11;
  82493. this[6] = m21;
  82494. this[7] = m31;
  82495. this[8] = m02;
  82496. this[9] = m12;
  82497. this[10] = m22;
  82498. this[11] = m32;
  82499. this[12] = m03;
  82500. this[13] = m13;
  82501. this[14] = m23;
  82502. this[15] = m33;
  82503. return this.check();
  82504. }
  82505. toRowMajor(result) {
  82506. result[0] = this[0];
  82507. result[1] = this[4];
  82508. result[2] = this[8];
  82509. result[3] = this[12];
  82510. result[4] = this[1];
  82511. result[5] = this[5];
  82512. result[6] = this[9];
  82513. result[7] = this[13];
  82514. result[8] = this[2];
  82515. result[9] = this[6];
  82516. result[10] = this[10];
  82517. result[11] = this[14];
  82518. result[12] = this[3];
  82519. result[13] = this[7];
  82520. result[14] = this[11];
  82521. result[15] = this[15];
  82522. return result;
  82523. }
  82524. identity() {
  82525. return this.copy(IDENTITY);
  82526. }
  82527. fromQuaternion(q) {
  82528. fromQuat(this, q);
  82529. return this.check();
  82530. }
  82531. frustum({
  82532. left,
  82533. right,
  82534. bottom,
  82535. top,
  82536. near,
  82537. far
  82538. }) {
  82539. if (far === Infinity) {
  82540. Matrix4$1._computeInfinitePerspectiveOffCenter(this, left, right, bottom, top, near);
  82541. } else {
  82542. frustum(this, left, right, bottom, top, near, far);
  82543. }
  82544. return this.check();
  82545. }
  82546. static _computeInfinitePerspectiveOffCenter(result, left, right, bottom, top, near) {
  82547. const column0Row0 = 2.0 * near / (right - left);
  82548. const column1Row1 = 2.0 * near / (top - bottom);
  82549. const column2Row0 = (right + left) / (right - left);
  82550. const column2Row1 = (top + bottom) / (top - bottom);
  82551. const column2Row2 = -1.0;
  82552. const column2Row3 = -1.0;
  82553. const column3Row2 = -2.0 * near;
  82554. result[0] = column0Row0;
  82555. result[1] = 0.0;
  82556. result[2] = 0.0;
  82557. result[3] = 0.0;
  82558. result[4] = 0.0;
  82559. result[5] = column1Row1;
  82560. result[6] = 0.0;
  82561. result[7] = 0.0;
  82562. result[8] = column2Row0;
  82563. result[9] = column2Row1;
  82564. result[10] = column2Row2;
  82565. result[11] = column2Row3;
  82566. result[12] = 0.0;
  82567. result[13] = 0.0;
  82568. result[14] = column3Row2;
  82569. result[15] = 0.0;
  82570. return result;
  82571. }
  82572. lookAt(eye, center, up) {
  82573. if (arguments.length === 1) {
  82574. ({
  82575. eye,
  82576. center,
  82577. up
  82578. } = eye);
  82579. }
  82580. center = center || [0, 0, 0];
  82581. up = up || [0, 1, 0];
  82582. lookAt(this, eye, center, up);
  82583. return this.check();
  82584. }
  82585. ortho({
  82586. left,
  82587. right,
  82588. bottom,
  82589. top,
  82590. near = 0.1,
  82591. far = 500
  82592. }) {
  82593. ortho(this, left, right, bottom, top, near, far);
  82594. return this.check();
  82595. }
  82596. orthographic({
  82597. fovy = 45 * Math.PI / 180,
  82598. aspect = 1,
  82599. focalDistance = 1,
  82600. near = 0.1,
  82601. far = 500
  82602. }) {
  82603. if (fovy > Math.PI * 2) {
  82604. throw Error('radians');
  82605. }
  82606. const halfY = fovy / 2;
  82607. const top = focalDistance * Math.tan(halfY);
  82608. const right = top * aspect;
  82609. return new Matrix4$1().ortho({
  82610. left: -right,
  82611. right,
  82612. bottom: -top,
  82613. top,
  82614. near,
  82615. far
  82616. });
  82617. }
  82618. perspective({
  82619. fovy = undefined,
  82620. fov = 45 * Math.PI / 180,
  82621. aspect = 1,
  82622. near = 0.1,
  82623. far = 500
  82624. } = {}) {
  82625. fovy = fovy || fov;
  82626. if (fovy > Math.PI * 2) {
  82627. throw Error('radians');
  82628. }
  82629. perspective(this, fovy, aspect, near, far);
  82630. return this.check();
  82631. }
  82632. determinant() {
  82633. return determinant(this);
  82634. }
  82635. getScale(result = [-0, -0, -0]) {
  82636. result[0] = Math.sqrt(this[0] * this[0] + this[1] * this[1] + this[2] * this[2]);
  82637. result[1] = Math.sqrt(this[4] * this[4] + this[5] * this[5] + this[6] * this[6]);
  82638. result[2] = Math.sqrt(this[8] * this[8] + this[9] * this[9] + this[10] * this[10]);
  82639. return result;
  82640. }
  82641. getTranslation(result = [-0, -0, -0]) {
  82642. result[0] = this[12];
  82643. result[1] = this[13];
  82644. result[2] = this[14];
  82645. return result;
  82646. }
  82647. getRotation(result = [-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0], scaleResult = null) {
  82648. const scale = this.getScale(scaleResult || [-0, -0, -0]);
  82649. const inverseScale0 = 1 / scale[0];
  82650. const inverseScale1 = 1 / scale[1];
  82651. const inverseScale2 = 1 / scale[2];
  82652. result[0] = this[0] * inverseScale0;
  82653. result[1] = this[1] * inverseScale1;
  82654. result[2] = this[2] * inverseScale2;
  82655. result[3] = 0;
  82656. result[4] = this[4] * inverseScale0;
  82657. result[5] = this[5] * inverseScale1;
  82658. result[6] = this[6] * inverseScale2;
  82659. result[7] = 0;
  82660. result[8] = this[8] * inverseScale0;
  82661. result[9] = this[9] * inverseScale1;
  82662. result[10] = this[10] * inverseScale2;
  82663. result[11] = 0;
  82664. result[12] = 0;
  82665. result[13] = 0;
  82666. result[14] = 0;
  82667. result[15] = 1;
  82668. return result;
  82669. }
  82670. getRotationMatrix3(result = [-0, -0, -0, -0, -0, -0, -0, -0, -0], scaleResult = null) {
  82671. const scale = this.getScale(scaleResult || [-0, -0, -0]);
  82672. const inverseScale0 = 1 / scale[0];
  82673. const inverseScale1 = 1 / scale[1];
  82674. const inverseScale2 = 1 / scale[2];
  82675. result[0] = this[0] * inverseScale0;
  82676. result[1] = this[1] * inverseScale1;
  82677. result[2] = this[2] * inverseScale2;
  82678. result[3] = this[4] * inverseScale0;
  82679. result[4] = this[5] * inverseScale1;
  82680. result[5] = this[6] * inverseScale2;
  82681. result[6] = this[8] * inverseScale0;
  82682. result[7] = this[9] * inverseScale1;
  82683. result[8] = this[10] * inverseScale2;
  82684. return result;
  82685. }
  82686. transpose() {
  82687. transpose(this, this);
  82688. return this.check();
  82689. }
  82690. invert() {
  82691. invert$1(this, this);
  82692. return this.check();
  82693. }
  82694. multiplyLeft(a) {
  82695. multiply$1(this, a, this);
  82696. return this.check();
  82697. }
  82698. multiplyRight(a) {
  82699. multiply$1(this, this, a);
  82700. return this.check();
  82701. }
  82702. rotateX(radians) {
  82703. rotateX$1(this, this, radians);
  82704. return this.check();
  82705. }
  82706. rotateY(radians) {
  82707. rotateY$1(this, this, radians);
  82708. return this.check();
  82709. }
  82710. rotateZ(radians) {
  82711. rotateZ$1(this, this, radians);
  82712. return this.check();
  82713. }
  82714. rotateXYZ([rx, ry, rz]) {
  82715. return this.rotateX(rx).rotateY(ry).rotateZ(rz);
  82716. }
  82717. rotateAxis(radians, axis) {
  82718. rotate(this, this, radians, axis);
  82719. return this.check();
  82720. }
  82721. scale(factor) {
  82722. if (Array.isArray(factor)) {
  82723. scale$2(this, this, factor);
  82724. } else {
  82725. scale$2(this, this, [factor, factor, factor]);
  82726. }
  82727. return this.check();
  82728. }
  82729. translate(vec) {
  82730. translate(this, this, vec);
  82731. return this.check();
  82732. }
  82733. transform(vector, result) {
  82734. if (vector.length === 4) {
  82735. result = transformMat4(result || [-0, -0, -0, -0], vector, this);
  82736. checkVector(result, 4);
  82737. return result;
  82738. }
  82739. return this.transformAsPoint(vector, result);
  82740. }
  82741. transformAsPoint(vector, result) {
  82742. const {
  82743. length
  82744. } = vector;
  82745. switch (length) {
  82746. case 2:
  82747. result = transformMat4$2(result || [-0, -0], vector, this);
  82748. break;
  82749. case 3:
  82750. result = transformMat4$1(result || [-0, -0, -0], vector, this);
  82751. break;
  82752. default:
  82753. throw new Error('Illegal vector');
  82754. }
  82755. checkVector(result, vector.length);
  82756. return result;
  82757. }
  82758. transformAsVector(vector, result) {
  82759. switch (vector.length) {
  82760. case 2:
  82761. result = vec2_transformMat4AsVector(result || [-0, -0], vector, this);
  82762. break;
  82763. case 3:
  82764. result = vec3_transformMat4AsVector(result || [-0, -0, -0], vector, this);
  82765. break;
  82766. default:
  82767. throw new Error('Illegal vector');
  82768. }
  82769. checkVector(result, vector.length);
  82770. return result;
  82771. }
  82772. makeRotationX(radians) {
  82773. return this.identity().rotateX(radians);
  82774. }
  82775. makeTranslation(x, y, z) {
  82776. return this.identity().translate([x, y, z]);
  82777. }
  82778. transformPoint(vector, result) {
  82779. deprecated('Matrix4.transformPoint', '3.0');
  82780. return this.transformAsPoint(vector, result);
  82781. }
  82782. transformVector(vector, result) {
  82783. deprecated('Matrix4.transformVector', '3.0');
  82784. return this.transformAsPoint(vector, result);
  82785. }
  82786. transformDirection(vector, result) {
  82787. deprecated('Matrix4.transformDirection', '3.0');
  82788. return this.transformAsVector(vector, result);
  82789. }
  82790. }
  82791. /**
  82792. * Quaternion
  82793. * @module quat
  82794. */
  82795. /**
  82796. * Creates a new identity quat
  82797. *
  82798. * @returns {quat} a new quaternion
  82799. */
  82800. function create() {
  82801. var out = new ARRAY_TYPE(4);
  82802. if (ARRAY_TYPE != Float32Array) {
  82803. out[0] = 0;
  82804. out[1] = 0;
  82805. out[2] = 0;
  82806. }
  82807. out[3] = 1;
  82808. return out;
  82809. }
  82810. /**
  82811. * Set a quat to the identity quaternion
  82812. *
  82813. * @param {quat} out the receiving quaternion
  82814. * @returns {quat} out
  82815. */
  82816. function identity(out) {
  82817. out[0] = 0;
  82818. out[1] = 0;
  82819. out[2] = 0;
  82820. out[3] = 1;
  82821. return out;
  82822. }
  82823. /**
  82824. * Sets a quat from the given angle and rotation axis,
  82825. * then returns it.
  82826. *
  82827. * @param {quat} out the receiving quaternion
  82828. * @param {ReadonlyVec3} axis the axis around which to rotate
  82829. * @param {Number} rad the angle in radians
  82830. * @returns {quat} out
  82831. **/
  82832. function setAxisAngle(out, axis, rad) {
  82833. rad = rad * 0.5;
  82834. var s = Math.sin(rad);
  82835. out[0] = s * axis[0];
  82836. out[1] = s * axis[1];
  82837. out[2] = s * axis[2];
  82838. out[3] = Math.cos(rad);
  82839. return out;
  82840. }
  82841. /**
  82842. * Multiplies two quat's
  82843. *
  82844. * @param {quat} out the receiving quaternion
  82845. * @param {ReadonlyQuat} a the first operand
  82846. * @param {ReadonlyQuat} b the second operand
  82847. * @returns {quat} out
  82848. */
  82849. function multiply(out, a, b) {
  82850. var ax = a[0],
  82851. ay = a[1],
  82852. az = a[2],
  82853. aw = a[3];
  82854. var bx = b[0],
  82855. by = b[1],
  82856. bz = b[2],
  82857. bw = b[3];
  82858. out[0] = ax * bw + aw * bx + ay * bz - az * by;
  82859. out[1] = ay * bw + aw * by + az * bx - ax * bz;
  82860. out[2] = az * bw + aw * bz + ax * by - ay * bx;
  82861. out[3] = aw * bw - ax * bx - ay * by - az * bz;
  82862. return out;
  82863. }
  82864. /**
  82865. * Rotates a quaternion by the given angle about the X axis
  82866. *
  82867. * @param {quat} out quat receiving operation result
  82868. * @param {ReadonlyQuat} a quat to rotate
  82869. * @param {number} rad angle (in radians) to rotate
  82870. * @returns {quat} out
  82871. */
  82872. function rotateX(out, a, rad) {
  82873. rad *= 0.5;
  82874. var ax = a[0],
  82875. ay = a[1],
  82876. az = a[2],
  82877. aw = a[3];
  82878. var bx = Math.sin(rad),
  82879. bw = Math.cos(rad);
  82880. out[0] = ax * bw + aw * bx;
  82881. out[1] = ay * bw + az * bx;
  82882. out[2] = az * bw - ay * bx;
  82883. out[3] = aw * bw - ax * bx;
  82884. return out;
  82885. }
  82886. /**
  82887. * Rotates a quaternion by the given angle about the Y axis
  82888. *
  82889. * @param {quat} out quat receiving operation result
  82890. * @param {ReadonlyQuat} a quat to rotate
  82891. * @param {number} rad angle (in radians) to rotate
  82892. * @returns {quat} out
  82893. */
  82894. function rotateY(out, a, rad) {
  82895. rad *= 0.5;
  82896. var ax = a[0],
  82897. ay = a[1],
  82898. az = a[2],
  82899. aw = a[3];
  82900. var by = Math.sin(rad),
  82901. bw = Math.cos(rad);
  82902. out[0] = ax * bw - az * by;
  82903. out[1] = ay * bw + aw * by;
  82904. out[2] = az * bw + ax * by;
  82905. out[3] = aw * bw - ay * by;
  82906. return out;
  82907. }
  82908. /**
  82909. * Rotates a quaternion by the given angle about the Z axis
  82910. *
  82911. * @param {quat} out quat receiving operation result
  82912. * @param {ReadonlyQuat} a quat to rotate
  82913. * @param {number} rad angle (in radians) to rotate
  82914. * @returns {quat} out
  82915. */
  82916. function rotateZ(out, a, rad) {
  82917. rad *= 0.5;
  82918. var ax = a[0],
  82919. ay = a[1],
  82920. az = a[2],
  82921. aw = a[3];
  82922. var bz = Math.sin(rad),
  82923. bw = Math.cos(rad);
  82924. out[0] = ax * bw + ay * bz;
  82925. out[1] = ay * bw - ax * bz;
  82926. out[2] = az * bw + aw * bz;
  82927. out[3] = aw * bw - az * bz;
  82928. return out;
  82929. }
  82930. /**
  82931. * Calculates the W component of a quat from the X, Y, and Z components.
  82932. * Assumes that quaternion is 1 unit in length.
  82933. * Any existing W component will be ignored.
  82934. *
  82935. * @param {quat} out the receiving quaternion
  82936. * @param {ReadonlyQuat} a quat to calculate W component of
  82937. * @returns {quat} out
  82938. */
  82939. function calculateW(out, a) {
  82940. var x = a[0],
  82941. y = a[1],
  82942. z = a[2];
  82943. out[0] = x;
  82944. out[1] = y;
  82945. out[2] = z;
  82946. out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
  82947. return out;
  82948. }
  82949. /**
  82950. * Performs a spherical linear interpolation between two quat
  82951. *
  82952. * @param {quat} out the receiving quaternion
  82953. * @param {ReadonlyQuat} a the first operand
  82954. * @param {ReadonlyQuat} b the second operand
  82955. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  82956. * @returns {quat} out
  82957. */
  82958. function slerp(out, a, b, t) {
  82959. // benchmarks:
  82960. // http://jsperf.com/quaternion-slerp-implementations
  82961. var ax = a[0],
  82962. ay = a[1],
  82963. az = a[2],
  82964. aw = a[3];
  82965. var bx = b[0],
  82966. by = b[1],
  82967. bz = b[2],
  82968. bw = b[3];
  82969. var omega, cosom, sinom, scale0, scale1; // calc cosine
  82970. cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary)
  82971. if (cosom < 0.0) {
  82972. cosom = -cosom;
  82973. bx = -bx;
  82974. by = -by;
  82975. bz = -bz;
  82976. bw = -bw;
  82977. } // calculate coefficients
  82978. if (1.0 - cosom > EPSILON) {
  82979. // standard case (slerp)
  82980. omega = Math.acos(cosom);
  82981. sinom = Math.sin(omega);
  82982. scale0 = Math.sin((1.0 - t) * omega) / sinom;
  82983. scale1 = Math.sin(t * omega) / sinom;
  82984. } else {
  82985. // "from" and "to" quaternions are very close
  82986. // ... so we can do a linear interpolation
  82987. scale0 = 1.0 - t;
  82988. scale1 = t;
  82989. } // calculate final values
  82990. out[0] = scale0 * ax + scale1 * bx;
  82991. out[1] = scale0 * ay + scale1 * by;
  82992. out[2] = scale0 * az + scale1 * bz;
  82993. out[3] = scale0 * aw + scale1 * bw;
  82994. return out;
  82995. }
  82996. /**
  82997. * Calculates the inverse of a quat
  82998. *
  82999. * @param {quat} out the receiving quaternion
  83000. * @param {ReadonlyQuat} a quat to calculate inverse of
  83001. * @returns {quat} out
  83002. */
  83003. function invert(out, a) {
  83004. var a0 = a[0],
  83005. a1 = a[1],
  83006. a2 = a[2],
  83007. a3 = a[3];
  83008. var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
  83009. var invDot = dot ? 1.0 / dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
  83010. out[0] = -a0 * invDot;
  83011. out[1] = -a1 * invDot;
  83012. out[2] = -a2 * invDot;
  83013. out[3] = a3 * invDot;
  83014. return out;
  83015. }
  83016. /**
  83017. * Calculates the conjugate of a quat
  83018. * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
  83019. *
  83020. * @param {quat} out the receiving quaternion
  83021. * @param {ReadonlyQuat} a quat to calculate conjugate of
  83022. * @returns {quat} out
  83023. */
  83024. function conjugate(out, a) {
  83025. out[0] = -a[0];
  83026. out[1] = -a[1];
  83027. out[2] = -a[2];
  83028. out[3] = a[3];
  83029. return out;
  83030. }
  83031. /**
  83032. * Creates a quaternion from the given 3x3 rotation matrix.
  83033. *
  83034. * NOTE: The resultant quaternion is not normalized, so you should be sure
  83035. * to renormalize the quaternion yourself where necessary.
  83036. *
  83037. * @param {quat} out the receiving quaternion
  83038. * @param {ReadonlyMat3} m rotation matrix
  83039. * @returns {quat} out
  83040. * @function
  83041. */
  83042. function fromMat3(out, m) {
  83043. // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
  83044. // article "Quaternion Calculus and Fast Animation".
  83045. var fTrace = m[0] + m[4] + m[8];
  83046. var fRoot;
  83047. if (fTrace > 0.0) {
  83048. // |w| > 1/2, may as well choose w > 1/2
  83049. fRoot = Math.sqrt(fTrace + 1.0); // 2w
  83050. out[3] = 0.5 * fRoot;
  83051. fRoot = 0.5 / fRoot; // 1/(4w)
  83052. out[0] = (m[5] - m[7]) * fRoot;
  83053. out[1] = (m[6] - m[2]) * fRoot;
  83054. out[2] = (m[1] - m[3]) * fRoot;
  83055. } else {
  83056. // |w| <= 1/2
  83057. var i = 0;
  83058. if (m[4] > m[0]) i = 1;
  83059. if (m[8] > m[i * 3 + i]) i = 2;
  83060. var j = (i + 1) % 3;
  83061. var k = (i + 2) % 3;
  83062. fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);
  83063. out[i] = 0.5 * fRoot;
  83064. fRoot = 0.5 / fRoot;
  83065. out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;
  83066. out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;
  83067. out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;
  83068. }
  83069. return out;
  83070. }
  83071. /**
  83072. * Adds two quat's
  83073. *
  83074. * @param {quat} out the receiving quaternion
  83075. * @param {ReadonlyQuat} a the first operand
  83076. * @param {ReadonlyQuat} b the second operand
  83077. * @returns {quat} out
  83078. * @function
  83079. */
  83080. var add = add$1;
  83081. /**
  83082. * Scales a quat by a scalar number
  83083. *
  83084. * @param {quat} out the receiving vector
  83085. * @param {ReadonlyQuat} a the vector to scale
  83086. * @param {Number} b amount to scale the vector by
  83087. * @returns {quat} out
  83088. * @function
  83089. */
  83090. var scale = scale$1;
  83091. /**
  83092. * Calculates the dot product of two quat's
  83093. *
  83094. * @param {ReadonlyQuat} a the first operand
  83095. * @param {ReadonlyQuat} b the second operand
  83096. * @returns {Number} dot product of a and b
  83097. * @function
  83098. */
  83099. var dot = dot$1;
  83100. /**
  83101. * Performs a linear interpolation between two quat's
  83102. *
  83103. * @param {quat} out the receiving quaternion
  83104. * @param {ReadonlyQuat} a the first operand
  83105. * @param {ReadonlyQuat} b the second operand
  83106. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  83107. * @returns {quat} out
  83108. * @function
  83109. */
  83110. var lerp$2 = lerp$1;
  83111. /**
  83112. * Calculates the length of a quat
  83113. *
  83114. * @param {ReadonlyQuat} a vector to calculate length of
  83115. * @returns {Number} length of a
  83116. */
  83117. var length = length$1;
  83118. /**
  83119. * Calculates the squared length of a quat
  83120. *
  83121. * @param {ReadonlyQuat} a vector to calculate squared length of
  83122. * @returns {Number} squared length of a
  83123. * @function
  83124. */
  83125. var squaredLength = squaredLength$1;
  83126. /**
  83127. * Normalize a quat
  83128. *
  83129. * @param {quat} out the receiving quaternion
  83130. * @param {ReadonlyQuat} a quaternion to normalize
  83131. * @returns {quat} out
  83132. * @function
  83133. */
  83134. var normalize = normalize$1;
  83135. /**
  83136. * Sets a quaternion to represent the shortest rotation from one
  83137. * vector to another.
  83138. *
  83139. * Both vectors are assumed to be unit length.
  83140. *
  83141. * @param {quat} out the receiving quaternion.
  83142. * @param {ReadonlyVec3} a the initial vector
  83143. * @param {ReadonlyVec3} b the destination vector
  83144. * @returns {quat} out
  83145. */
  83146. var rotationTo = function () {
  83147. var tmpvec3 = create$3();
  83148. var xUnitVec3 = fromValues(1, 0, 0);
  83149. var yUnitVec3 = fromValues(0, 1, 0);
  83150. return function (out, a, b) {
  83151. var dot = dot$2(a, b);
  83152. if (dot < -0.999999) {
  83153. cross(tmpvec3, xUnitVec3, a);
  83154. if (len(tmpvec3) < 0.000001) cross(tmpvec3, yUnitVec3, a);
  83155. normalize$2(tmpvec3, tmpvec3);
  83156. setAxisAngle(out, tmpvec3, Math.PI);
  83157. return out;
  83158. } else if (dot > 0.999999) {
  83159. out[0] = 0;
  83160. out[1] = 0;
  83161. out[2] = 0;
  83162. out[3] = 1;
  83163. return out;
  83164. } else {
  83165. cross(tmpvec3, a, b);
  83166. out[0] = tmpvec3[0];
  83167. out[1] = tmpvec3[1];
  83168. out[2] = tmpvec3[2];
  83169. out[3] = 1 + dot;
  83170. return normalize(out, out);
  83171. }
  83172. };
  83173. }();
  83174. /**
  83175. * Performs a spherical linear interpolation with two control points
  83176. *
  83177. * @param {quat} out the receiving quaternion
  83178. * @param {ReadonlyQuat} a the first operand
  83179. * @param {ReadonlyQuat} b the second operand
  83180. * @param {ReadonlyQuat} c the third operand
  83181. * @param {ReadonlyQuat} d the fourth operand
  83182. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  83183. * @returns {quat} out
  83184. */
  83185. (function () {
  83186. var temp1 = create();
  83187. var temp2 = create();
  83188. return function (out, a, b, c, d, t) {
  83189. slerp(temp1, a, d, t);
  83190. slerp(temp2, b, c, t);
  83191. slerp(out, temp1, temp2, 2 * t * (1 - t));
  83192. return out;
  83193. };
  83194. })();
  83195. /**
  83196. * Sets the specified quaternion with values corresponding to the given
  83197. * axes. Each axis is a vec3 and is expected to be unit length and
  83198. * perpendicular to all other specified axes.
  83199. *
  83200. * @param {ReadonlyVec3} view the vector representing the viewing direction
  83201. * @param {ReadonlyVec3} right the vector representing the local "right" direction
  83202. * @param {ReadonlyVec3} up the vector representing the local "up" direction
  83203. * @returns {quat} out
  83204. */
  83205. (function () {
  83206. var matr = create$2();
  83207. return function (out, view, right, up) {
  83208. matr[0] = right[0];
  83209. matr[3] = right[1];
  83210. matr[6] = right[2];
  83211. matr[1] = up[0];
  83212. matr[4] = up[1];
  83213. matr[7] = up[2];
  83214. matr[2] = -view[0];
  83215. matr[5] = -view[1];
  83216. matr[8] = -view[2];
  83217. return normalize(out, fromMat3(out, matr));
  83218. };
  83219. })();
  83220. const IDENTITY_QUATERNION = [0, 0, 0, 1];
  83221. class Quaternion$1 extends MathArray {
  83222. constructor(x = 0, y = 0, z = 0, w = 1) {
  83223. super(-0, -0, -0, -0);
  83224. if (Array.isArray(x) && arguments.length === 1) {
  83225. this.copy(x);
  83226. } else {
  83227. this.set(x, y, z, w);
  83228. }
  83229. }
  83230. copy(array) {
  83231. this[0] = array[0];
  83232. this[1] = array[1];
  83233. this[2] = array[2];
  83234. this[3] = array[3];
  83235. return this.check();
  83236. }
  83237. set(x, y, z, w) {
  83238. this[0] = x;
  83239. this[1] = y;
  83240. this[2] = z;
  83241. this[3] = w;
  83242. return this.check();
  83243. }
  83244. fromMatrix3(m) {
  83245. fromMat3(this, m);
  83246. return this.check();
  83247. }
  83248. identity() {
  83249. identity(this);
  83250. return this.check();
  83251. }
  83252. fromAxisRotation(axis, rad) {
  83253. setAxisAngle(this, axis, rad);
  83254. return this.check();
  83255. }
  83256. setAxisAngle(axis, rad) {
  83257. return this.fromAxisRotation(axis, rad);
  83258. }
  83259. get ELEMENTS() {
  83260. return 4;
  83261. }
  83262. get x() {
  83263. return this[0];
  83264. }
  83265. set x(value) {
  83266. this[0] = checkNumber(value);
  83267. }
  83268. get y() {
  83269. return this[1];
  83270. }
  83271. set y(value) {
  83272. this[1] = checkNumber(value);
  83273. }
  83274. get z() {
  83275. return this[2];
  83276. }
  83277. set z(value) {
  83278. this[2] = checkNumber(value);
  83279. }
  83280. get w() {
  83281. return this[3];
  83282. }
  83283. set w(value) {
  83284. this[3] = checkNumber(value);
  83285. }
  83286. len() {
  83287. return length(this);
  83288. }
  83289. lengthSquared() {
  83290. return squaredLength(this);
  83291. }
  83292. dot(a, b) {
  83293. if (b !== undefined) {
  83294. throw new Error('Quaternion.dot only takes one argument');
  83295. }
  83296. return dot(this, a);
  83297. }
  83298. rotationTo(vectorA, vectorB) {
  83299. rotationTo(this, vectorA, vectorB);
  83300. return this.check();
  83301. }
  83302. add(a, b) {
  83303. if (b !== undefined) {
  83304. throw new Error('Quaternion.add only takes one argument');
  83305. }
  83306. add(this, this, a);
  83307. return this.check();
  83308. }
  83309. calculateW() {
  83310. calculateW(this, this);
  83311. return this.check();
  83312. }
  83313. conjugate() {
  83314. conjugate(this, this);
  83315. return this.check();
  83316. }
  83317. invert() {
  83318. invert(this, this);
  83319. return this.check();
  83320. }
  83321. lerp(a, b, t) {
  83322. lerp$2(this, a, b, t);
  83323. return this.check();
  83324. }
  83325. multiplyRight(a, b) {
  83326. assert$4(!b);
  83327. multiply(this, this, a);
  83328. return this.check();
  83329. }
  83330. multiplyLeft(a, b) {
  83331. assert$4(!b);
  83332. multiply(this, a, this);
  83333. return this.check();
  83334. }
  83335. normalize() {
  83336. const length = this.len();
  83337. const l = length > 0 ? 1 / length : 0;
  83338. this[0] = this[0] * l;
  83339. this[1] = this[1] * l;
  83340. this[2] = this[2] * l;
  83341. this[3] = this[3] * l;
  83342. if (length === 0) {
  83343. this[3] = 1;
  83344. }
  83345. return this.check();
  83346. }
  83347. rotateX(rad) {
  83348. rotateX(this, this, rad);
  83349. return this.check();
  83350. }
  83351. rotateY(rad) {
  83352. rotateY(this, this, rad);
  83353. return this.check();
  83354. }
  83355. rotateZ(rad) {
  83356. rotateZ(this, this, rad);
  83357. return this.check();
  83358. }
  83359. scale(b) {
  83360. scale(this, this, b);
  83361. return this.check();
  83362. }
  83363. slerp(start, target, ratio) {
  83364. switch (arguments.length) {
  83365. case 1:
  83366. ({
  83367. start = IDENTITY_QUATERNION,
  83368. target,
  83369. ratio
  83370. } = arguments[0]);
  83371. break;
  83372. case 2:
  83373. [target, ratio] = arguments;
  83374. start = this;
  83375. break;
  83376. }
  83377. slerp(this, start, target, ratio);
  83378. return this.check();
  83379. }
  83380. transformVector4(vector, result = vector) {
  83381. transformQuat(result, vector, this);
  83382. return checkVector(result, 4);
  83383. }
  83384. lengthSq() {
  83385. return this.lengthSquared();
  83386. }
  83387. setFromAxisAngle(axis, rad) {
  83388. return this.setAxisAngle(axis, rad);
  83389. }
  83390. premultiply(a, b) {
  83391. return this.multiplyLeft(a, b);
  83392. }
  83393. multiply(a, b) {
  83394. return this.multiplyRight(a, b);
  83395. }
  83396. }
  83397. var _MathUtils = {
  83398. EPSILON1: 1e-1,
  83399. EPSILON2: 1e-2,
  83400. EPSILON3: 1e-3,
  83401. EPSILON4: 1e-4,
  83402. EPSILON5: 1e-5,
  83403. EPSILON6: 1e-6,
  83404. EPSILON7: 1e-7,
  83405. EPSILON8: 1e-8,
  83406. EPSILON9: 1e-9,
  83407. EPSILON10: 1e-10,
  83408. EPSILON11: 1e-11,
  83409. EPSILON12: 1e-12,
  83410. EPSILON13: 1e-13,
  83411. EPSILON14: 1e-14,
  83412. EPSILON15: 1e-15,
  83413. EPSILON16: 1e-16,
  83414. EPSILON17: 1e-17,
  83415. EPSILON18: 1e-18,
  83416. EPSILON19: 1e-19,
  83417. EPSILON20: 1e-20,
  83418. PI_OVER_TWO: Math.PI / 2,
  83419. PI_OVER_FOUR: Math.PI / 4,
  83420. PI_OVER_SIX: Math.PI / 6,
  83421. TWO_PI: Math.PI * 2
  83422. };
  83423. const WGS84_RADIUS_X$1 = 6378137.0;
  83424. const WGS84_RADIUS_Y$1 = 6378137.0;
  83425. const WGS84_RADIUS_Z$1 = 6356752.3142451793;
  83426. const noop = x => x;
  83427. const scratchVector$6 = new Vector3$1();
  83428. function fromCartographic(cartographic, result, map = noop) {
  83429. if (isArray(cartographic)) {
  83430. result[0] = map(cartographic[0]);
  83431. result[1] = map(cartographic[1]);
  83432. result[2] = cartographic[2];
  83433. } else if ('longitude' in cartographic) {
  83434. result[0] = map(cartographic.longitude);
  83435. result[1] = map(cartographic.latitude);
  83436. result[2] = cartographic.height;
  83437. } else {
  83438. result[0] = map(cartographic.x);
  83439. result[1] = map(cartographic.y);
  83440. result[2] = cartographic.z;
  83441. }
  83442. return result;
  83443. }
  83444. function fromCartographicToRadians(cartographic, vector = scratchVector$6) {
  83445. return fromCartographic(cartographic, vector, config$2._cartographicRadians ? noop : toRadians);
  83446. }
  83447. function toCartographic(vector, cartographic, map = noop) {
  83448. if (isArray(cartographic)) {
  83449. cartographic[0] = map(vector[0]);
  83450. cartographic[1] = map(vector[1]);
  83451. cartographic[2] = vector[2];
  83452. } else if ('longitude' in cartographic) {
  83453. cartographic.longitude = map(vector[0]);
  83454. cartographic.latitude = map(vector[1]);
  83455. cartographic.height = vector[2];
  83456. } else {
  83457. cartographic.x = map(vector[0]);
  83458. cartographic.y = map(vector[1]);
  83459. cartographic.z = vector[2];
  83460. }
  83461. return cartographic;
  83462. }
  83463. function toCartographicFromRadians(vector, cartographic) {
  83464. return toCartographic(vector, cartographic, config$2._cartographicRadians ? noop : toDegrees);
  83465. }
  83466. const scratchVector$5 = new Vector3$1();
  83467. const scaleToGeodeticSurfaceIntersection = new Vector3$1();
  83468. const scaleToGeodeticSurfaceGradient = new Vector3$1();
  83469. function scaleToGeodeticSurface(cartesian, ellipsoid, result = new Vector3$1()) {
  83470. const {
  83471. oneOverRadii,
  83472. oneOverRadiiSquared,
  83473. centerToleranceSquared
  83474. } = ellipsoid;
  83475. scratchVector$5.from(cartesian);
  83476. const positionX = cartesian.x;
  83477. const positionY = cartesian.y;
  83478. const positionZ = cartesian.z;
  83479. const oneOverRadiiX = oneOverRadii.x;
  83480. const oneOverRadiiY = oneOverRadii.y;
  83481. const oneOverRadiiZ = oneOverRadii.z;
  83482. const x2 = positionX * positionX * oneOverRadiiX * oneOverRadiiX;
  83483. const y2 = positionY * positionY * oneOverRadiiY * oneOverRadiiY;
  83484. const z2 = positionZ * positionZ * oneOverRadiiZ * oneOverRadiiZ;
  83485. const squaredNorm = x2 + y2 + z2;
  83486. const ratio = Math.sqrt(1.0 / squaredNorm);
  83487. if (!Number.isFinite(ratio)) {
  83488. return undefined;
  83489. }
  83490. const intersection = scaleToGeodeticSurfaceIntersection;
  83491. intersection.copy(cartesian).scale(ratio);
  83492. if (squaredNorm < centerToleranceSquared) {
  83493. return intersection.to(result);
  83494. }
  83495. const oneOverRadiiSquaredX = oneOverRadiiSquared.x;
  83496. const oneOverRadiiSquaredY = oneOverRadiiSquared.y;
  83497. const oneOverRadiiSquaredZ = oneOverRadiiSquared.z;
  83498. const gradient = scaleToGeodeticSurfaceGradient;
  83499. gradient.set(intersection.x * oneOverRadiiSquaredX * 2.0, intersection.y * oneOverRadiiSquaredY * 2.0, intersection.z * oneOverRadiiSquaredZ * 2.0);
  83500. let lambda = (1.0 - ratio) * cartesian.len() / (0.5 * gradient.len());
  83501. let correction = 0.0;
  83502. let xMultiplier;
  83503. let yMultiplier;
  83504. let zMultiplier;
  83505. let func;
  83506. do {
  83507. lambda -= correction;
  83508. xMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredX);
  83509. yMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredY);
  83510. zMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredZ);
  83511. const xMultiplier2 = xMultiplier * xMultiplier;
  83512. const yMultiplier2 = yMultiplier * yMultiplier;
  83513. const zMultiplier2 = zMultiplier * zMultiplier;
  83514. const xMultiplier3 = xMultiplier2 * xMultiplier;
  83515. const yMultiplier3 = yMultiplier2 * yMultiplier;
  83516. const zMultiplier3 = zMultiplier2 * zMultiplier;
  83517. func = x2 * xMultiplier2 + y2 * yMultiplier2 + z2 * zMultiplier2 - 1.0;
  83518. const denominator = x2 * xMultiplier3 * oneOverRadiiSquaredX + y2 * yMultiplier3 * oneOverRadiiSquaredY + z2 * zMultiplier3 * oneOverRadiiSquaredZ;
  83519. const derivative = -2.0 * denominator;
  83520. correction = func / derivative;
  83521. } while (Math.abs(func) > _MathUtils.EPSILON12);
  83522. return scratchVector$5.scale([xMultiplier, yMultiplier, zMultiplier]).to(result);
  83523. }
  83524. const EPSILON14 = 1e-14;
  83525. const scratchOrigin = new Vector3$1();
  83526. const VECTOR_PRODUCT_LOCAL_FRAME = {
  83527. up: {
  83528. south: 'east',
  83529. north: 'west',
  83530. west: 'south',
  83531. east: 'north'
  83532. },
  83533. down: {
  83534. south: 'west',
  83535. north: 'east',
  83536. west: 'north',
  83537. east: 'south'
  83538. },
  83539. south: {
  83540. up: 'west',
  83541. down: 'east',
  83542. west: 'down',
  83543. east: 'up'
  83544. },
  83545. north: {
  83546. up: 'east',
  83547. down: 'west',
  83548. west: 'up',
  83549. east: 'down'
  83550. },
  83551. west: {
  83552. up: 'north',
  83553. down: 'south',
  83554. north: 'down',
  83555. south: 'up'
  83556. },
  83557. east: {
  83558. up: 'south',
  83559. down: 'north',
  83560. north: 'up',
  83561. south: 'down'
  83562. }
  83563. };
  83564. const degeneratePositionLocalFrame = {
  83565. north: [-1, 0, 0],
  83566. east: [0, 1, 0],
  83567. up: [0, 0, 1],
  83568. south: [1, 0, 0],
  83569. west: [0, -1, 0],
  83570. down: [0, 0, -1]
  83571. };
  83572. const scratchAxisVectors = {
  83573. east: new Vector3$1(),
  83574. north: new Vector3$1(),
  83575. up: new Vector3$1(),
  83576. west: new Vector3$1(),
  83577. south: new Vector3$1(),
  83578. down: new Vector3$1()
  83579. };
  83580. const scratchVector1 = new Vector3$1();
  83581. const scratchVector2$1 = new Vector3$1();
  83582. const scratchVector3$1 = new Vector3$1();
  83583. function localFrameToFixedFrame(ellipsoid, firstAxis, secondAxis, thirdAxis, cartesianOrigin, result) {
  83584. const thirdAxisInferred = VECTOR_PRODUCT_LOCAL_FRAME[firstAxis] && VECTOR_PRODUCT_LOCAL_FRAME[firstAxis][secondAxis];
  83585. assert$4(thirdAxisInferred && (!thirdAxis || thirdAxis === thirdAxisInferred));
  83586. let firstAxisVector;
  83587. let secondAxisVector;
  83588. let thirdAxisVector;
  83589. const origin = scratchOrigin.copy(cartesianOrigin);
  83590. const atPole = equals$1(origin.x, 0.0, EPSILON14) && equals$1(origin.y, 0.0, EPSILON14);
  83591. if (atPole) {
  83592. const sign = Math.sign(origin.z);
  83593. firstAxisVector = scratchVector1.fromArray(degeneratePositionLocalFrame[firstAxis]);
  83594. if (firstAxis !== 'east' && firstAxis !== 'west') {
  83595. firstAxisVector.scale(sign);
  83596. }
  83597. secondAxisVector = scratchVector2$1.fromArray(degeneratePositionLocalFrame[secondAxis]);
  83598. if (secondAxis !== 'east' && secondAxis !== 'west') {
  83599. secondAxisVector.scale(sign);
  83600. }
  83601. thirdAxisVector = scratchVector3$1.fromArray(degeneratePositionLocalFrame[thirdAxis]);
  83602. if (thirdAxis !== 'east' && thirdAxis !== 'west') {
  83603. thirdAxisVector.scale(sign);
  83604. }
  83605. } else {
  83606. const {
  83607. up,
  83608. east,
  83609. north
  83610. } = scratchAxisVectors;
  83611. east.set(-origin.y, origin.x, 0.0).normalize();
  83612. ellipsoid.geodeticSurfaceNormal(origin, up);
  83613. north.copy(up).cross(east);
  83614. const {
  83615. down,
  83616. west,
  83617. south
  83618. } = scratchAxisVectors;
  83619. down.copy(up).scale(-1);
  83620. west.copy(east).scale(-1);
  83621. south.copy(north).scale(-1);
  83622. firstAxisVector = scratchAxisVectors[firstAxis];
  83623. secondAxisVector = scratchAxisVectors[secondAxis];
  83624. thirdAxisVector = scratchAxisVectors[thirdAxis];
  83625. }
  83626. result[0] = firstAxisVector.x;
  83627. result[1] = firstAxisVector.y;
  83628. result[2] = firstAxisVector.z;
  83629. result[3] = 0.0;
  83630. result[4] = secondAxisVector.x;
  83631. result[5] = secondAxisVector.y;
  83632. result[6] = secondAxisVector.z;
  83633. result[7] = 0.0;
  83634. result[8] = thirdAxisVector.x;
  83635. result[9] = thirdAxisVector.y;
  83636. result[10] = thirdAxisVector.z;
  83637. result[11] = 0.0;
  83638. result[12] = origin.x;
  83639. result[13] = origin.y;
  83640. result[14] = origin.z;
  83641. result[15] = 1.0;
  83642. return result;
  83643. }
  83644. const scratchVector$4 = new Vector3$1();
  83645. const scratchNormal$2 = new Vector3$1();
  83646. const scratchK = new Vector3$1();
  83647. const scratchPosition$2 = new Vector3$1();
  83648. const scratchHeight = new Vector3$1();
  83649. const scratchCartesian = new Vector3$1();
  83650. let wgs84;
  83651. class Ellipsoid {
  83652. static get WGS84() {
  83653. wgs84 = wgs84 || new Ellipsoid(WGS84_RADIUS_X$1, WGS84_RADIUS_Y$1, WGS84_RADIUS_Z$1);
  83654. return wgs84;
  83655. }
  83656. constructor(x = 0.0, y = 0.0, z = 0.0) {
  83657. assert$4(x >= 0.0);
  83658. assert$4(y >= 0.0);
  83659. assert$4(z >= 0.0);
  83660. this.radii = new Vector3$1(x, y, z);
  83661. this.radiiSquared = new Vector3$1(x * x, y * y, z * z);
  83662. this.radiiToTheFourth = new Vector3$1(x * x * x * x, y * y * y * y, z * z * z * z);
  83663. this.oneOverRadii = new Vector3$1(x === 0.0 ? 0.0 : 1.0 / x, y === 0.0 ? 0.0 : 1.0 / y, z === 0.0 ? 0.0 : 1.0 / z);
  83664. this.oneOverRadiiSquared = new Vector3$1(x === 0.0 ? 0.0 : 1.0 / (x * x), y === 0.0 ? 0.0 : 1.0 / (y * y), z === 0.0 ? 0.0 : 1.0 / (z * z));
  83665. this.minimumRadius = Math.min(x, y, z);
  83666. this.maximumRadius = Math.max(x, y, z);
  83667. this.centerToleranceSquared = _MathUtils.EPSILON1;
  83668. if (this.radiiSquared.z !== 0) {
  83669. this.squaredXOverSquaredZ = this.radiiSquared.x / this.radiiSquared.z;
  83670. }
  83671. Object.freeze(this);
  83672. }
  83673. equals(right) {
  83674. return this === right || Boolean(right && this.radii.equals(right.radii));
  83675. }
  83676. toString() {
  83677. return this.radii.toString();
  83678. }
  83679. cartographicToCartesian(cartographic, result = [0, 0, 0]) {
  83680. const normal = scratchNormal$2;
  83681. const k = scratchK;
  83682. const [,, height] = cartographic;
  83683. this.geodeticSurfaceNormalCartographic(cartographic, normal);
  83684. k.copy(this.radiiSquared).scale(normal);
  83685. const gamma = Math.sqrt(normal.dot(k));
  83686. k.scale(1 / gamma);
  83687. normal.scale(height);
  83688. k.add(normal);
  83689. return k.to(result);
  83690. }
  83691. cartesianToCartographic(cartesian, result = [0, 0, 0]) {
  83692. scratchCartesian.from(cartesian);
  83693. const point = this.scaleToGeodeticSurface(scratchCartesian, scratchPosition$2);
  83694. if (!point) {
  83695. return undefined;
  83696. }
  83697. const normal = this.geodeticSurfaceNormal(point, scratchNormal$2);
  83698. const h = scratchHeight;
  83699. h.copy(scratchCartesian).subtract(point);
  83700. const longitude = Math.atan2(normal.y, normal.x);
  83701. const latitude = Math.asin(normal.z);
  83702. const height = Math.sign(dot$2(h, scratchCartesian)) * length$2(h);
  83703. return toCartographicFromRadians([longitude, latitude, height], result);
  83704. }
  83705. eastNorthUpToFixedFrame(origin, result = new Matrix4$1()) {
  83706. return localFrameToFixedFrame(this, 'east', 'north', 'up', origin, result);
  83707. }
  83708. localFrameToFixedFrame(firstAxis, secondAxis, thirdAxis, origin, result = new Matrix4$1()) {
  83709. return localFrameToFixedFrame(this, firstAxis, secondAxis, thirdAxis, origin, result);
  83710. }
  83711. geocentricSurfaceNormal(cartesian, result = [0, 0, 0]) {
  83712. return scratchVector$4.from(cartesian).normalize().to(result);
  83713. }
  83714. geodeticSurfaceNormalCartographic(cartographic, result = [0, 0, 0]) {
  83715. const cartographicVectorRadians = fromCartographicToRadians(cartographic);
  83716. const longitude = cartographicVectorRadians[0];
  83717. const latitude = cartographicVectorRadians[1];
  83718. const cosLatitude = Math.cos(latitude);
  83719. scratchVector$4.set(cosLatitude * Math.cos(longitude), cosLatitude * Math.sin(longitude), Math.sin(latitude)).normalize();
  83720. return scratchVector$4.to(result);
  83721. }
  83722. geodeticSurfaceNormal(cartesian, result = [0, 0, 0]) {
  83723. return scratchVector$4.from(cartesian).scale(this.oneOverRadiiSquared).normalize().to(result);
  83724. }
  83725. scaleToGeodeticSurface(cartesian, result) {
  83726. return scaleToGeodeticSurface(cartesian, this, result);
  83727. }
  83728. scaleToGeocentricSurface(cartesian, result = [0, 0, 0]) {
  83729. scratchPosition$2.from(cartesian);
  83730. const positionX = scratchPosition$2.x;
  83731. const positionY = scratchPosition$2.y;
  83732. const positionZ = scratchPosition$2.z;
  83733. const oneOverRadiiSquared = this.oneOverRadiiSquared;
  83734. const beta = 1.0 / Math.sqrt(positionX * positionX * oneOverRadiiSquared.x + positionY * positionY * oneOverRadiiSquared.y + positionZ * positionZ * oneOverRadiiSquared.z);
  83735. return scratchPosition$2.multiplyScalar(beta).to(result);
  83736. }
  83737. transformPositionToScaledSpace(position, result = [0, 0, 0]) {
  83738. return scratchPosition$2.from(position).scale(this.oneOverRadii).to(result);
  83739. }
  83740. transformPositionFromScaledSpace(position, result = [0, 0, 0]) {
  83741. return scratchPosition$2.from(position).scale(this.radii).to(result);
  83742. }
  83743. getSurfaceNormalIntersectionWithZAxis(position, buffer = 0.0, result = [0, 0, 0]) {
  83744. assert$4(equals$1(this.radii.x, this.radii.y, _MathUtils.EPSILON15));
  83745. assert$4(this.radii.z > 0);
  83746. scratchPosition$2.from(position);
  83747. const z = scratchPosition$2.z * (1 - this.squaredXOverSquaredZ);
  83748. if (Math.abs(z) >= this.radii.z - buffer) {
  83749. return undefined;
  83750. }
  83751. return scratchPosition$2.set(0.0, 0.0, z).to(result);
  83752. }
  83753. }
  83754. class DoublyLinkedListNode {
  83755. constructor(item, previous, next) {
  83756. _defineProperty(this, "item", void 0);
  83757. _defineProperty(this, "previous", void 0);
  83758. _defineProperty(this, "next", void 0);
  83759. this.item = item;
  83760. this.previous = previous;
  83761. this.next = next;
  83762. }
  83763. }
  83764. class DoublyLinkedList {
  83765. constructor() {
  83766. _defineProperty(this, "head", null);
  83767. _defineProperty(this, "tail", null);
  83768. _defineProperty(this, "_length", 0);
  83769. }
  83770. get length() {
  83771. return this._length;
  83772. }
  83773. add(item) {
  83774. const node = new DoublyLinkedListNode(item, this.tail, null);
  83775. if (this.tail) {
  83776. this.tail.next = node;
  83777. this.tail = node;
  83778. } else {
  83779. this.head = node;
  83780. this.tail = node;
  83781. }
  83782. ++this._length;
  83783. return node;
  83784. }
  83785. remove(node) {
  83786. if (!node) {
  83787. return;
  83788. }
  83789. if (node.previous && node.next) {
  83790. node.previous.next = node.next;
  83791. node.next.previous = node.previous;
  83792. } else if (node.previous) {
  83793. node.previous.next = null;
  83794. this.tail = node.previous;
  83795. } else if (node.next) {
  83796. node.next.previous = null;
  83797. this.head = node.next;
  83798. } else {
  83799. this.head = null;
  83800. this.tail = null;
  83801. }
  83802. node.next = null;
  83803. node.previous = null;
  83804. --this._length;
  83805. }
  83806. splice(node, nextNode) {
  83807. if (node === nextNode) {
  83808. return;
  83809. }
  83810. this.remove(nextNode);
  83811. this._insert(node, nextNode);
  83812. }
  83813. _insert(node, nextNode) {
  83814. const oldNodeNext = node.next;
  83815. node.next = nextNode;
  83816. if (this.tail === node) {
  83817. this.tail = nextNode;
  83818. } else {
  83819. oldNodeNext.previous = nextNode;
  83820. }
  83821. nextNode.next = oldNodeNext;
  83822. nextNode.previous = node;
  83823. ++this._length;
  83824. }
  83825. }
  83826. function defined$5(x) {
  83827. return x !== undefined && x !== null;
  83828. }
  83829. class TilesetCache {
  83830. constructor() {
  83831. _defineProperty(this, "_list", void 0);
  83832. _defineProperty(this, "_sentinel", void 0);
  83833. _defineProperty(this, "_trimTiles", void 0);
  83834. this._list = new DoublyLinkedList();
  83835. this._sentinel = this._list.add('sentinel');
  83836. this._trimTiles = false;
  83837. }
  83838. reset() {
  83839. this._list.splice(this._list.tail, this._sentinel);
  83840. }
  83841. touch(tile) {
  83842. const node = tile._cacheNode;
  83843. if (defined$5(node)) {
  83844. this._list.splice(this._sentinel, node);
  83845. }
  83846. }
  83847. add(tileset, tile, addCallback) {
  83848. if (!defined$5(tile._cacheNode)) {
  83849. tile._cacheNode = this._list.add(tile);
  83850. if (addCallback) {
  83851. addCallback(tileset, tile);
  83852. }
  83853. }
  83854. }
  83855. unloadTile(tileset, tile, unloadCallback) {
  83856. const node = tile._cacheNode;
  83857. if (!defined$5(node)) {
  83858. return;
  83859. }
  83860. this._list.remove(node);
  83861. tile._cacheNode = undefined;
  83862. if (unloadCallback) {
  83863. unloadCallback(tileset, tile);
  83864. }
  83865. }
  83866. unloadTiles(tileset, unloadCallback) {
  83867. const trimTiles = this._trimTiles;
  83868. this._trimTiles = false;
  83869. const list = this._list;
  83870. const maximumMemoryUsageInBytes = tileset.maximumMemoryUsage * 1024 * 1024;
  83871. const sentinel = this._sentinel;
  83872. let node = list.head;
  83873. while (node !== sentinel && (tileset.gpuMemoryUsageInBytes > maximumMemoryUsageInBytes || trimTiles)) {
  83874. const tile = node.item;
  83875. node = node.next;
  83876. this.unloadTile(tileset, tile, unloadCallback);
  83877. }
  83878. }
  83879. trim() {
  83880. this._trimTiles = true;
  83881. }
  83882. }
  83883. function calculateTransformProps(tileHeader, tile) {
  83884. assert$7(tileHeader);
  83885. assert$7(tile);
  83886. const {
  83887. rtcCenter,
  83888. gltfUpAxis
  83889. } = tile;
  83890. const {
  83891. computedTransform,
  83892. boundingVolume: {
  83893. center
  83894. }
  83895. } = tileHeader;
  83896. let modelMatrix = new Matrix4$1(computedTransform);
  83897. if (rtcCenter) {
  83898. modelMatrix.translate(rtcCenter);
  83899. }
  83900. switch (gltfUpAxis) {
  83901. case 'Z':
  83902. break;
  83903. case 'Y':
  83904. const rotationY = new Matrix4$1().rotateX(Math.PI / 2);
  83905. modelMatrix = modelMatrix.multiplyRight(rotationY);
  83906. break;
  83907. case 'X':
  83908. const rotationX = new Matrix4$1().rotateY(-Math.PI / 2);
  83909. modelMatrix = modelMatrix.multiplyRight(rotationX);
  83910. break;
  83911. }
  83912. if (tile.isQuantized) {
  83913. modelMatrix.translate(tile.quantizedVolumeOffset).scale(tile.quantizedVolumeScale);
  83914. }
  83915. const cartesianOrigin = new Vector3$1(center);
  83916. tile.cartesianModelMatrix = modelMatrix;
  83917. tile.cartesianOrigin = cartesianOrigin;
  83918. const cartographicOrigin = Ellipsoid.WGS84.cartesianToCartographic(cartesianOrigin, new Vector3$1());
  83919. const fromFixedFrameMatrix = Ellipsoid.WGS84.eastNorthUpToFixedFrame(cartesianOrigin);
  83920. const toFixedFrameMatrix = fromFixedFrameMatrix.invert();
  83921. tile.cartographicModelMatrix = toFixedFrameMatrix.multiplyRight(modelMatrix);
  83922. tile.cartographicOrigin = cartographicOrigin;
  83923. if (!tile.coordinateSystem) {
  83924. tile.modelMatrix = tile.cartographicModelMatrix;
  83925. }
  83926. }
  83927. const INTERSECTION = Object.freeze({
  83928. OUTSIDE: -1,
  83929. INTERSECTING: 0,
  83930. INSIDE: 1
  83931. });
  83932. new Vector3$1();
  83933. new Vector3$1();
  83934. const scratchVector$3 = new Vector3$1();
  83935. const scratchVector2 = new Vector3$1();
  83936. class BoundingSphere {
  83937. constructor(center = [0, 0, 0], radius = 0.0) {
  83938. this.radius = -0;
  83939. this.center = new Vector3$1();
  83940. this.fromCenterRadius(center, radius);
  83941. }
  83942. fromCenterRadius(center, radius) {
  83943. this.center.from(center);
  83944. this.radius = radius;
  83945. return this;
  83946. }
  83947. fromCornerPoints(corner, oppositeCorner) {
  83948. oppositeCorner = scratchVector$3.from(oppositeCorner);
  83949. this.center = new Vector3$1().from(corner).add(oppositeCorner).scale(0.5);
  83950. this.radius = this.center.distance(oppositeCorner);
  83951. return this;
  83952. }
  83953. equals(right) {
  83954. return this === right || Boolean(right) && this.center.equals(right.center) && this.radius === right.radius;
  83955. }
  83956. clone() {
  83957. return new BoundingSphere(this.center, this.radius);
  83958. }
  83959. union(boundingSphere) {
  83960. const leftCenter = this.center;
  83961. const leftRadius = this.radius;
  83962. const rightCenter = boundingSphere.center;
  83963. const rightRadius = boundingSphere.radius;
  83964. const toRightCenter = scratchVector$3.copy(rightCenter).subtract(leftCenter);
  83965. const centerSeparation = toRightCenter.magnitude();
  83966. if (leftRadius >= centerSeparation + rightRadius) {
  83967. return this.clone();
  83968. }
  83969. if (rightRadius >= centerSeparation + leftRadius) {
  83970. return boundingSphere.clone();
  83971. }
  83972. const halfDistanceBetweenTangentPoints = (leftRadius + centerSeparation + rightRadius) * 0.5;
  83973. scratchVector2.copy(toRightCenter).scale((-leftRadius + halfDistanceBetweenTangentPoints) / centerSeparation).add(leftCenter);
  83974. this.center.copy(scratchVector2);
  83975. this.radius = halfDistanceBetweenTangentPoints;
  83976. return this;
  83977. }
  83978. expand(point) {
  83979. point = scratchVector$3.from(point);
  83980. const radius = point.subtract(this.center).magnitude();
  83981. if (radius > this.radius) {
  83982. this.radius = radius;
  83983. }
  83984. return this;
  83985. }
  83986. transform(transform) {
  83987. this.center.transform(transform);
  83988. const scale = getScaling(scratchVector$3, transform);
  83989. this.radius = Math.max(scale[0], Math.max(scale[1], scale[2])) * this.radius;
  83990. return this;
  83991. }
  83992. distanceSquaredTo(point) {
  83993. const d = this.distanceTo(point);
  83994. return d * d;
  83995. }
  83996. distanceTo(point) {
  83997. point = scratchVector$3.from(point);
  83998. const delta = point.subtract(this.center);
  83999. return Math.max(0, delta.len() - this.radius);
  84000. }
  84001. intersectPlane(plane) {
  84002. const center = this.center;
  84003. const radius = this.radius;
  84004. const normal = plane.normal;
  84005. const distanceToPlane = normal.dot(center) + plane.distance;
  84006. if (distanceToPlane < -radius) {
  84007. return INTERSECTION.OUTSIDE;
  84008. }
  84009. if (distanceToPlane < radius) {
  84010. return INTERSECTION.INTERSECTING;
  84011. }
  84012. return INTERSECTION.INSIDE;
  84013. }
  84014. }
  84015. const scratchVector3 = new Vector3$1();
  84016. const scratchOffset = new Vector3$1();
  84017. const scratchVectorU = new Vector3$1();
  84018. const scratchVectorV = new Vector3$1();
  84019. const scratchVectorW = new Vector3$1();
  84020. const scratchCorner = new Vector3$1();
  84021. const scratchToCenter = new Vector3$1();
  84022. const MATRIX3 = {
  84023. COLUMN0ROW0: 0,
  84024. COLUMN0ROW1: 1,
  84025. COLUMN0ROW2: 2,
  84026. COLUMN1ROW0: 3,
  84027. COLUMN1ROW1: 4,
  84028. COLUMN1ROW2: 5,
  84029. COLUMN2ROW0: 6,
  84030. COLUMN2ROW1: 7,
  84031. COLUMN2ROW2: 8
  84032. };
  84033. class OrientedBoundingBox {
  84034. constructor(center = [0, 0, 0], halfAxes = [0, 0, 0, 0, 0, 0, 0, 0, 0]) {
  84035. this.center = new Vector3$1().from(center);
  84036. this.halfAxes = new Matrix3$1(halfAxes);
  84037. }
  84038. get halfSize() {
  84039. const xAxis = this.halfAxes.getColumn(0);
  84040. const yAxis = this.halfAxes.getColumn(1);
  84041. const zAxis = this.halfAxes.getColumn(2);
  84042. return [new Vector3$1(xAxis).len(), new Vector3$1(yAxis).len(), new Vector3$1(zAxis).len()];
  84043. }
  84044. get quaternion() {
  84045. const xAxis = this.halfAxes.getColumn(0);
  84046. const yAxis = this.halfAxes.getColumn(1);
  84047. const zAxis = this.halfAxes.getColumn(2);
  84048. const normXAxis = new Vector3$1(xAxis).normalize();
  84049. const normYAxis = new Vector3$1(yAxis).normalize();
  84050. const normZAxis = new Vector3$1(zAxis).normalize();
  84051. return new Quaternion$1().fromMatrix3(new Matrix3$1([...normXAxis, ...normYAxis, ...normZAxis]));
  84052. }
  84053. fromCenterHalfSizeQuaternion(center, halfSize, quaternion) {
  84054. const quaternionObject = new Quaternion$1(quaternion);
  84055. const directionsMatrix = new Matrix3$1().fromQuaternion(quaternionObject);
  84056. directionsMatrix[0] = directionsMatrix[0] * halfSize[0];
  84057. directionsMatrix[1] = directionsMatrix[1] * halfSize[0];
  84058. directionsMatrix[2] = directionsMatrix[2] * halfSize[0];
  84059. directionsMatrix[3] = directionsMatrix[3] * halfSize[1];
  84060. directionsMatrix[4] = directionsMatrix[4] * halfSize[1];
  84061. directionsMatrix[5] = directionsMatrix[5] * halfSize[1];
  84062. directionsMatrix[6] = directionsMatrix[6] * halfSize[2];
  84063. directionsMatrix[7] = directionsMatrix[7] * halfSize[2];
  84064. directionsMatrix[8] = directionsMatrix[8] * halfSize[2];
  84065. this.center = new Vector3$1().from(center);
  84066. this.halfAxes = directionsMatrix;
  84067. return this;
  84068. }
  84069. clone() {
  84070. return new OrientedBoundingBox(this.center, this.halfAxes);
  84071. }
  84072. equals(right) {
  84073. return this === right || Boolean(right) && this.center.equals(right.center) && this.halfAxes.equals(right.halfAxes);
  84074. }
  84075. getBoundingSphere(result = new BoundingSphere()) {
  84076. const halfAxes = this.halfAxes;
  84077. const u = halfAxes.getColumn(0, scratchVectorU);
  84078. const v = halfAxes.getColumn(1, scratchVectorV);
  84079. const w = halfAxes.getColumn(2, scratchVectorW);
  84080. const cornerVector = scratchVector3.copy(u).add(v).add(w);
  84081. result.center.copy(this.center);
  84082. result.radius = cornerVector.magnitude();
  84083. return result;
  84084. }
  84085. intersectPlane(plane) {
  84086. const center = this.center;
  84087. const normal = plane.normal;
  84088. const halfAxes = this.halfAxes;
  84089. const normalX = normal.x;
  84090. const normalY = normal.y;
  84091. const normalZ = normal.z;
  84092. const radEffective = Math.abs(normalX * halfAxes[MATRIX3.COLUMN0ROW0] + normalY * halfAxes[MATRIX3.COLUMN0ROW1] + normalZ * halfAxes[MATRIX3.COLUMN0ROW2]) + Math.abs(normalX * halfAxes[MATRIX3.COLUMN1ROW0] + normalY * halfAxes[MATRIX3.COLUMN1ROW1] + normalZ * halfAxes[MATRIX3.COLUMN1ROW2]) + Math.abs(normalX * halfAxes[MATRIX3.COLUMN2ROW0] + normalY * halfAxes[MATRIX3.COLUMN2ROW1] + normalZ * halfAxes[MATRIX3.COLUMN2ROW2]);
  84093. const distanceToPlane = normal.dot(center) + plane.distance;
  84094. if (distanceToPlane <= -radEffective) {
  84095. return INTERSECTION.OUTSIDE;
  84096. } else if (distanceToPlane >= radEffective) {
  84097. return INTERSECTION.INSIDE;
  84098. }
  84099. return INTERSECTION.INTERSECTING;
  84100. }
  84101. distanceTo(point) {
  84102. return Math.sqrt(this.distanceSquaredTo(point));
  84103. }
  84104. distanceSquaredTo(point) {
  84105. const offset = scratchOffset.from(point).subtract(this.center);
  84106. const halfAxes = this.halfAxes;
  84107. const u = halfAxes.getColumn(0, scratchVectorU);
  84108. const v = halfAxes.getColumn(1, scratchVectorV);
  84109. const w = halfAxes.getColumn(2, scratchVectorW);
  84110. const uHalf = u.magnitude();
  84111. const vHalf = v.magnitude();
  84112. const wHalf = w.magnitude();
  84113. u.normalize();
  84114. v.normalize();
  84115. w.normalize();
  84116. let distanceSquared = 0.0;
  84117. let d;
  84118. d = Math.abs(offset.dot(u)) - uHalf;
  84119. if (d > 0) {
  84120. distanceSquared += d * d;
  84121. }
  84122. d = Math.abs(offset.dot(v)) - vHalf;
  84123. if (d > 0) {
  84124. distanceSquared += d * d;
  84125. }
  84126. d = Math.abs(offset.dot(w)) - wHalf;
  84127. if (d > 0) {
  84128. distanceSquared += d * d;
  84129. }
  84130. return distanceSquared;
  84131. }
  84132. computePlaneDistances(position, direction, result = [-0, -0]) {
  84133. let minDist = Number.POSITIVE_INFINITY;
  84134. let maxDist = Number.NEGATIVE_INFINITY;
  84135. const center = this.center;
  84136. const halfAxes = this.halfAxes;
  84137. const u = halfAxes.getColumn(0, scratchVectorU);
  84138. const v = halfAxes.getColumn(1, scratchVectorV);
  84139. const w = halfAxes.getColumn(2, scratchVectorW);
  84140. const corner = scratchCorner.copy(u).add(v).add(w).add(center);
  84141. const toCenter = scratchToCenter.copy(corner).subtract(position);
  84142. let mag = direction.dot(toCenter);
  84143. minDist = Math.min(mag, minDist);
  84144. maxDist = Math.max(mag, maxDist);
  84145. corner.copy(center).add(u).add(v).subtract(w);
  84146. toCenter.copy(corner).subtract(position);
  84147. mag = direction.dot(toCenter);
  84148. minDist = Math.min(mag, minDist);
  84149. maxDist = Math.max(mag, maxDist);
  84150. corner.copy(center).add(u).subtract(v).add(w);
  84151. toCenter.copy(corner).subtract(position);
  84152. mag = direction.dot(toCenter);
  84153. minDist = Math.min(mag, minDist);
  84154. maxDist = Math.max(mag, maxDist);
  84155. corner.copy(center).add(u).subtract(v).subtract(w);
  84156. toCenter.copy(corner).subtract(position);
  84157. mag = direction.dot(toCenter);
  84158. minDist = Math.min(mag, minDist);
  84159. maxDist = Math.max(mag, maxDist);
  84160. center.copy(corner).subtract(u).add(v).add(w);
  84161. toCenter.copy(corner).subtract(position);
  84162. mag = direction.dot(toCenter);
  84163. minDist = Math.min(mag, minDist);
  84164. maxDist = Math.max(mag, maxDist);
  84165. center.copy(corner).subtract(u).add(v).subtract(w);
  84166. toCenter.copy(corner).subtract(position);
  84167. mag = direction.dot(toCenter);
  84168. minDist = Math.min(mag, minDist);
  84169. maxDist = Math.max(mag, maxDist);
  84170. center.copy(corner).subtract(u).subtract(v).add(w);
  84171. toCenter.copy(corner).subtract(position);
  84172. mag = direction.dot(toCenter);
  84173. minDist = Math.min(mag, minDist);
  84174. maxDist = Math.max(mag, maxDist);
  84175. center.copy(corner).subtract(u).subtract(v).subtract(w);
  84176. toCenter.copy(corner).subtract(position);
  84177. mag = direction.dot(toCenter);
  84178. minDist = Math.min(mag, minDist);
  84179. maxDist = Math.max(mag, maxDist);
  84180. result[0] = minDist;
  84181. result[1] = maxDist;
  84182. return result;
  84183. }
  84184. transform(transformation) {
  84185. this.center.transformAsPoint(transformation);
  84186. const xAxis = this.halfAxes.getColumn(0, scratchVectorU);
  84187. xAxis.transformAsPoint(transformation);
  84188. const yAxis = this.halfAxes.getColumn(1, scratchVectorV);
  84189. yAxis.transformAsPoint(transformation);
  84190. const zAxis = this.halfAxes.getColumn(2, scratchVectorW);
  84191. zAxis.transformAsPoint(transformation);
  84192. this.halfAxes = new Matrix3$1([...xAxis, ...yAxis, ...zAxis]);
  84193. return this;
  84194. }
  84195. getTransform() {
  84196. throw new Error('not implemented');
  84197. }
  84198. }
  84199. const scratchPosition$1 = new Vector3$1();
  84200. const scratchNormal$1 = new Vector3$1();
  84201. class Plane$1 {
  84202. constructor(normal = [0, 0, 1], distance = 0) {
  84203. this.normal = new Vector3$1();
  84204. this.distance = -0;
  84205. this.fromNormalDistance(normal, distance);
  84206. }
  84207. fromNormalDistance(normal, distance) {
  84208. assert$4(Number.isFinite(distance));
  84209. this.normal.from(normal).normalize();
  84210. this.distance = distance;
  84211. return this;
  84212. }
  84213. fromPointNormal(point, normal) {
  84214. point = scratchPosition$1.from(point);
  84215. this.normal.from(normal).normalize();
  84216. const distance = -this.normal.dot(point);
  84217. this.distance = distance;
  84218. return this;
  84219. }
  84220. fromCoefficients(a, b, c, d) {
  84221. this.normal.set(a, b, c);
  84222. assert$4(equals$1(this.normal.len(), 1));
  84223. this.distance = d;
  84224. return this;
  84225. }
  84226. clone(plane) {
  84227. return new Plane$1(this.normal, this.distance);
  84228. }
  84229. equals(right) {
  84230. return equals$1(this.distance, right.distance) && equals$1(this.normal, right.normal);
  84231. }
  84232. getPointDistance(point) {
  84233. return this.normal.dot(point) + this.distance;
  84234. }
  84235. transform(matrix4) {
  84236. const normal = scratchNormal$1.copy(this.normal).transformAsVector(matrix4).normalize();
  84237. const point = this.normal.scale(-this.distance).transform(matrix4);
  84238. return this.fromPointNormal(point, normal);
  84239. }
  84240. projectPointOntoPlane(point, result = [0, 0, 0]) {
  84241. point = scratchPosition$1.from(point);
  84242. const pointDistance = this.getPointDistance(point);
  84243. const scaledNormal = scratchNormal$1.copy(this.normal).scale(pointDistance);
  84244. return point.subtract(scaledNormal).to(result);
  84245. }
  84246. }
  84247. const faces = [new Vector3$1([1, 0, 0]), new Vector3$1([0, 1, 0]), new Vector3$1([0, 0, 1])];
  84248. const scratchPlaneCenter = new Vector3$1();
  84249. const scratchPlaneNormal$1 = new Vector3$1();
  84250. new Plane$1(new Vector3$1(1.0, 0.0, 0.0), 0.0);
  84251. class CullingVolume {
  84252. static get MASK_OUTSIDE() {
  84253. return 0xffffffff;
  84254. }
  84255. static get MASK_INSIDE() {
  84256. return 0x00000000;
  84257. }
  84258. static get MASK_INDETERMINATE() {
  84259. return 0x7fffffff;
  84260. }
  84261. constructor(planes = []) {
  84262. this.planes = planes;
  84263. assert$4(this.planes.every(plane => plane instanceof Plane$1));
  84264. }
  84265. fromBoundingSphere(boundingSphere) {
  84266. this.planes.length = 2 * faces.length;
  84267. const center = boundingSphere.center;
  84268. const radius = boundingSphere.radius;
  84269. let planeIndex = 0;
  84270. for (const faceNormal of faces) {
  84271. let plane0 = this.planes[planeIndex];
  84272. let plane1 = this.planes[planeIndex + 1];
  84273. if (!plane0) {
  84274. plane0 = this.planes[planeIndex] = new Plane$1();
  84275. }
  84276. if (!plane1) {
  84277. plane1 = this.planes[planeIndex + 1] = new Plane$1();
  84278. }
  84279. const plane0Center = scratchPlaneCenter.copy(faceNormal).scale(-radius).add(center);
  84280. -faceNormal.dot(plane0Center);
  84281. plane0.fromPointNormal(plane0Center, faceNormal);
  84282. const plane1Center = scratchPlaneCenter.copy(faceNormal).scale(radius).add(center);
  84283. const negatedFaceNormal = scratchPlaneNormal$1.copy(faceNormal).negate();
  84284. -negatedFaceNormal.dot(plane1Center);
  84285. plane1.fromPointNormal(plane1Center, negatedFaceNormal);
  84286. planeIndex += 2;
  84287. }
  84288. return this;
  84289. }
  84290. computeVisibility(boundingVolume) {
  84291. assert$4(boundingVolume);
  84292. let intersect = INTERSECTION.INSIDE;
  84293. for (const plane of this.planes) {
  84294. const result = boundingVolume.intersectPlane(plane);
  84295. switch (result) {
  84296. case INTERSECTION.OUTSIDE:
  84297. return INTERSECTION.OUTSIDE;
  84298. case INTERSECTION.INTERSECTING:
  84299. intersect = INTERSECTION.INTERSECTING;
  84300. break;
  84301. }
  84302. }
  84303. return intersect;
  84304. }
  84305. computeVisibilityWithPlaneMask(boundingVolume, parentPlaneMask) {
  84306. assert$4(boundingVolume, 'boundingVolume is required.');
  84307. assert$4(Number.isFinite(parentPlaneMask), 'parentPlaneMask is required.');
  84308. if (parentPlaneMask === CullingVolume.MASK_OUTSIDE || parentPlaneMask === CullingVolume.MASK_INSIDE) {
  84309. return parentPlaneMask;
  84310. }
  84311. let mask = CullingVolume.MASK_INSIDE;
  84312. const planes = this.planes;
  84313. for (let k = 0; k < this.planes.length; ++k) {
  84314. const flag = k < 31 ? 1 << k : 0;
  84315. if (k < 31 && (parentPlaneMask & flag) === 0) {
  84316. continue;
  84317. }
  84318. const plane = planes[k];
  84319. const result = boundingVolume.intersectPlane(plane);
  84320. if (result === INTERSECTION.OUTSIDE) {
  84321. return CullingVolume.MASK_OUTSIDE;
  84322. } else if (result === INTERSECTION.INTERSECTING) {
  84323. mask |= flag;
  84324. }
  84325. }
  84326. return mask;
  84327. }
  84328. }
  84329. const scratchPlaneUpVector = new Vector3$1();
  84330. const scratchPlaneRightVector = new Vector3$1();
  84331. const scratchPlaneNearCenter = new Vector3$1();
  84332. const scratchPlaneFarCenter = new Vector3$1();
  84333. const scratchPlaneNormal = new Vector3$1();
  84334. class PerspectiveOffCenterFrustum {
  84335. constructor(options = {}) {
  84336. options = {
  84337. near: 1.0,
  84338. far: 500000000.0,
  84339. ...options
  84340. };
  84341. this.left = options.left;
  84342. this._left = undefined;
  84343. this.right = options.right;
  84344. this._right = undefined;
  84345. this.top = options.top;
  84346. this._top = undefined;
  84347. this.bottom = options.bottom;
  84348. this._bottom = undefined;
  84349. this.near = options.near;
  84350. this._near = this.near;
  84351. this.far = options.far;
  84352. this._far = this.far;
  84353. this._cullingVolume = new CullingVolume([new Plane$1(), new Plane$1(), new Plane$1(), new Plane$1(), new Plane$1(), new Plane$1()]);
  84354. this._perspectiveMatrix = new Matrix4$1();
  84355. this._infinitePerspective = new Matrix4$1();
  84356. }
  84357. clone() {
  84358. return new PerspectiveOffCenterFrustum({
  84359. right: this.right,
  84360. left: this.left,
  84361. top: this.top,
  84362. bottom: this.bottom,
  84363. near: this.near,
  84364. far: this.far
  84365. });
  84366. }
  84367. equals(other) {
  84368. return other && other instanceof PerspectiveOffCenterFrustum && this.right === other.right && this.left === other.left && this.top === other.top && this.bottom === other.bottom && this.near === other.near && this.far === other.far;
  84369. }
  84370. get projectionMatrix() {
  84371. update$1(this);
  84372. return this._perspectiveMatrix;
  84373. }
  84374. get infiniteProjectionMatrix() {
  84375. update$1(this);
  84376. return this._infinitePerspective;
  84377. }
  84378. computeCullingVolume(position, direction, up) {
  84379. assert$4(position, 'position is required.');
  84380. assert$4(direction, 'direction is required.');
  84381. assert$4(up, 'up is required.');
  84382. const planes = this._cullingVolume.planes;
  84383. up = scratchPlaneUpVector.copy(up).normalize();
  84384. const right = scratchPlaneRightVector.copy(direction).cross(up).normalize();
  84385. const nearCenter = scratchPlaneNearCenter.copy(direction).multiplyByScalar(this.near).add(position);
  84386. const farCenter = scratchPlaneFarCenter.copy(direction).multiplyByScalar(this.far).add(position);
  84387. let normal = scratchPlaneNormal;
  84388. normal.copy(right).multiplyByScalar(this.left).add(nearCenter).subtract(position).cross(up);
  84389. planes[0].fromPointNormal(position, normal);
  84390. normal.copy(right).multiplyByScalar(this.right).add(nearCenter).subtract(position).cross(up).negate();
  84391. planes[1].fromPointNormal(position, normal);
  84392. normal.copy(up).multiplyByScalar(this.bottom).add(nearCenter).subtract(position).cross(right).negate();
  84393. planes[2].fromPointNormal(position, normal);
  84394. normal.copy(up).multiplyByScalar(this.top).add(nearCenter).subtract(position).cross(right);
  84395. planes[3].fromPointNormal(position, normal);
  84396. normal = new Vector3$1().copy(direction);
  84397. planes[4].fromPointNormal(nearCenter, normal);
  84398. normal.negate();
  84399. planes[5].fromPointNormal(farCenter, normal);
  84400. return this._cullingVolume;
  84401. }
  84402. getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result) {
  84403. update$1(this);
  84404. assert$4(Number.isFinite(drawingBufferWidth) && Number.isFinite(drawingBufferHeight));
  84405. assert$4(drawingBufferWidth > 0);
  84406. assert$4(drawingBufferHeight > 0);
  84407. assert$4(distance > 0);
  84408. assert$4(result);
  84409. const inverseNear = 1.0 / this.near;
  84410. let tanTheta = this.top * inverseNear;
  84411. const pixelHeight = 2.0 * distance * tanTheta / drawingBufferHeight;
  84412. tanTheta = this.right * inverseNear;
  84413. const pixelWidth = 2.0 * distance * tanTheta / drawingBufferWidth;
  84414. result.x = pixelWidth;
  84415. result.y = pixelHeight;
  84416. return result;
  84417. }
  84418. }
  84419. function update$1(frustum) {
  84420. assert$4(Number.isFinite(frustum.right) && Number.isFinite(frustum.left) && Number.isFinite(frustum.top) && Number.isFinite(frustum.bottom) && Number.isFinite(frustum.near) && Number.isFinite(frustum.far));
  84421. const {
  84422. top,
  84423. bottom,
  84424. right,
  84425. left,
  84426. near,
  84427. far
  84428. } = frustum;
  84429. if (top !== frustum._top || bottom !== frustum._bottom || left !== frustum._left || right !== frustum._right || near !== frustum._near || far !== frustum._far) {
  84430. assert$4(frustum.near > 0 && frustum.near < frustum.far, 'near must be greater than zero and less than far.');
  84431. frustum._left = left;
  84432. frustum._right = right;
  84433. frustum._top = top;
  84434. frustum._bottom = bottom;
  84435. frustum._near = near;
  84436. frustum._far = far;
  84437. frustum._perspectiveMatrix = new Matrix4$1().frustum({
  84438. left,
  84439. right,
  84440. bottom,
  84441. top,
  84442. near,
  84443. far
  84444. });
  84445. frustum._infinitePerspective = new Matrix4$1().frustum({
  84446. left,
  84447. right,
  84448. bottom,
  84449. top,
  84450. near,
  84451. far: Infinity
  84452. });
  84453. }
  84454. }
  84455. const defined$4 = val => val !== null && typeof val !== 'undefined';
  84456. class PerspectiveFrustum {
  84457. constructor(options = {}) {
  84458. options = {
  84459. near: 1.0,
  84460. far: 500000000.0,
  84461. xOffset: 0.0,
  84462. yOffset: 0.0,
  84463. ...options
  84464. };
  84465. this._offCenterFrustum = new PerspectiveOffCenterFrustum();
  84466. this.fov = options.fov;
  84467. this._fov = undefined;
  84468. this._fovy = undefined;
  84469. this._sseDenominator = undefined;
  84470. this.aspectRatio = options.aspectRatio;
  84471. this._aspectRatio = undefined;
  84472. this.near = options.near;
  84473. this._near = this.near;
  84474. this.far = options.far;
  84475. this._far = this.far;
  84476. this.xOffset = options.xOffset;
  84477. this._xOffset = this.xOffset;
  84478. this.yOffset = options.yOffset;
  84479. this._yOffset = this.yOffset;
  84480. }
  84481. clone() {
  84482. return new PerspectiveFrustum({
  84483. aspectRatio: this.aspectRatio,
  84484. fov: this.fov,
  84485. near: this.near,
  84486. far: this.far
  84487. });
  84488. }
  84489. equals(other) {
  84490. if (!defined$4(other) || !(other instanceof PerspectiveFrustum)) {
  84491. return false;
  84492. }
  84493. update(this);
  84494. update(other);
  84495. return this.fov === other.fov && this.aspectRatio === other.aspectRatio && this.near === other.near && this.far === other.far && this._offCenterFrustum.equals(other._offCenterFrustum);
  84496. }
  84497. get projectionMatrix() {
  84498. update(this);
  84499. return this._offCenterFrustum.projectionMatrix;
  84500. }
  84501. get infiniteProjectionMatrix() {
  84502. update(this);
  84503. return this._offCenterFrustum.infiniteProjectionMatrix;
  84504. }
  84505. get fovy() {
  84506. update(this);
  84507. return this._fovy;
  84508. }
  84509. get sseDenominator() {
  84510. update(this);
  84511. return this._sseDenominator;
  84512. }
  84513. computeCullingVolume(position, direction, up) {
  84514. update(this);
  84515. return this._offCenterFrustum.computeCullingVolume(position, direction, up);
  84516. }
  84517. getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result) {
  84518. update(this);
  84519. return this._offCenterFrustum.getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result);
  84520. }
  84521. }
  84522. function update(frustum) {
  84523. assert$4(Number.isFinite(frustum.fov) && Number.isFinite(frustum.aspectRatio) && Number.isFinite(frustum.near) && Number.isFinite(frustum.far));
  84524. const f = frustum._offCenterFrustum;
  84525. if (frustum.fov !== frustum._fov || frustum.aspectRatio !== frustum._aspectRatio || frustum.near !== frustum._near || frustum.far !== frustum._far || frustum.xOffset !== frustum._xOffset || frustum.yOffset !== frustum._yOffset) {
  84526. assert$4(frustum.fov >= 0 && frustum.fov < Math.PI);
  84527. assert$4(frustum.aspectRatio > 0);
  84528. assert$4(frustum.near >= 0 && frustum.near < frustum.far);
  84529. frustum._aspectRatio = frustum.aspectRatio;
  84530. frustum._fov = frustum.fov;
  84531. frustum._fovy = frustum.aspectRatio <= 1 ? frustum.fov : Math.atan(Math.tan(frustum.fov * 0.5) / frustum.aspectRatio) * 2.0;
  84532. frustum._near = frustum.near;
  84533. frustum._far = frustum.far;
  84534. frustum._sseDenominator = 2.0 * Math.tan(0.5 * frustum._fovy);
  84535. frustum._xOffset = frustum.xOffset;
  84536. frustum._yOffset = frustum.yOffset;
  84537. f.top = frustum.near * Math.tan(0.5 * frustum._fovy);
  84538. f.bottom = -f.top;
  84539. f.right = frustum.aspectRatio * f.top;
  84540. f.left = -f.right;
  84541. f.near = frustum.near;
  84542. f.far = frustum.far;
  84543. f.right += frustum.xOffset;
  84544. f.left += frustum.xOffset;
  84545. f.top += frustum.yOffset;
  84546. f.bottom += frustum.yOffset;
  84547. }
  84548. }
  84549. new Vector3$1();
  84550. new Vector3$1();
  84551. new Vector3$1();
  84552. new Vector3$1();
  84553. new Vector3$1();
  84554. new Vector3$1();
  84555. new Vector3$1();
  84556. new Vector3$1();
  84557. new Vector3$1();
  84558. new Vector3$1();
  84559. new Vector3$1();
  84560. new Vector3$1();
  84561. new Matrix3$1();
  84562. new Matrix3$1();
  84563. new Matrix3$1();
  84564. new Matrix3$1();
  84565. new Matrix3$1();
  84566. new Vector3$1();
  84567. new Vector3$1();
  84568. new Vector3$1();
  84569. new Vector3$1();
  84570. new Vector3$1();
  84571. new Matrix3$1();
  84572. ({
  84573. diagonal: new Matrix3$1(),
  84574. unitary: new Matrix3$1()
  84575. });
  84576. const scratchVector$2 = new Vector3$1();
  84577. const scratchPosition = new Vector3$1();
  84578. const cullingVolume = new CullingVolume([new Plane$1(), new Plane$1(), new Plane$1(), new Plane$1(), new Plane$1(), new Plane$1()]);
  84579. function getFrameState(viewport, frameNumber) {
  84580. const {
  84581. cameraDirection,
  84582. cameraUp,
  84583. height
  84584. } = viewport;
  84585. const {
  84586. metersPerUnit
  84587. } = viewport.distanceScales;
  84588. const viewportCenterCartographic = viewport.unprojectPosition(viewport.center);
  84589. const viewportCenterCartesian = Ellipsoid.WGS84.cartographicToCartesian(viewportCenterCartographic, new Vector3$1());
  84590. const enuToFixedTransform = Ellipsoid.WGS84.eastNorthUpToFixedFrame(viewportCenterCartesian);
  84591. const cameraPositionCartographic = viewport.unprojectPosition(viewport.cameraPosition);
  84592. const cameraPositionCartesian = Ellipsoid.WGS84.cartographicToCartesian(cameraPositionCartographic, new Vector3$1());
  84593. const cameraDirectionCartesian = new Vector3$1(enuToFixedTransform.transformAsVector(new Vector3$1(cameraDirection).scale(metersPerUnit))).normalize();
  84594. const cameraUpCartesian = new Vector3$1(enuToFixedTransform.transformAsVector(new Vector3$1(cameraUp).scale(metersPerUnit))).normalize();
  84595. commonSpacePlanesToWGS84(viewport, viewportCenterCartesian);
  84596. return {
  84597. camera: {
  84598. position: cameraPositionCartesian,
  84599. direction: cameraDirectionCartesian,
  84600. up: cameraUpCartesian
  84601. },
  84602. viewport,
  84603. height,
  84604. cullingVolume,
  84605. frameNumber,
  84606. sseDenominator: 1.15
  84607. };
  84608. }
  84609. function commonSpacePlanesToWGS84(viewport, viewportCenterCartesian) {
  84610. const frustumPlanes = viewport.getFrustumPlanes();
  84611. let i = 0;
  84612. for (const dir in frustumPlanes) {
  84613. const plane = frustumPlanes[dir];
  84614. const distanceToCenter = plane.normal.dot(viewport.center);
  84615. scratchPosition.copy(plane.normal).scale(plane.distance - distanceToCenter).add(viewport.center);
  84616. const cartographicPos = viewport.unprojectPosition(scratchPosition);
  84617. const cartesianPos = Ellipsoid.WGS84.cartographicToCartesian(cartographicPos, new Vector3$1());
  84618. cullingVolume.planes[i++].fromPointNormal(cartesianPos, scratchVector$2.copy(viewportCenterCartesian).subtract(cartesianPos));
  84619. }
  84620. }
  84621. const WGS84_RADIUS_X = 6378137.0;
  84622. const WGS84_RADIUS_Y = 6378137.0;
  84623. const WGS84_RADIUS_Z = 6356752.3142451793;
  84624. const scratchVector$1 = new Vector3$1();
  84625. function getZoomFromBoundingVolume(boundingVolume) {
  84626. const {
  84627. halfAxes,
  84628. radius,
  84629. width,
  84630. height
  84631. } = boundingVolume;
  84632. if (halfAxes) {
  84633. const obbSize = getObbSize(halfAxes);
  84634. return Math.log2(WGS84_RADIUS_Z / obbSize);
  84635. } else if (radius) {
  84636. return Math.log2(WGS84_RADIUS_Z / radius);
  84637. } else if (height && width) {
  84638. const zoomX = Math.log2(WGS84_RADIUS_X / width);
  84639. const zoomY = Math.log2(WGS84_RADIUS_Y / height);
  84640. return (zoomX + zoomY) / 2;
  84641. }
  84642. return 1;
  84643. }
  84644. function getObbSize(halfAxes) {
  84645. halfAxes.getColumn(0, scratchVector$1);
  84646. const axeY = halfAxes.getColumn(1);
  84647. const axeZ = halfAxes.getColumn(2);
  84648. const farthestVertex = scratchVector$1.add(axeY).add(axeZ);
  84649. const size = farthestVertex.len();
  84650. return size;
  84651. }
  84652. const TILE_CONTENT_STATE = {
  84653. UNLOADED: 0,
  84654. LOADING: 1,
  84655. PROCESSING: 2,
  84656. READY: 3,
  84657. EXPIRED: 4,
  84658. FAILED: 5
  84659. };
  84660. const TILE_REFINEMENT = {
  84661. ADD: 1,
  84662. REPLACE: 2
  84663. };
  84664. const TILE_TYPE = {
  84665. EMPTY: 'empty',
  84666. SCENEGRAPH: 'scenegraph',
  84667. POINTCLOUD: 'pointcloud',
  84668. MESH: 'mesh'
  84669. };
  84670. const TILESET_TYPE = {
  84671. I3S: 'I3S',
  84672. TILES3D: 'TILES3D'
  84673. };
  84674. const LOD_METRIC_TYPE = {
  84675. GEOMETRIC_ERROR: 'geometricError',
  84676. MAX_SCREEN_THRESHOLD: 'maxScreenThreshold'
  84677. };
  84678. const TILE3D_OPTIMIZATION_HINT = {
  84679. NOT_COMPUTED: -1,
  84680. USE_OPTIMIZATION: 1,
  84681. SKIP_OPTIMIZATION: 0
  84682. };
  84683. function defined$3(x) {
  84684. return x !== undefined && x !== null;
  84685. }
  84686. const scratchScale = new Vector3$1();
  84687. const scratchNorthWest = new Vector3$1();
  84688. const scratchSouthEast = new Vector3$1();
  84689. function createBoundingVolume(boundingVolumeHeader, transform, result) {
  84690. assert$7(boundingVolumeHeader, '3D Tile: boundingVolume must be defined');
  84691. if (boundingVolumeHeader.box) {
  84692. return createBox(boundingVolumeHeader.box, transform, result);
  84693. }
  84694. if (boundingVolumeHeader.region) {
  84695. const [west, south, east, north, minHeight, maxHeight] = boundingVolumeHeader.region;
  84696. const northWest = Ellipsoid.WGS84.cartographicToCartesian([degrees(west), degrees(north), minHeight], scratchNorthWest);
  84697. const southEast = Ellipsoid.WGS84.cartographicToCartesian([degrees(east), degrees(south), maxHeight], scratchSouthEast);
  84698. const centerInCartesian = new Vector3$1().addVectors(northWest, southEast).multiplyScalar(0.5);
  84699. const radius = new Vector3$1().subVectors(northWest, southEast).len() / 2.0;
  84700. return createSphere([centerInCartesian[0], centerInCartesian[1], centerInCartesian[2], radius], new Matrix4$1());
  84701. }
  84702. if (boundingVolumeHeader.sphere) {
  84703. return createSphere(boundingVolumeHeader.sphere, transform, result);
  84704. }
  84705. throw new Error('3D Tile: boundingVolume must contain a sphere, region, or box');
  84706. }
  84707. function createBox(box, transform, result) {
  84708. const center = new Vector3$1(box[0], box[1], box[2]);
  84709. result && (result.oriCenter = center);//add
  84710. transform.transform(center, center);
  84711. let origin = [];
  84712. if (box.length === 10) {
  84713. const halfSize = box.slice(3, 6);
  84714. const quaternion = new Quaternion$1();
  84715. quaternion.fromArray(box, 6);
  84716. const x = new Vector3$1([1, 0, 0]);
  84717. const y = new Vector3$1([0, 1, 0]);
  84718. const z = new Vector3$1([0, 0, 1]);
  84719. x.transformByQuaternion(quaternion);
  84720. x.scale(halfSize[0]);
  84721. y.transformByQuaternion(quaternion);
  84722. y.scale(halfSize[1]);
  84723. z.transformByQuaternion(quaternion);
  84724. z.scale(halfSize[2]);
  84725. origin = [...x.toArray(), ...y.toArray(), ...z.toArray()];
  84726. } else {
  84727. origin = [...box.slice(3, 6), ...box.slice(6, 9), ...box.slice(9, 12)];
  84728. }
  84729. const xAxis = transform.transformAsVector(origin.slice(0, 3));
  84730. const yAxis = transform.transformAsVector(origin.slice(3, 6));
  84731. const zAxis = transform.transformAsVector(origin.slice(6, 9));
  84732. const halfAxes = new Matrix3$1([xAxis[0], xAxis[1], xAxis[2], yAxis[0], yAxis[1], yAxis[2], zAxis[0], zAxis[1], zAxis[2]]);
  84733. if (defined$3(result)) {
  84734. result.center = center;
  84735. result.halfAxes = halfAxes;
  84736. return result;
  84737. }
  84738. return new OrientedBoundingBox(center, halfAxes);
  84739. }
  84740. function createSphere(sphere, transform, result) {
  84741. const center = new Vector3$1(sphere[0], sphere[1], sphere[2]);
  84742. transform.transform(center, center);
  84743. const scale = transform.getScale(scratchScale);
  84744. const uniformScale = Math.max(Math.max(scale[0], scale[1]), scale[2]);
  84745. const radius = sphere[3] * uniformScale;
  84746. if (defined$3(result)) {
  84747. result.center = center;
  84748. result.radius = radius;
  84749. return result;
  84750. }
  84751. return new BoundingSphere(center, radius);
  84752. }
  84753. new Vector3$1();
  84754. new Vector3$1();
  84755. new Matrix4$1();
  84756. new Vector3$1();
  84757. new Vector3$1();
  84758. new Vector3$1();
  84759. function fog(distanceToCamera, density) {
  84760. const scalar = distanceToCamera * density;
  84761. return 1.0 - Math.exp(-(scalar * scalar));
  84762. }
  84763. function getDynamicScreenSpaceError(tileset, distanceToCamera) {
  84764. if (tileset.dynamicScreenSpaceError && tileset.dynamicScreenSpaceErrorComputedDensity) {
  84765. const density = tileset.dynamicScreenSpaceErrorComputedDensity;
  84766. const factor = tileset.dynamicScreenSpaceErrorFactor;
  84767. const dynamicError = fog(distanceToCamera, density) * factor;
  84768. return dynamicError;
  84769. }
  84770. return 0;
  84771. }
  84772. function getTiles3DScreenSpaceError(tile, frameState, useParentLodMetric) {
  84773. const tileset = tile.tileset;
  84774. const parentLodMetricValue = tile.parent && tile.parent.lodMetricValue || tile.lodMetricValue;
  84775. const lodMetricValue = useParentLodMetric ? parentLodMetricValue : tile.lodMetricValue;
  84776. if (lodMetricValue === 0.0) {
  84777. return 0.0;
  84778. }
  84779. const distance = Math.max(tile._distanceToCamera, 1e-7);
  84780. const {
  84781. height,
  84782. sseDenominator
  84783. } = frameState;
  84784. const {
  84785. viewDistanceScale
  84786. } = tileset.options;
  84787. let error = lodMetricValue * height * (viewDistanceScale || 1.0) / (distance * sseDenominator);
  84788. error -= getDynamicScreenSpaceError(tileset, distance);
  84789. return error;
  84790. }
  84791. function getLodStatus(tile, frameState) {
  84792. if (tile.lodMetricValue === 0 || isNaN(tile.lodMetricValue)) {
  84793. return 'DIG';
  84794. }
  84795. const screenSize = 2 * getProjectedRadius(tile, frameState);
  84796. if (screenSize < 2) {
  84797. return 'OUT';
  84798. }
  84799. if (!tile.header.children || screenSize <= tile.lodMetricValue) {
  84800. return 'DRAW';
  84801. } else if (tile.header.children) {
  84802. return 'DIG';
  84803. }
  84804. return 'OUT';
  84805. }
  84806. function getProjectedRadius(tile, frameState) {
  84807. const originalViewport = frameState.viewport;
  84808. const ViewportClass = originalViewport.constructor;
  84809. const {
  84810. longitude,
  84811. latitude,
  84812. height,
  84813. width,
  84814. bearing,
  84815. zoom
  84816. } = originalViewport;
  84817. const viewport = new ViewportClass({
  84818. longitude,
  84819. latitude,
  84820. height,
  84821. width,
  84822. bearing,
  84823. zoom,
  84824. pitch: 0
  84825. });
  84826. const mbsLat = tile.header.mbs[1];
  84827. const mbsLon = tile.header.mbs[0];
  84828. const mbsZ = tile.header.mbs[2];
  84829. const mbsR = tile.header.mbs[3];
  84830. const mbsCenterCartesian = [...tile.boundingVolume.center];
  84831. const cameraPositionCartographic = viewport.unprojectPosition(viewport.cameraPosition);
  84832. const cameraPositionCartesian = Ellipsoid.WGS84.cartographicToCartesian(cameraPositionCartographic, new Vector3$1());
  84833. const toEye = new Vector3$1(cameraPositionCartesian).subtract(mbsCenterCartesian).normalize();
  84834. const enuToCartesianMatrix = new Matrix4$1();
  84835. Ellipsoid.WGS84.eastNorthUpToFixedFrame(mbsCenterCartesian, enuToCartesianMatrix);
  84836. const cartesianToEnuMatrix = new Matrix4$1(enuToCartesianMatrix).invert();
  84837. const cameraPositionEnu = new Vector3$1(cameraPositionCartesian).transform(cartesianToEnuMatrix);
  84838. const projection = Math.sqrt(cameraPositionEnu[0] * cameraPositionEnu[0] + cameraPositionEnu[1] * cameraPositionEnu[1]);
  84839. const extraZ = projection * projection / cameraPositionEnu[2];
  84840. const extraVertexEnu = new Vector3$1([cameraPositionEnu[0], cameraPositionEnu[1], extraZ]);
  84841. const extraVertexCartesian = extraVertexEnu.transform(enuToCartesianMatrix);
  84842. const extraVectorCartesian = new Vector3$1(extraVertexCartesian).subtract(mbsCenterCartesian).normalize();
  84843. const radiusVector = toEye.cross(extraVectorCartesian).normalize().scale(mbsR);
  84844. const sphereMbsBorderVertexCartesian = new Vector3$1(mbsCenterCartesian).add(radiusVector);
  84845. const sphereMbsBorderVertexCartographic = Ellipsoid.WGS84.cartesianToCartographic(sphereMbsBorderVertexCartesian);
  84846. const projectedOrigin = viewport.project([mbsLon, mbsLat, mbsZ]);
  84847. const projectedMbsBorderVertex = viewport.project(sphereMbsBorderVertexCartographic);
  84848. const projectedRadius = new Vector3$1(projectedOrigin).subtract(projectedMbsBorderVertex).magnitude();
  84849. return projectedRadius;
  84850. }
  84851. function get3dTilesOptions(tileset) {
  84852. return {
  84853. assetGltfUpAxis: tileset.asset && tileset.asset.gltfUpAxis || 'Y'
  84854. };
  84855. }
  84856. class ManagedArray {
  84857. constructor(length = 0) {
  84858. _defineProperty(this, "_map", new Map());
  84859. _defineProperty(this, "_array", void 0);
  84860. _defineProperty(this, "_length", void 0);
  84861. this._array = new Array(length);
  84862. this._length = length;
  84863. }
  84864. get length() {
  84865. return this._length;
  84866. }
  84867. set length(length) {
  84868. this._length = length;
  84869. if (length > this._array.length) {
  84870. this._array.length = length;
  84871. }
  84872. }
  84873. get values() {
  84874. return this._array;
  84875. }
  84876. get(index) {
  84877. assert$7(index < this._array.length);
  84878. return this._array[index];
  84879. }
  84880. set(index, element) {
  84881. assert$7(index >= 0);
  84882. if (index >= this.length) {
  84883. this.length = index + 1;
  84884. }
  84885. if (this._map.has(this._array[index])) {
  84886. this._map.delete(this._array[index]);
  84887. }
  84888. this._array[index] = element;
  84889. this._map.set(element, index);
  84890. }
  84891. delete(element) {
  84892. const index = this._map.get(element);
  84893. if (index >= 0) {
  84894. this._array.splice(index, 1);
  84895. this._map.delete(element);
  84896. this.length--;
  84897. }
  84898. }
  84899. peek() {
  84900. return this._array[this._length - 1];
  84901. }
  84902. push(element) {
  84903. if (!this._map.has(element)) {
  84904. const index = this.length++;
  84905. this._array[index] = element;
  84906. this._map.set(element, index);
  84907. }
  84908. }
  84909. pop() {
  84910. const element = this._array[--this.length];
  84911. this._map.delete(element);
  84912. return element;
  84913. }
  84914. reserve(length) {
  84915. assert$7(length >= 0);
  84916. if (length > this._array.length) {
  84917. this._array.length = length;
  84918. }
  84919. }
  84920. resize(length) {
  84921. assert$7(length >= 0);
  84922. this.length = length;
  84923. }
  84924. trim(length) {
  84925. if (length === null || length === undefined) {
  84926. length = this.length;
  84927. }
  84928. this._array.length = length;
  84929. }
  84930. reset() {
  84931. this._array = [];
  84932. this._map = new Map();
  84933. this._length = 0;
  84934. }
  84935. find(target) {
  84936. return this._map.has(target);
  84937. }
  84938. }
  84939. const DEFAULT_PROPS$1 = {
  84940. loadSiblings: false,
  84941. skipLevelOfDetail: false,
  84942. maximumScreenSpaceError: 2,
  84943. updateTransforms: true,
  84944. onTraversalEnd: () => {},
  84945. viewportTraversersMap: {},
  84946. basePath: ''
  84947. };
  84948. class TilesetTraverser {
  84949. constructor(options) {
  84950. _defineProperty(this, "options", void 0);
  84951. _defineProperty(this, "root", void 0);
  84952. _defineProperty(this, "requestedTiles", void 0);
  84953. _defineProperty(this, "selectedTiles", void 0);
  84954. _defineProperty(this, "emptyTiles", void 0);
  84955. _defineProperty(this, "_traversalStack", void 0);
  84956. _defineProperty(this, "_emptyTraversalStack", void 0);
  84957. _defineProperty(this, "_frameNumber", void 0);
  84958. this.options = { ...DEFAULT_PROPS$1,
  84959. ...options
  84960. };
  84961. this._traversalStack = new ManagedArray();
  84962. this._emptyTraversalStack = new ManagedArray();
  84963. this._frameNumber = null;
  84964. this.root = null;
  84965. this.selectedTiles = {};
  84966. this.requestedTiles = {};
  84967. this.emptyTiles = {};
  84968. }
  84969. traverse(root, frameState, options) {
  84970. this.root = root;
  84971. this.options = { ...this.options,
  84972. ...options
  84973. };
  84974. this.reset();
  84975. this.updateTile(root, frameState);
  84976. this._frameNumber = frameState.frameNumber;
  84977. this.executeTraversal(root, frameState);
  84978. }
  84979. reset() {
  84980. this.requestedTiles = {};
  84981. this.selectedTiles = {};
  84982. this.emptyTiles = {};
  84983. this._traversalStack.reset();
  84984. this._emptyTraversalStack.reset();
  84985. }
  84986. executeTraversal(root, frameState) {// 遍历root
  84987. const stack = this._traversalStack;
  84988. root._selectionDepth = 1;
  84989. stack.push(root);
  84990. while (stack.length > 0) {
  84991. const tile = stack.pop();
  84992. let shouldRefine = false;
  84993. // !zeg改 循环遍历子tile, maxDepth用来限制可加载的最大深度
  84994. if (this.canTraverse(tile, frameState) && tile.depth < this.options.maxDepth) {//add maxDepth
  84995. this.updateChildTiles(tile, frameState);
  84996. shouldRefine = this.updateAndPushChildren(tile, frameState, stack, tile.hasRenderContent ? tile._selectionDepth + 1 : tile._selectionDepth);
  84997. }
  84998. const parent = tile.parent;
  84999. const parentRefines = Boolean(!parent || parent._shouldRefine);
  85000. const stoppedRefining = !shouldRefine;
  85001. if (!tile.hasRenderContent) {
  85002. this.emptyTiles[tile.id] = tile;
  85003. this.loadTile(tile, frameState);
  85004. if (stoppedRefining) {
  85005. this.selectTile(tile, frameState);
  85006. }
  85007. } else if (tile.refine === TILE_REFINEMENT.ADD) {
  85008. this.loadTile(tile, frameState);
  85009. this.selectTile(tile, frameState);
  85010. } else if (tile.refine === TILE_REFINEMENT.REPLACE) {
  85011. this.loadTile(tile, frameState);
  85012. if (stoppedRefining) {
  85013. this.selectTile(tile, frameState);
  85014. }
  85015. }
  85016. this.touchTile(tile, frameState);
  85017. tile._shouldRefine = shouldRefine && parentRefines;
  85018. }
  85019. this.options.onTraversalEnd(frameState);
  85020. }
  85021. updateChildTiles(tile, frameState) {
  85022. const children = tile.children;
  85023. for (const child of children) {
  85024. this.updateTile(child, frameState);
  85025. }
  85026. return true;
  85027. }
  85028. updateAndPushChildren(tile, frameState, stack, depth) {
  85029. const {
  85030. loadSiblings,
  85031. skipLevelOfDetail
  85032. } = this.options;
  85033. const children = tile.children;
  85034. children.sort(this.compareDistanceToCamera.bind(this));
  85035. const checkRefines = tile.refine === TILE_REFINEMENT.REPLACE && tile.hasRenderContent && !skipLevelOfDetail;
  85036. let hasVisibleChild = false;
  85037. let refines = true;
  85038. for (const child of children) {
  85039. child._selectionDepth = depth;
  85040. if (child.isVisibleAndInRequestVolume) {
  85041. if (stack.find(child)) {
  85042. stack.delete(child);
  85043. }
  85044. stack.push(child);
  85045. hasVisibleChild = true;
  85046. } else if (checkRefines || loadSiblings) {
  85047. this.loadTile(child, frameState);
  85048. this.touchTile(child, frameState);
  85049. }
  85050. if (checkRefines) {
  85051. let childRefines;
  85052. if (!child._inRequestVolume) {
  85053. childRefines = false;
  85054. } else if (!child.hasRenderContent) {
  85055. childRefines = this.executeEmptyTraversal(child, frameState);
  85056. } else {
  85057. childRefines = child.contentAvailable;
  85058. }
  85059. refines = refines && childRefines;
  85060. if (!refines) {
  85061. return false;
  85062. }
  85063. }
  85064. }
  85065. if (!hasVisibleChild) {
  85066. refines = false;
  85067. }
  85068. return refines;
  85069. }
  85070. updateTile(tile, frameState) {
  85071. this.updateTileVisibility(tile, frameState);
  85072. }
  85073. selectTile(tile, frameState) {
  85074. if (this.shouldSelectTile(tile)) {
  85075. tile._selectedFrame = frameState.frameNumber;
  85076. this.selectedTiles[tile.id] = tile;
  85077. }
  85078. }
  85079. loadTile(tile, frameState) {
  85080. if (this.shouldLoadTile(tile)) {
  85081. tile._requestedFrame = frameState.frameNumber;
  85082. tile._priority = tile._getPriority();
  85083. this.requestedTiles[tile.id] = tile;
  85084. }
  85085. }
  85086. touchTile(tile, frameState) {
  85087. tile.tileset._cache.touch(tile);
  85088. tile._touchedFrame = frameState.frameNumber;
  85089. }
  85090. canTraverse(tile, frameState, useParentMetric = false, ignoreVisibility = false) {
  85091. if (!tile.hasChildren) {
  85092. return false;
  85093. }
  85094. if (tile.hasTilesetContent) {
  85095. return !tile.contentExpired;
  85096. }
  85097. if (!ignoreVisibility && !tile.isVisibleAndInRequestVolume) {
  85098. return false;
  85099. }
  85100. return this.shouldRefine(tile, frameState, useParentMetric);
  85101. }
  85102. shouldLoadTile(tile) {
  85103. return tile.hasUnloadedContent || tile.contentExpired;
  85104. }
  85105. shouldSelectTile(tile) {
  85106. return tile.contentAvailable && !this.options.skipLevelOfDetail;
  85107. }
  85108. shouldRefine(tile, frameState, useParentMetric) {
  85109. let screenSpaceError = tile._screenSpaceError;
  85110. if (useParentMetric) {
  85111. screenSpaceError = tile.getScreenSpaceError(frameState, true);
  85112. }
  85113. return screenSpaceError > this.options.maximumScreenSpaceError;
  85114. }
  85115. updateTileVisibility(tile, frameState) {
  85116. const viewportIds = [];
  85117. if (this.options.viewportTraversersMap) {
  85118. for (const key in this.options.viewportTraversersMap) {
  85119. const value = this.options.viewportTraversersMap[key];
  85120. if (value === frameState.viewport.id) {
  85121. viewportIds.push(key);
  85122. }
  85123. }
  85124. } else {
  85125. viewportIds.push(frameState.viewport.id);
  85126. }
  85127. tile.updateVisibility(frameState, viewportIds);
  85128. }
  85129. compareDistanceToCamera(b, a) {
  85130. return b._distanceToCamera - a._distanceToCamera;
  85131. }
  85132. anyChildrenVisible(tile, frameState) {
  85133. let anyVisible = false;
  85134. for (const child of tile.children) {
  85135. child.updateVisibility(frameState);
  85136. anyVisible = anyVisible || child.isVisibleAndInRequestVolume;
  85137. }
  85138. return anyVisible;
  85139. }
  85140. executeEmptyTraversal(root, frameState) {
  85141. let allDescendantsLoaded = true;
  85142. const stack = this._emptyTraversalStack;
  85143. stack.push(root);
  85144. while (stack.length > 0 && allDescendantsLoaded) {
  85145. const tile = stack.pop();
  85146. this.updateTile(tile, frameState);
  85147. if (!tile.isVisibleAndInRequestVolume) {
  85148. this.loadTile(tile, frameState);
  85149. }
  85150. this.touchTile(tile, frameState);
  85151. const traverse = !tile.hasRenderContent && this.canTraverse(tile, frameState, false, true);
  85152. if (traverse) {
  85153. const children = tile.children;
  85154. for (const child of children) {
  85155. if (stack.find(child)) {
  85156. stack.delete(child);
  85157. }
  85158. stack.push(child);
  85159. }
  85160. } else if (!tile.contentAvailable) {
  85161. allDescendantsLoaded = false;
  85162. }
  85163. }
  85164. return allDescendantsLoaded;
  85165. }
  85166. }
  85167. const scratchVector = new Vector3$1();
  85168. function defined$2(x) {
  85169. return x !== undefined && x !== null;
  85170. }
  85171. class TileHeader {
  85172. constructor(tileset, header, parentHeader, extendedId = '') {
  85173. _defineProperty(this, "tileset", void 0);
  85174. _defineProperty(this, "header", void 0);
  85175. _defineProperty(this, "id", void 0);
  85176. _defineProperty(this, "url", void 0);
  85177. _defineProperty(this, "parent", void 0);
  85178. _defineProperty(this, "refine", void 0);
  85179. _defineProperty(this, "type", void 0);
  85180. _defineProperty(this, "contentUrl", void 0);
  85181. _defineProperty(this, "lodMetricType", void 0);
  85182. _defineProperty(this, "lodMetricValue", void 0);
  85183. _defineProperty(this, "boundingVolume", void 0);
  85184. _defineProperty(this, "content", void 0);
  85185. _defineProperty(this, "contentState", void 0);
  85186. _defineProperty(this, "gpuMemoryUsageInBytes", void 0);
  85187. _defineProperty(this, "children", void 0);
  85188. _defineProperty(this, "depth", void 0);
  85189. _defineProperty(this, "viewportIds", void 0);
  85190. _defineProperty(this, "transform", void 0);
  85191. _defineProperty(this, "extensions", void 0);
  85192. _defineProperty(this, "userData", void 0);
  85193. _defineProperty(this, "computedTransform", void 0);
  85194. _defineProperty(this, "hasEmptyContent", void 0);
  85195. _defineProperty(this, "hasTilesetContent", void 0);
  85196. _defineProperty(this, "traverser", void 0);
  85197. _defineProperty(this, "_cacheNode", void 0);
  85198. _defineProperty(this, "_frameNumber", void 0);
  85199. _defineProperty(this, "_lodJudge", void 0);
  85200. _defineProperty(this, "_expireDate", void 0);
  85201. _defineProperty(this, "_expiredContent", void 0);
  85202. _defineProperty(this, "_shouldRefine", void 0);
  85203. _defineProperty(this, "_distanceToCamera", void 0);
  85204. _defineProperty(this, "_centerZDepth", void 0);
  85205. _defineProperty(this, "_screenSpaceError", void 0);
  85206. _defineProperty(this, "_visibilityPlaneMask", void 0);
  85207. _defineProperty(this, "_visible", void 0);
  85208. _defineProperty(this, "_inRequestVolume", void 0);
  85209. _defineProperty(this, "_stackLength", void 0);
  85210. _defineProperty(this, "_selectionDepth", void 0);
  85211. _defineProperty(this, "_touchedFrame", void 0);
  85212. _defineProperty(this, "_visitedFrame", void 0);
  85213. _defineProperty(this, "_selectedFrame", void 0);
  85214. _defineProperty(this, "_requestedFrame", void 0);
  85215. _defineProperty(this, "_priority", void 0);
  85216. _defineProperty(this, "_contentBoundingVolume", void 0);
  85217. _defineProperty(this, "_viewerRequestVolume", void 0);
  85218. _defineProperty(this, "_initialTransform", void 0);
  85219. this.header = header;
  85220. this.tileset = tileset;
  85221. this.id = extendedId || header.id;
  85222. this.url = header.url;
  85223. this.parent = parentHeader;
  85224. this.refine = this._getRefine(header.refine);
  85225. this.type = header.type;
  85226. this.contentUrl = header.contentUrl;
  85227. this.lodMetricType = 'geometricError';
  85228. this.lodMetricValue = 0;
  85229. this.boundingVolume = null;
  85230. this.content = null;
  85231. this.contentState = TILE_CONTENT_STATE.UNLOADED;
  85232. this.gpuMemoryUsageInBytes = 0;
  85233. this.children = [];
  85234. this.hasEmptyContent = false;
  85235. this.hasTilesetContent = false;
  85236. this.depth = 0;
  85237. this.viewportIds = [];
  85238. this.userData = {};
  85239. this.extensions = null;
  85240. this._priority = 0;
  85241. this._touchedFrame = 0;
  85242. this._visitedFrame = 0;
  85243. this._selectedFrame = 0;
  85244. this._requestedFrame = 0;
  85245. this._screenSpaceError = 0;
  85246. this._cacheNode = null;
  85247. this._frameNumber = null;
  85248. this._cacheNode = null;
  85249. this.traverser = new TilesetTraverser({});
  85250. this._shouldRefine = false;
  85251. this._distanceToCamera = 0;
  85252. this._centerZDepth = 0;
  85253. this._visible = undefined;
  85254. this._inRequestVolume = false;
  85255. this._stackLength = 0;
  85256. this._selectionDepth = 0;
  85257. this._initialTransform = new Matrix4$1();
  85258. this.transform = new Matrix4$1();
  85259. this._initializeLodMetric(header);
  85260. this._initializeTransforms(header);
  85261. this._initializeBoundingVolumes(header);
  85262. this._initializeContent(header);
  85263. this._initializeRenderingState(header);
  85264. this._lodJudge = null;
  85265. this._expireDate = null;
  85266. this._expiredContent = null;
  85267. Object.seal(this);
  85268. }
  85269. destroy() {
  85270. this.header = null;
  85271. }
  85272. isDestroyed() {
  85273. return this.header === null;
  85274. }
  85275. get selected() {
  85276. return this._selectedFrame === this.tileset._frameNumber;
  85277. }
  85278. get isVisible() {
  85279. return this._visible;
  85280. }
  85281. get isVisibleAndInRequestVolume() {
  85282. return this._visible && this._inRequestVolume;
  85283. }
  85284. get hasRenderContent() {
  85285. return !this.hasEmptyContent && !this.hasTilesetContent;
  85286. }
  85287. get hasChildren() {
  85288. return this.children.length > 0 || this.header.children && this.header.children.length > 0;
  85289. }
  85290. get contentReady() {
  85291. return this.contentState === TILE_CONTENT_STATE.READY || this.hasEmptyContent;
  85292. }
  85293. get contentAvailable() {
  85294. return Boolean(this.contentReady && this.hasRenderContent || this._expiredContent && !this.contentFailed);
  85295. }
  85296. get hasUnloadedContent() {
  85297. return this.hasRenderContent && this.contentUnloaded;
  85298. }
  85299. get contentUnloaded() {
  85300. return this.contentState === TILE_CONTENT_STATE.UNLOADED;
  85301. }
  85302. get contentExpired() {
  85303. return this.contentState === TILE_CONTENT_STATE.EXPIRED;
  85304. }
  85305. get contentFailed() {
  85306. return this.contentState === TILE_CONTENT_STATE.FAILED;
  85307. }
  85308. getScreenSpaceError(frameState, useParentLodMetric) {
  85309. switch (this.tileset.type) {
  85310. case TILESET_TYPE.I3S:
  85311. return getProjectedRadius(this, frameState);
  85312. case TILESET_TYPE.TILES3D:
  85313. return getTiles3DScreenSpaceError(this, frameState, useParentLodMetric);
  85314. default:
  85315. throw new Error('Unsupported tileset type');
  85316. }
  85317. }
  85318. _getPriority() {
  85319. const traverser = this.tileset._traverser;
  85320. const {
  85321. skipLevelOfDetail
  85322. } = traverser.options;
  85323. const maySkipTile = this.refine === TILE_REFINEMENT.ADD || skipLevelOfDetail;
  85324. if (maySkipTile && !this.isVisible && this._visible !== undefined) {
  85325. return -1;
  85326. }
  85327. if (this.tileset._frameNumber - this._touchedFrame >= 1) {
  85328. return -1;
  85329. }
  85330. if (this.contentState === TILE_CONTENT_STATE.UNLOADED) {
  85331. return -1;
  85332. }
  85333. const parent = this.parent;
  85334. const useParentScreenSpaceError = parent && (!maySkipTile || this._screenSpaceError === 0.0 || parent.hasTilesetContent);
  85335. const screenSpaceError = useParentScreenSpaceError ? parent._screenSpaceError : this._screenSpaceError;
  85336. const rootScreenSpaceError = traverser.root ? traverser.root._screenSpaceError : 0.0;
  85337. return Math.max(rootScreenSpaceError - screenSpaceError, 0);
  85338. }
  85339. async loadContent() {
  85340. if (this.hasEmptyContent) {
  85341. return false;
  85342. }
  85343. if (this.content) {
  85344. return true;
  85345. }
  85346. const expired = this.contentExpired;
  85347. if (expired) {
  85348. this._expireDate = null;
  85349. }
  85350. this.contentState = TILE_CONTENT_STATE.LOADING;
  85351. const requestToken = await this.tileset._requestScheduler.scheduleRequest(this.id, this._getPriority.bind(this));
  85352. if (!requestToken) {
  85353. this.contentState = TILE_CONTENT_STATE.UNLOADED;
  85354. return false;
  85355. }
  85356. try {
  85357. const contentUrl = this.tileset.getTileUrl(this.contentUrl);
  85358. const loader = this.tileset.loader;
  85359. const options = { ...this.tileset.loadOptions,
  85360. [loader.id]: { ...this.tileset.loadOptions[loader.id],
  85361. isTileset: this.type === 'json',
  85362. ...this._getLoaderSpecificOptions(loader.id)
  85363. }
  85364. };
  85365. this.content = await load(contentUrl, loader, options);
  85366. // !zeg改
  85367. if (this.tileset.options.maxDepth < this.depth) {
  85368. this.unloadContent();
  85369. return false
  85370. }
  85371. if (this.tileset.options.contentLoader) {
  85372. await this.tileset.options.contentLoader(this);
  85373. }
  85374. if (this._isTileset()) {
  85375. this.tileset._initializeTileHeaders(this.content, this);
  85376. }
  85377. this.contentState = TILE_CONTENT_STATE.READY;
  85378. this._onContentLoaded();
  85379. return true;
  85380. } catch (error) {
  85381. this.contentState = TILE_CONTENT_STATE.FAILED;
  85382. throw error;
  85383. } finally {
  85384. requestToken.done();
  85385. }
  85386. }
  85387. unloadContent() {
  85388. if (this.content && this.content.destroy) {
  85389. this.content.destroy();
  85390. }
  85391. this.content = null;
  85392. if (this.header.content && this.header.content.destroy) {
  85393. this.header.content.destroy();
  85394. }
  85395. this.header.content = null;
  85396. this.contentState = TILE_CONTENT_STATE.UNLOADED;
  85397. return true;
  85398. }
  85399. updateVisibility(frameState, viewportIds) {
  85400. if (this._frameNumber === frameState.frameNumber) {
  85401. return;
  85402. }
  85403. const parent = this.parent;
  85404. const parentVisibilityPlaneMask = parent ? parent._visibilityPlaneMask : CullingVolume.MASK_INDETERMINATE;
  85405. if (this.tileset._traverser.options.updateTransforms) {
  85406. const parentTransform = parent ? parent.computedTransform : this.tileset.modelMatrix;
  85407. this._updateTransform(parentTransform);
  85408. }
  85409. this._distanceToCamera = this.distanceToTile(frameState);
  85410. this._screenSpaceError = this.getScreenSpaceError(frameState, false);
  85411. this._visibilityPlaneMask = this.visibility(frameState, parentVisibilityPlaneMask);
  85412. this._visible = this._visibilityPlaneMask !== CullingVolume.MASK_OUTSIDE;
  85413. this._inRequestVolume = this.insideViewerRequestVolume(frameState);
  85414. this._frameNumber = frameState.frameNumber;
  85415. this.viewportIds = viewportIds;
  85416. }
  85417. visibility(frameState, parentVisibilityPlaneMask) {
  85418. const {
  85419. cullingVolume
  85420. } = frameState;
  85421. const {
  85422. boundingVolume
  85423. } = this;
  85424. return cullingVolume.computeVisibilityWithPlaneMask(boundingVolume, parentVisibilityPlaneMask);
  85425. }
  85426. contentVisibility() {
  85427. return true;
  85428. }
  85429. distanceToTile(frameState) {
  85430. const boundingVolume = this.boundingVolume;
  85431. return Math.sqrt(Math.max(boundingVolume.distanceSquaredTo(frameState.camera.position), 0));
  85432. }
  85433. cameraSpaceZDepth({
  85434. camera
  85435. }) {
  85436. const boundingVolume = this.boundingVolume;
  85437. scratchVector.subVectors(boundingVolume.center, camera.position);
  85438. return camera.direction.dot(scratchVector);
  85439. }
  85440. insideViewerRequestVolume(frameState) {
  85441. const viewerRequestVolume = this._viewerRequestVolume;
  85442. return !viewerRequestVolume || viewerRequestVolume.distanceSquaredTo(frameState.camera.position) <= 0;
  85443. }
  85444. updateExpiration() {
  85445. if (defined$2(this._expireDate) && this.contentReady && !this.hasEmptyContent) {
  85446. const now = Date.now();
  85447. if (Date.lessThan(this._expireDate, now)) {
  85448. this.contentState = TILE_CONTENT_STATE.EXPIRED;
  85449. this._expiredContent = this.content;
  85450. }
  85451. }
  85452. }
  85453. get extras() {
  85454. return this.header.extras;
  85455. }
  85456. _initializeLodMetric(header) {
  85457. if ('lodMetricType' in header) {
  85458. this.lodMetricType = header.lodMetricType;
  85459. } else {
  85460. this.lodMetricType = this.parent && this.parent.lodMetricType || this.tileset.lodMetricType;
  85461. console.warn("3D Tile: Required prop lodMetricType is undefined. Using parent lodMetricType");
  85462. }
  85463. if ('lodMetricValue' in header) {
  85464. this.lodMetricValue = header.lodMetricValue;
  85465. } else {
  85466. this.lodMetricValue = this.parent && this.parent.lodMetricValue || this.tileset.lodMetricValue;
  85467. console.warn('3D Tile: Required prop lodMetricValue is undefined. Using parent lodMetricValue');
  85468. }
  85469. }
  85470. _initializeTransforms(tileHeader) {
  85471. this.transform = tileHeader.transform ? new Matrix4$1(tileHeader.transform) : new Matrix4$1();
  85472. const parent = this.parent;
  85473. const tileset = this.tileset;
  85474. const parentTransform = parent && parent.computedTransform ? parent.computedTransform.clone() : tileset.modelMatrix.clone();
  85475. this.computedTransform = new Matrix4$1(parentTransform).multiplyRight(this.transform);
  85476. const parentInitialTransform = parent && parent._initialTransform ? parent._initialTransform.clone() : new Matrix4$1();
  85477. this._initialTransform = new Matrix4$1(parentInitialTransform).multiplyRight(this.transform);
  85478. }
  85479. _initializeBoundingVolumes(tileHeader) {
  85480. this._contentBoundingVolume = null;
  85481. this._viewerRequestVolume = null;
  85482. this._updateBoundingVolume(tileHeader);
  85483. }
  85484. _initializeContent(tileHeader) {
  85485. this.content = {
  85486. _tileset: this.tileset,
  85487. _tile: this
  85488. };
  85489. this.hasEmptyContent = true;
  85490. this.contentState = TILE_CONTENT_STATE.UNLOADED;
  85491. this.hasTilesetContent = false;
  85492. if (tileHeader.contentUrl) {
  85493. this.content = null;
  85494. this.hasEmptyContent = false;
  85495. }
  85496. }
  85497. _initializeRenderingState(header) {
  85498. this.depth = header.level || (this.parent ? this.parent.depth + 1 : 0);
  85499. this._shouldRefine = false;
  85500. this._distanceToCamera = 0;
  85501. this._centerZDepth = 0;
  85502. this._screenSpaceError = 0;
  85503. this._visibilityPlaneMask = CullingVolume.MASK_INDETERMINATE;
  85504. this._visible = undefined;
  85505. this._inRequestVolume = false;
  85506. this._stackLength = 0;
  85507. this._selectionDepth = 0;
  85508. this._frameNumber = 0;
  85509. this._touchedFrame = 0;
  85510. this._visitedFrame = 0;
  85511. this._selectedFrame = 0;
  85512. this._requestedFrame = 0;
  85513. this._priority = 0.0;
  85514. }
  85515. _getRefine(refine) {
  85516. return refine || this.parent && this.parent.refine || TILE_REFINEMENT.REPLACE;
  85517. }
  85518. _isTileset() {
  85519. return this.contentUrl.indexOf('.json') !== -1;
  85520. }
  85521. _onContentLoaded() {
  85522. switch (this.content && this.content.type) {
  85523. case 'vctr':
  85524. case 'geom':
  85525. this.tileset._traverser.disableSkipLevelOfDetail = true;
  85526. break;
  85527. }
  85528. if (this._isTileset()) {
  85529. this.hasTilesetContent = true;
  85530. }
  85531. }
  85532. _updateBoundingVolume(header) {
  85533. this.boundingVolume = createBoundingVolume(header.boundingVolume, this.computedTransform, this.boundingVolume);
  85534. const content = header.content;
  85535. if (!content) {
  85536. return;
  85537. }
  85538. if (content.boundingVolume) {
  85539. this._contentBoundingVolume = createBoundingVolume(content.boundingVolume, this.computedTransform, this._contentBoundingVolume);
  85540. }
  85541. if (header.viewerRequestVolume) {
  85542. this._viewerRequestVolume = createBoundingVolume(header.viewerRequestVolume, this.computedTransform, this._viewerRequestVolume);
  85543. }
  85544. }
  85545. _updateTransform(parentTransform = new Matrix4$1()) {
  85546. const computedTransform = parentTransform.clone().multiplyRight(this.transform);
  85547. const didTransformChange = !computedTransform.equals(this.computedTransform);
  85548. if (!didTransformChange) {
  85549. return;
  85550. }
  85551. this.computedTransform = computedTransform;
  85552. this._updateBoundingVolume(this.header);
  85553. }
  85554. _getLoaderSpecificOptions(loaderId) {
  85555. switch (loaderId) {
  85556. case 'i3s':
  85557. return { ...this.tileset.options.i3s,
  85558. tile: this.header,
  85559. tileset: this.tileset.tileset,
  85560. isTileHeader: false
  85561. };
  85562. case '3d-tiles':
  85563. case 'cesium-ion':
  85564. default:
  85565. return get3dTilesOptions(this.tileset.tileset);
  85566. }
  85567. }
  85568. }
  85569. class Tileset3DTraverser extends TilesetTraverser {
  85570. compareDistanceToCamera(a, b) {
  85571. return b._distanceToCamera === 0 && a._distanceToCamera === 0 ? b._centerZDepth - a._centerZDepth : b._distanceToCamera - a._distanceToCamera;
  85572. }
  85573. updateTileVisibility(tile, frameState) {
  85574. super.updateTileVisibility(tile, frameState);
  85575. if (!tile.isVisibleAndInRequestVolume) {
  85576. return;
  85577. }
  85578. const hasChildren = tile.children.length > 0;
  85579. if (tile.hasTilesetContent && hasChildren) {
  85580. const firstChild = tile.children[0];
  85581. this.updateTileVisibility(firstChild, frameState);
  85582. tile._visible = firstChild._visible;
  85583. return;
  85584. }
  85585. if (this.meetsScreenSpaceErrorEarly(tile, frameState)) {
  85586. tile._visible = false;
  85587. return;
  85588. }
  85589. const replace = tile.refine === TILE_REFINEMENT.REPLACE;
  85590. const useOptimization = tile._optimChildrenWithinParent === TILE3D_OPTIMIZATION_HINT.USE_OPTIMIZATION;
  85591. if (replace && useOptimization && hasChildren) {
  85592. if (!this.anyChildrenVisible(tile, frameState)) {
  85593. tile._visible = false;
  85594. return;
  85595. }
  85596. }
  85597. }
  85598. meetsScreenSpaceErrorEarly(tile, frameState) {
  85599. const {
  85600. parent
  85601. } = tile;
  85602. if (!parent || parent.hasTilesetContent || parent.refine !== TILE_REFINEMENT.ADD) {
  85603. return false;
  85604. }
  85605. return !this.shouldRefine(tile, frameState, true);
  85606. }
  85607. }
  85608. const STATUS = {
  85609. REQUESTED: 'REQUESTED',
  85610. COMPLETED: 'COMPLETED',
  85611. ERROR: 'ERROR'
  85612. };
  85613. class I3STileManager {
  85614. constructor() {
  85615. _defineProperty(this, "_statusMap", void 0);
  85616. this._statusMap = {};
  85617. }
  85618. add(request, key, callback, frameState) {
  85619. if (!this._statusMap[key]) {
  85620. this._statusMap[key] = {
  85621. request,
  85622. callback,
  85623. key,
  85624. frameState,
  85625. status: STATUS.REQUESTED
  85626. };
  85627. request().then(data => {
  85628. this._statusMap[key].status = STATUS.COMPLETED;
  85629. this._statusMap[key].callback(data, frameState);
  85630. }).catch(error => {
  85631. this._statusMap[key].status = STATUS.ERROR;
  85632. callback(error);
  85633. });
  85634. }
  85635. }
  85636. update(key, frameState) {
  85637. if (this._statusMap[key]) {
  85638. this._statusMap[key].frameState = frameState;
  85639. }
  85640. }
  85641. find(key) {
  85642. return this._statusMap[key];
  85643. }
  85644. }
  85645. class I3STilesetTraverser extends TilesetTraverser {
  85646. constructor(options) {
  85647. super(options);
  85648. _defineProperty(this, "_tileManager", void 0);
  85649. this._tileManager = new I3STileManager();
  85650. }
  85651. shouldRefine(tile, frameState) {
  85652. tile._lodJudge = getLodStatus(tile, frameState);
  85653. return tile._lodJudge === 'DIG';
  85654. }
  85655. updateChildTiles(tile, frameState) {
  85656. const children = tile.header.children || [];
  85657. const childTiles = tile.children;
  85658. const tileset = tile.tileset;
  85659. for (const child of children) {
  85660. const extendedId = "".concat(child.id, "-").concat(frameState.viewport.id);
  85661. const childTile = childTiles && childTiles.find(t => t.id === extendedId);
  85662. if (!childTile) {
  85663. let request = () => this._loadTile(child.id, tileset);
  85664. const cachedRequest = this._tileManager.find(extendedId);
  85665. if (!cachedRequest) {
  85666. if (tileset.tileset.nodePages) {
  85667. request = () => tileset.tileset.nodePagesTile.formTileFromNodePages(child.id);
  85668. }
  85669. this._tileManager.add(request, extendedId, header => this._onTileLoad(header, tile, extendedId), frameState);
  85670. } else {
  85671. this._tileManager.update(extendedId, frameState);
  85672. }
  85673. } else if (childTile) {
  85674. this.updateTile(childTile, frameState);
  85675. }
  85676. }
  85677. return false;
  85678. }
  85679. async _loadTile(nodeId, tileset) {
  85680. const {
  85681. loader
  85682. } = tileset;
  85683. const nodeUrl = tileset.getTileUrl("".concat(tileset.url, "/nodes/").concat(nodeId));
  85684. const options = { ...tileset.loadOptions,
  85685. i3s: { ...tileset.loadOptions.i3s,
  85686. isTileHeader: true,
  85687. loadContent: false
  85688. }
  85689. };
  85690. return await load(nodeUrl, loader, options);
  85691. }
  85692. _onTileLoad(header, tile, extendedId) {
  85693. const childTile = new TileHeader(tile.tileset, header, tile, extendedId);
  85694. tile.children.push(childTile);
  85695. const frameState = this._tileManager.find(childTile.id).frameState;
  85696. this.updateTile(childTile, frameState);
  85697. if (this._frameNumber === frameState.frameNumber) {
  85698. this.executeTraversal(childTile, frameState);
  85699. }
  85700. }
  85701. }
  85702. const DEFAULT_PROPS = {
  85703. description: '',
  85704. ellipsoid: Ellipsoid.WGS84,
  85705. modelMatrix: new Matrix4$1(),
  85706. throttleRequests: true,
  85707. maxRequests: 64,
  85708. maximumMemoryUsage: 32,
  85709. onTileLoad: () => {},
  85710. onTileUnload: () => {},
  85711. onTileError: () => {},
  85712. onTraversalComplete: selectedTiles => selectedTiles,
  85713. contentLoader: undefined,
  85714. viewDistanceScale: 1.0,
  85715. maximumScreenSpaceError: 8,
  85716. loadTiles: true,
  85717. updateTransforms: true,
  85718. viewportTraversersMap: null,
  85719. loadOptions: {
  85720. fetch: {}
  85721. },
  85722. attributions: [],
  85723. basePath: '',
  85724. i3s: {}
  85725. };
  85726. const TILES_TOTAL = 'Tiles In Tileset(s)';
  85727. const TILES_IN_MEMORY = 'Tiles In Memory';
  85728. const TILES_IN_VIEW = 'Tiles In View';
  85729. const TILES_RENDERABLE = 'Tiles To Render';
  85730. const TILES_LOADED = 'Tiles Loaded';
  85731. const TILES_LOADING = 'Tiles Loading';
  85732. const TILES_UNLOADED = 'Tiles Unloaded';
  85733. const TILES_LOAD_FAILED = 'Failed Tile Loads';
  85734. const POINTS_COUNT = 'Points';
  85735. const TILES_GPU_MEMORY = 'Tile Memory Use';
  85736. let tilesetSid = 0;//add
  85737. class Tileset3D extends EventDispatcher{//xzw add EventDispatcher
  85738. constructor(json, options) {
  85739. super();
  85740. _defineProperty(this, "options", void 0);
  85741. _defineProperty(this, "loadOptions", void 0);
  85742. _defineProperty(this, "type", void 0);
  85743. _defineProperty(this, "tileset", void 0);
  85744. _defineProperty(this, "loader", void 0);
  85745. _defineProperty(this, "url", void 0);
  85746. _defineProperty(this, "basePath", void 0);
  85747. _defineProperty(this, "modelMatrix", void 0);
  85748. _defineProperty(this, "ellipsoid", void 0);
  85749. _defineProperty(this, "lodMetricType", void 0);
  85750. _defineProperty(this, "lodMetricValue", void 0);
  85751. _defineProperty(this, "refine", void 0);
  85752. _defineProperty(this, "root", void 0);
  85753. _defineProperty(this, "roots", void 0);
  85754. _defineProperty(this, "asset", void 0);
  85755. _defineProperty(this, "description", void 0);
  85756. _defineProperty(this, "properties", void 0);
  85757. _defineProperty(this, "extras", void 0);
  85758. _defineProperty(this, "attributions", void 0);
  85759. _defineProperty(this, "credits", void 0);
  85760. _defineProperty(this, "stats", void 0);
  85761. _defineProperty(this, "traverseCounter", void 0);
  85762. _defineProperty(this, "geometricError", void 0);
  85763. _defineProperty(this, "selectedTiles", void 0);
  85764. _defineProperty(this, "cartographicCenter", void 0);
  85765. _defineProperty(this, "cartesianCenter", void 0);
  85766. _defineProperty(this, "zoom", void 0);
  85767. _defineProperty(this, "boundingVolume", void 0);
  85768. _defineProperty(this, "gpuMemoryUsageInBytes", void 0);
  85769. _defineProperty(this, "dynamicScreenSpaceErrorComputedDensity", void 0);
  85770. _defineProperty(this, "_traverser", void 0);
  85771. _defineProperty(this, "_cache", void 0);
  85772. _defineProperty(this, "_requestScheduler", void 0);
  85773. _defineProperty(this, "_frameNumber", void 0);
  85774. _defineProperty(this, "_queryParamsString", void 0);
  85775. _defineProperty(this, "_queryParams", void 0);
  85776. _defineProperty(this, "_extensionsUsed", void 0);
  85777. _defineProperty(this, "_tiles", void 0);
  85778. _defineProperty(this, "_pendingCount", void 0);
  85779. _defineProperty(this, "lastUpdatedVieports", void 0);
  85780. _defineProperty(this, "_requestedTiles", void 0);
  85781. _defineProperty(this, "_emptyTiles", void 0);
  85782. _defineProperty(this, "frameStateData", void 0);
  85783. _defineProperty(this, "maximumMemoryUsage", void 0);
  85784. assert$7(json);
  85785. this.options = { ...DEFAULT_PROPS,
  85786. ...options
  85787. };
  85788. this.tileset = json;
  85789. this.loader = json.loader;
  85790. this.type = json.type;
  85791. this.url = json.url;
  85792. this.basePath = json.basePath || dirname(this.url);
  85793. this.modelMatrix = this.options.modelMatrix;
  85794. this.ellipsoid = this.options.ellipsoid;
  85795. this.lodMetricType = json.lodMetricType;
  85796. this.lodMetricValue = json.lodMetricValue;
  85797. this.refine = json.root.refine;
  85798. this.loadOptions = this.options.loadOptions || {};
  85799. this.root = null;
  85800. this.roots = {};
  85801. this.cartographicCenter = null;
  85802. this.cartesianCenter = null;
  85803. this.zoom = 1;
  85804. this.boundingVolume = null;
  85805. this.traverseCounter = 0;
  85806. this.geometricError = 0;
  85807. this._traverser = this._initializeTraverser();
  85808. this._cache = new TilesetCache();
  85809. this._requestScheduler = new RequestScheduler({
  85810. throttleRequests: this.options.throttleRequests,
  85811. maxRequests: this.options.maxRequests
  85812. });
  85813. this._frameNumber = 0;
  85814. this._pendingCount = 0;
  85815. this._tiles = {};
  85816. this.selectedTiles = [];
  85817. this._emptyTiles = [];
  85818. this._requestedTiles = [];
  85819. this.frameStateData = {};
  85820. this.lastUpdatedVieports = null;
  85821. this._queryParams = {};
  85822. this._queryParamsString = '';
  85823. this.maximumMemoryUsage = this.options.maximumMemoryUsage || 32;
  85824. this.gpuMemoryUsageInBytes = 0;
  85825. this.stats = new Stats$1({
  85826. id: this.url
  85827. });
  85828. this._initializeStats();
  85829. this._extensionsUsed = undefined;
  85830. this.dynamicScreenSpaceErrorComputedDensity = 0.0;
  85831. this.extras = null;
  85832. this.asset = {};
  85833. this.credits = {};
  85834. this.description = this.options.description || '';
  85835. this._initializeTileSet(json);
  85836. }
  85837. destroy() {
  85838. this._destroy();
  85839. }
  85840. isLoaded() {
  85841. return this._pendingCount === 0 && this._frameNumber !== 0;
  85842. }
  85843. get tiles() {
  85844. return Object.values(this._tiles);
  85845. }
  85846. get frameNumber() {
  85847. return this._frameNumber;
  85848. }
  85849. get queryParams() {
  85850. if (!this._queryParamsString) {
  85851. this._queryParamsString = getQueryParamString(this._queryParams);
  85852. }
  85853. return this._queryParamsString;
  85854. }
  85855. setProps(props) {
  85856. this.options = { ...this.options,
  85857. ...props
  85858. };
  85859. }
  85860. setOptions(options) {
  85861. this.options = { ...this.options,
  85862. ...options
  85863. };
  85864. }
  85865. getTileUrl(tilePath) {
  85866. const isDataUrl = tilePath.startsWith('data:');
  85867. tilePath = Potree.Common.dealURL(tilePath); //add 去除'+'
  85868. if (isDataUrl) {
  85869. return tilePath;
  85870. }
  85871. return "".concat(tilePath).concat(this.queryParams);
  85872. }
  85873. hasExtension(extensionName) {
  85874. return Boolean(this._extensionsUsed && this._extensionsUsed.indexOf(extensionName) > -1);
  85875. }
  85876. update(viewports) {
  85877. if ('loadTiles' in this.options && !this.options.loadTiles) {
  85878. return;
  85879. }
  85880. if (this.traverseCounter > 0) {
  85881. return;
  85882. }
  85883. if (!viewports && this.lastUpdatedVieports) {
  85884. viewports = this.lastUpdatedVieports;
  85885. } else {
  85886. this.lastUpdatedVieports = viewports;
  85887. }
  85888. if (!(viewports instanceof Array)) {
  85889. viewports = [viewports];
  85890. }
  85891. this._cache.reset();
  85892. this._frameNumber++;
  85893. this.traverseCounter = viewports.length;
  85894. const viewportsToTraverse = [];
  85895. for (const viewport of viewports) {
  85896. const id = viewport.id;
  85897. if (this._needTraverse(id)) {
  85898. viewportsToTraverse.push(id);
  85899. } else {
  85900. this.traverseCounter--;
  85901. }
  85902. }
  85903. for (const viewport of viewports) {
  85904. const id = viewport.id;
  85905. if (!this.roots[id]) {
  85906. this.roots[id] = this._initializeTileHeaders(this.tileset, null);
  85907. }
  85908. if (!viewportsToTraverse.includes(id)) {
  85909. continue;
  85910. }
  85911. const frameState = getFrameState(viewport, this._frameNumber);
  85912. this._traverser.traverse(this.roots[id], frameState, this.options);
  85913. }
  85914. }
  85915. _needTraverse(viewportId) {
  85916. let traverserId = viewportId;
  85917. if (this.options.viewportTraversersMap) {
  85918. traverserId = this.options.viewportTraversersMap[viewportId];
  85919. }
  85920. if (traverserId !== viewportId) {
  85921. return false;
  85922. }
  85923. return true;
  85924. }
  85925. _onTraversalEnd(frameState) {
  85926. const id = frameState.viewport.id;
  85927. if (!this.frameStateData[id]) {
  85928. this.frameStateData[id] = {
  85929. selectedTiles: [],
  85930. _requestedTiles: [],
  85931. _emptyTiles: []
  85932. };
  85933. }
  85934. const currentFrameStateData = this.frameStateData[id];
  85935. const selectedTiles = Object.values(this._traverser.selectedTiles);
  85936. currentFrameStateData.selectedTiles = selectedTiles;
  85937. currentFrameStateData._requestedTiles = Object.values(this._traverser.requestedTiles);
  85938. currentFrameStateData._emptyTiles = Object.values(this._traverser.emptyTiles);
  85939. this.traverseCounter--;
  85940. if (this.traverseCounter > 0) {
  85941. return;
  85942. }
  85943. this._updateTiles();
  85944. }
  85945. _updateTiles() {
  85946. this.selectedTiles = [];
  85947. this._requestedTiles = [];
  85948. this._emptyTiles = [];
  85949. for (const frameStateKey in this.frameStateData) {
  85950. const frameStateDataValue = this.frameStateData[frameStateKey];
  85951. this.selectedTiles = this.selectedTiles.concat(frameStateDataValue.selectedTiles);
  85952. this._requestedTiles = this._requestedTiles.concat(frameStateDataValue._requestedTiles);
  85953. this._emptyTiles = this._emptyTiles.concat(frameStateDataValue._emptyTiles);
  85954. }
  85955. this.selectedTiles = this.options.onTraversalComplete(this.selectedTiles);
  85956. for (const tile of this.selectedTiles) {
  85957. this._tiles[tile.id] = tile;
  85958. }
  85959. this._loadTiles();
  85960. this._unloadTiles();
  85961. this._updateStats();
  85962. }
  85963. _tilesChanged(oldSelectedTiles, selectedTiles) {
  85964. if (oldSelectedTiles.length !== selectedTiles.length) {
  85965. return true;
  85966. }
  85967. const set1 = new Set(oldSelectedTiles.map(t => t.id));
  85968. const set2 = new Set(selectedTiles.map(t => t.id));
  85969. let changed = oldSelectedTiles.filter(x => !set2.has(x.id)).length > 0;
  85970. changed = changed || selectedTiles.filter(x => !set1.has(x.id)).length > 0;
  85971. return changed;
  85972. }
  85973. _loadTiles() {
  85974. for (const tile of this._requestedTiles) {
  85975. if (tile.contentUnloaded) {
  85976. this._loadTile(tile);
  85977. }
  85978. }
  85979. }
  85980. _unloadTiles() {
  85981. this._cache.unloadTiles(this, (tileset, tile) => tileset._unloadTile(tile));
  85982. }
  85983. _updateStats() {
  85984. let tilesRenderable = 0;
  85985. let pointsRenderable = 0;
  85986. for (const tile of this.selectedTiles) {
  85987. if (tile.contentAvailable && tile.content) {
  85988. tilesRenderable++;
  85989. if (tile.content.pointCount) {
  85990. pointsRenderable += tile.content.pointCount;
  85991. }
  85992. }
  85993. }
  85994. this.stats.get(TILES_IN_VIEW).count = this.selectedTiles.length;
  85995. this.stats.get(TILES_RENDERABLE).count = tilesRenderable;
  85996. this.stats.get(POINTS_COUNT).count = pointsRenderable;
  85997. }
  85998. _initializeTileSet(tilesetJson) {
  85999. this.root = this._initializeTileHeaders(tilesetJson, null);
  86000. if (this.type === TILESET_TYPE.TILES3D) {
  86001. this._initializeCesiumTileset(tilesetJson);
  86002. }
  86003. if (this.type === TILESET_TYPE.I3S) {
  86004. this._initializeI3STileset();
  86005. }
  86006. this._calculateViewProps();
  86007. }
  86008. _calculateViewProps() {
  86009. const root = this.root;
  86010. assert$7(root);
  86011. const {
  86012. center
  86013. } = root.boundingVolume;
  86014. if (!center) {
  86015. console.warn('center was not pre-calculated for the root tile');
  86016. this.cartographicCenter = new Vector3$1();
  86017. this.zoom = 1;
  86018. return;
  86019. }
  86020. this.cartographicCenter = Ellipsoid.WGS84.cartesianToCartographic(center, new Vector3$1());
  86021. this.cartesianCenter = center;
  86022. this.zoom = getZoomFromBoundingVolume(root.boundingVolume);
  86023. }
  86024. _initializeStats() {
  86025. this.stats.get(TILES_TOTAL);
  86026. this.stats.get(TILES_LOADING);
  86027. this.stats.get(TILES_IN_MEMORY);
  86028. this.stats.get(TILES_IN_VIEW);
  86029. this.stats.get(TILES_RENDERABLE);
  86030. this.stats.get(TILES_LOADED);
  86031. this.stats.get(TILES_UNLOADED);
  86032. this.stats.get(TILES_LOAD_FAILED);
  86033. this.stats.get(POINTS_COUNT, 'memory');
  86034. this.stats.get(TILES_GPU_MEMORY, 'memory');
  86035. }
  86036. _initializeTileHeaders(tilesetJson, parentTileHeader) {
  86037. const rootTile = new TileHeader(this, tilesetJson.root, parentTileHeader, parentTileHeader == void 0 && 'root_'+tilesetSid++);
  86038. if (parentTileHeader) {
  86039. parentTileHeader.children.push(rootTile);
  86040. rootTile.depth = parentTileHeader.depth + 1;
  86041. }
  86042. if (this.type === TILESET_TYPE.TILES3D) {
  86043. const stack = [];
  86044. stack.push(rootTile);
  86045. while (stack.length > 0) {
  86046. const tile = stack.pop();
  86047. this.stats.get(TILES_TOTAL).incrementCount();
  86048. const children = tile.header.children || [];
  86049. // !zeg改
  86050. if(tile.depth < this.options.maxDepth){
  86051. for (const childHeader of children) {
  86052. const childTile = new TileHeader(this, childHeader, tile);
  86053. tile.children.push(childTile);
  86054. childTile.depth = tile.depth + 1;
  86055. stack.push(childTile);
  86056. }
  86057. }
  86058. window.maxDepth = Math.max(window.maxDepth||0,tile.depth);
  86059. }
  86060. }
  86061. return rootTile;
  86062. }
  86063. _initializeTraverser() {
  86064. let TraverserClass;
  86065. const type = this.type;
  86066. switch (type) {
  86067. case TILESET_TYPE.TILES3D:
  86068. TraverserClass = Tileset3DTraverser;
  86069. break;
  86070. case TILESET_TYPE.I3S:
  86071. TraverserClass = I3STilesetTraverser;
  86072. break;
  86073. default:
  86074. TraverserClass = TilesetTraverser;
  86075. }
  86076. return new TraverserClass({
  86077. basePath: this.basePath,
  86078. onTraversalEnd: this._onTraversalEnd.bind(this)
  86079. });
  86080. }
  86081. _destroyTileHeaders(parentTile) {
  86082. this._destroySubtree(parentTile);
  86083. }
  86084. async _loadTile(tile) {
  86085. let loaded;
  86086. try {
  86087. this._onStartTileLoading();
  86088. loaded = await tile.loadContent();
  86089. } catch (error) {
  86090. this._onTileLoadError(tile, error);
  86091. } finally {
  86092. this._onEndTileLoading(tile);//
  86093. this._onTileLoad(tile, loaded);
  86094. }
  86095. }
  86096. _onTileLoadError(tile, error) {
  86097. this.stats.get(TILES_LOAD_FAILED).incrementCount();
  86098. const message = error.message || error.toString();
  86099. const url = tile.url;
  86100. console.error("A 3D tile failed to load: ".concat(tile.url, " ").concat(message));
  86101. this.options.onTileError(tile, message, url);
  86102. }
  86103. _onTileLoad(tile, loaded) {
  86104. if (!loaded) {
  86105. return;
  86106. }
  86107. if (tile && tile.content) {
  86108. calculateTransformProps(tile, tile.content);
  86109. }
  86110. this._addTileToCache(tile);
  86111. this.options.onTileLoad(tile);
  86112. }
  86113. _onStartTileLoading() {
  86114. this._pendingCount++;
  86115. this.stats.get(TILES_LOADING).incrementCount();
  86116. }
  86117. _onEndTileLoading(tile) {
  86118. this._pendingCount--;
  86119. this.stats.get(TILES_LOADING).decrementCount();
  86120. this.dispatchEvent({type:'endTileLoading', tile, loadingCount: this._pendingCount }); // !zeg改
  86121. }
  86122. _addTileToCache(tile) {
  86123. this._cache.add(this, tile, tileset => tileset._updateCacheStats(tile));
  86124. }
  86125. _updateCacheStats(tile) {
  86126. this.stats.get(TILES_LOADED).incrementCount();
  86127. this.stats.get(TILES_IN_MEMORY).incrementCount();
  86128. this.gpuMemoryUsageInBytes += tile.content.byteLength || 0;
  86129. this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
  86130. }
  86131. _unloadTile(tile) {
  86132. this.gpuMemoryUsageInBytes -= tile.content && tile.content.byteLength || 0;
  86133. this.stats.get(TILES_IN_MEMORY).decrementCount();
  86134. this.stats.get(TILES_UNLOADED).incrementCount();
  86135. this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
  86136. this.options.onTileUnload(tile);
  86137. tile.unloadContent();
  86138. }
  86139. _destroy() {
  86140. const stack = [];
  86141. if (this.root) {
  86142. stack.push(this.root);
  86143. }
  86144. while (stack.length > 0) {
  86145. const tile = stack.pop();
  86146. for (const child of tile.children) {
  86147. stack.push(child);
  86148. }
  86149. this._destroyTile(tile);
  86150. }
  86151. this.root = null;
  86152. }
  86153. _destroySubtree(tile) {
  86154. const root = tile;
  86155. const stack = [];
  86156. stack.push(root);
  86157. while (stack.length > 0) {
  86158. tile = stack.pop();
  86159. for (const child of tile.children) {
  86160. stack.push(child);
  86161. }
  86162. if (tile !== root) {
  86163. this._destroyTile(tile);
  86164. }
  86165. }
  86166. root.children = [];
  86167. }
  86168. _destroyTile(tile) {
  86169. this._cache.unloadTile(this, tile);
  86170. this._unloadTile(tile);
  86171. tile.destroy();
  86172. }
  86173. _initializeCesiumTileset(tilesetJson) {
  86174. this.asset = tilesetJson.asset;
  86175. if (!this.asset) {
  86176. throw new Error('Tileset must have an asset property.');
  86177. }
  86178. if (this.asset.version !== '0.0' && this.asset.version !== '1.0') {
  86179. throw new Error('The tileset must be 3D Tiles version 0.0 or 1.0.');
  86180. }
  86181. if ('tilesetVersion' in this.asset) {
  86182. this._queryParams.v = this.asset.tilesetVersion;
  86183. }
  86184. this.credits = {
  86185. attributions: this.options.attributions || []
  86186. };
  86187. this.description = this.options.description || '';
  86188. this.properties = tilesetJson.properties;
  86189. this.geometricError = tilesetJson.geometricError;
  86190. this._extensionsUsed = tilesetJson.extensionsUsed;
  86191. this.extras = tilesetJson.extras;
  86192. }
  86193. _initializeI3STileset() {
  86194. if (this.loadOptions.i3s && 'token' in this.loadOptions.i3s) {
  86195. this._queryParams.token = this.loadOptions.i3s.token;
  86196. }
  86197. }
  86198. }
  86199. function getQueryParamString(queryParams) {
  86200. const queryParamStrings = [];
  86201. for (const key of Object.keys(queryParams)) {
  86202. queryParamStrings.push("".concat(key, "=").concat(queryParams[key]));
  86203. }
  86204. switch (queryParamStrings.length) {
  86205. case 0:
  86206. return '';
  86207. case 1:
  86208. return "?".concat(queryParamStrings[0]);
  86209. default:
  86210. return "?".concat(queryParamStrings.join('&'));
  86211. }
  86212. }
  86213. const VERSION$5 = "3.1.4" ;
  86214. const TILE3D_TYPE = {
  86215. COMPOSITE: 'cmpt',
  86216. POINT_CLOUD: 'pnts',
  86217. BATCHED_3D_MODEL: 'b3dm',
  86218. INSTANCED_3D_MODEL: 'i3dm',
  86219. GEOMETRY: 'geom',
  86220. VECTOR: 'vect',
  86221. GLTF: 'glTF'
  86222. };
  86223. function getStringFromArrayBuffer(arrayBuffer, byteOffset, byteLength) {
  86224. assert$7(arrayBuffer instanceof ArrayBuffer);
  86225. const textDecoder = new TextDecoder('utf8');
  86226. const typedArray = new Uint8Array(arrayBuffer, byteOffset, byteLength);
  86227. const string = textDecoder.decode(typedArray);
  86228. return string;
  86229. }
  86230. function getMagicString$1(arrayBuffer, byteOffset = 0) {
  86231. const dataView = new DataView(arrayBuffer);
  86232. return "".concat(String.fromCharCode(dataView.getUint8(byteOffset + 0))).concat(String.fromCharCode(dataView.getUint8(byteOffset + 1))).concat(String.fromCharCode(dataView.getUint8(byteOffset + 2))).concat(String.fromCharCode(dataView.getUint8(byteOffset + 3)));
  86233. }
  86234. const VERSION$4 = "3.1.4" ;
  86235. const DEFAULT_DRACO_OPTIONS = {
  86236. draco: {
  86237. decoderType: typeof WebAssembly === 'object' ? 'wasm' : 'js',
  86238. libraryPath: 'libs/',
  86239. extraAttributes: {},
  86240. attributeNameEntry: undefined
  86241. }
  86242. };
  86243. const DracoLoader$1 = {
  86244. name: 'Draco',
  86245. id: 'draco',
  86246. module: 'draco',
  86247. shapes: ['mesh'],
  86248. version: VERSION$4,
  86249. worker: true,
  86250. extensions: ['drc'],
  86251. mimeTypes: ['application/octet-stream'],
  86252. binary: true,
  86253. tests: ['DRACO'],
  86254. options: DEFAULT_DRACO_OPTIONS
  86255. };
  86256. function getMeshBoundingBox(attributes) {
  86257. let minX = Infinity;
  86258. let minY = Infinity;
  86259. let minZ = Infinity;
  86260. let maxX = -Infinity;
  86261. let maxY = -Infinity;
  86262. let maxZ = -Infinity;
  86263. const positions = attributes.POSITION ? attributes.POSITION.value : [];
  86264. const len = positions && positions.length;
  86265. for (let i = 0; i < len; i += 3) {
  86266. const x = positions[i];
  86267. const y = positions[i + 1];
  86268. const z = positions[i + 2];
  86269. minX = x < minX ? x : minX;
  86270. minY = y < minY ? y : minY;
  86271. minZ = z < minZ ? z : minZ;
  86272. maxX = x > maxX ? x : maxX;
  86273. maxY = y > maxY ? y : maxY;
  86274. maxZ = z > maxZ ? z : maxZ;
  86275. }
  86276. return [[minX, minY, minZ], [maxX, maxY, maxZ]];
  86277. }
  86278. function assert$3(condition, message) {
  86279. if (!condition) {
  86280. throw new Error(message || 'loader assertion failed.');
  86281. }
  86282. }
  86283. class Schema {
  86284. constructor(fields, metadata) {
  86285. _defineProperty(this, "fields", void 0);
  86286. _defineProperty(this, "metadata", void 0);
  86287. assert$3(Array.isArray(fields));
  86288. checkNames(fields);
  86289. this.fields = fields;
  86290. this.metadata = metadata || new Map();
  86291. }
  86292. compareTo(other) {
  86293. if (this.metadata !== other.metadata) {
  86294. return false;
  86295. }
  86296. if (this.fields.length !== other.fields.length) {
  86297. return false;
  86298. }
  86299. for (let i = 0; i < this.fields.length; ++i) {
  86300. if (!this.fields[i].compareTo(other.fields[i])) {
  86301. return false;
  86302. }
  86303. }
  86304. return true;
  86305. }
  86306. select(...columnNames) {
  86307. const nameMap = Object.create(null);
  86308. for (const name of columnNames) {
  86309. nameMap[name] = true;
  86310. }
  86311. const selectedFields = this.fields.filter(field => nameMap[field.name]);
  86312. return new Schema(selectedFields, this.metadata);
  86313. }
  86314. selectAt(...columnIndices) {
  86315. const selectedFields = columnIndices.map(index => this.fields[index]).filter(Boolean);
  86316. return new Schema(selectedFields, this.metadata);
  86317. }
  86318. assign(schemaOrFields) {
  86319. let fields;
  86320. let metadata = this.metadata;
  86321. if (schemaOrFields instanceof Schema) {
  86322. const otherSchema = schemaOrFields;
  86323. fields = otherSchema.fields;
  86324. metadata = mergeMaps(mergeMaps(new Map(), this.metadata), otherSchema.metadata);
  86325. } else {
  86326. fields = schemaOrFields;
  86327. }
  86328. const fieldMap = Object.create(null);
  86329. for (const field of this.fields) {
  86330. fieldMap[field.name] = field;
  86331. }
  86332. for (const field of fields) {
  86333. fieldMap[field.name] = field;
  86334. }
  86335. const mergedFields = Object.values(fieldMap);
  86336. return new Schema(mergedFields, metadata);
  86337. }
  86338. }
  86339. function checkNames(fields) {
  86340. const usedNames = {};
  86341. for (const field of fields) {
  86342. if (usedNames[field.name]) {
  86343. console.warn('Schema: duplicated field name', field.name, field);
  86344. }
  86345. usedNames[field.name] = true;
  86346. }
  86347. }
  86348. function mergeMaps(m1, m2) {
  86349. return new Map([...(m1 || new Map()), ...(m2 || new Map())]);
  86350. }
  86351. class Field {
  86352. constructor(name, type, nullable = false, metadata = new Map()) {
  86353. _defineProperty(this, "name", void 0);
  86354. _defineProperty(this, "type", void 0);
  86355. _defineProperty(this, "nullable", void 0);
  86356. _defineProperty(this, "metadata", void 0);
  86357. this.name = name;
  86358. this.type = type;
  86359. this.nullable = nullable;
  86360. this.metadata = metadata;
  86361. }
  86362. get typeId() {
  86363. return this.type && this.type.typeId;
  86364. }
  86365. clone() {
  86366. return new Field(this.name, this.type, this.nullable, this.metadata);
  86367. }
  86368. compareTo(other) {
  86369. return this.name === other.name && this.type === other.type && this.nullable === other.nullable && this.metadata === other.metadata;
  86370. }
  86371. toString() {
  86372. return "".concat(this.type).concat(this.nullable ? ', nullable' : '').concat(this.metadata ? ", metadata: ".concat(this.metadata) : '');
  86373. }
  86374. }
  86375. let Type;
  86376. (function (Type) {
  86377. Type[Type["NONE"] = 0] = "NONE";
  86378. Type[Type["Null"] = 1] = "Null";
  86379. Type[Type["Int"] = 2] = "Int";
  86380. Type[Type["Float"] = 3] = "Float";
  86381. Type[Type["Binary"] = 4] = "Binary";
  86382. Type[Type["Utf8"] = 5] = "Utf8";
  86383. Type[Type["Bool"] = 6] = "Bool";
  86384. Type[Type["Decimal"] = 7] = "Decimal";
  86385. Type[Type["Date"] = 8] = "Date";
  86386. Type[Type["Time"] = 9] = "Time";
  86387. Type[Type["Timestamp"] = 10] = "Timestamp";
  86388. Type[Type["Interval"] = 11] = "Interval";
  86389. Type[Type["List"] = 12] = "List";
  86390. Type[Type["Struct"] = 13] = "Struct";
  86391. Type[Type["Union"] = 14] = "Union";
  86392. Type[Type["FixedSizeBinary"] = 15] = "FixedSizeBinary";
  86393. Type[Type["FixedSizeList"] = 16] = "FixedSizeList";
  86394. Type[Type["Map"] = 17] = "Map";
  86395. Type[Type["Dictionary"] = -1] = "Dictionary";
  86396. Type[Type["Int8"] = -2] = "Int8";
  86397. Type[Type["Int16"] = -3] = "Int16";
  86398. Type[Type["Int32"] = -4] = "Int32";
  86399. Type[Type["Int64"] = -5] = "Int64";
  86400. Type[Type["Uint8"] = -6] = "Uint8";
  86401. Type[Type["Uint16"] = -7] = "Uint16";
  86402. Type[Type["Uint32"] = -8] = "Uint32";
  86403. Type[Type["Uint64"] = -9] = "Uint64";
  86404. Type[Type["Float16"] = -10] = "Float16";
  86405. Type[Type["Float32"] = -11] = "Float32";
  86406. Type[Type["Float64"] = -12] = "Float64";
  86407. Type[Type["DateDay"] = -13] = "DateDay";
  86408. Type[Type["DateMillisecond"] = -14] = "DateMillisecond";
  86409. Type[Type["TimestampSecond"] = -15] = "TimestampSecond";
  86410. Type[Type["TimestampMillisecond"] = -16] = "TimestampMillisecond";
  86411. Type[Type["TimestampMicrosecond"] = -17] = "TimestampMicrosecond";
  86412. Type[Type["TimestampNanosecond"] = -18] = "TimestampNanosecond";
  86413. Type[Type["TimeSecond"] = -19] = "TimeSecond";
  86414. Type[Type["TimeMillisecond"] = -20] = "TimeMillisecond";
  86415. Type[Type["TimeMicrosecond"] = -21] = "TimeMicrosecond";
  86416. Type[Type["TimeNanosecond"] = -22] = "TimeNanosecond";
  86417. Type[Type["DenseUnion"] = -23] = "DenseUnion";
  86418. Type[Type["SparseUnion"] = -24] = "SparseUnion";
  86419. Type[Type["IntervalDayTime"] = -25] = "IntervalDayTime";
  86420. Type[Type["IntervalYearMonth"] = -26] = "IntervalYearMonth";
  86421. })(Type || (Type = {}));
  86422. let _Symbol$toStringTag, _Symbol$toStringTag2, _Symbol$toStringTag7;
  86423. class DataType {
  86424. static isNull(x) {
  86425. return x && x.typeId === Type.Null;
  86426. }
  86427. static isInt(x) {
  86428. return x && x.typeId === Type.Int;
  86429. }
  86430. static isFloat(x) {
  86431. return x && x.typeId === Type.Float;
  86432. }
  86433. static isBinary(x) {
  86434. return x && x.typeId === Type.Binary;
  86435. }
  86436. static isUtf8(x) {
  86437. return x && x.typeId === Type.Utf8;
  86438. }
  86439. static isBool(x) {
  86440. return x && x.typeId === Type.Bool;
  86441. }
  86442. static isDecimal(x) {
  86443. return x && x.typeId === Type.Decimal;
  86444. }
  86445. static isDate(x) {
  86446. return x && x.typeId === Type.Date;
  86447. }
  86448. static isTime(x) {
  86449. return x && x.typeId === Type.Time;
  86450. }
  86451. static isTimestamp(x) {
  86452. return x && x.typeId === Type.Timestamp;
  86453. }
  86454. static isInterval(x) {
  86455. return x && x.typeId === Type.Interval;
  86456. }
  86457. static isList(x) {
  86458. return x && x.typeId === Type.List;
  86459. }
  86460. static isStruct(x) {
  86461. return x && x.typeId === Type.Struct;
  86462. }
  86463. static isUnion(x) {
  86464. return x && x.typeId === Type.Union;
  86465. }
  86466. static isFixedSizeBinary(x) {
  86467. return x && x.typeId === Type.FixedSizeBinary;
  86468. }
  86469. static isFixedSizeList(x) {
  86470. return x && x.typeId === Type.FixedSizeList;
  86471. }
  86472. static isMap(x) {
  86473. return x && x.typeId === Type.Map;
  86474. }
  86475. static isDictionary(x) {
  86476. return x && x.typeId === Type.Dictionary;
  86477. }
  86478. get typeId() {
  86479. return Type.NONE;
  86480. }
  86481. compareTo(other) {
  86482. return this === other;
  86483. }
  86484. }
  86485. _Symbol$toStringTag = Symbol.toStringTag;
  86486. class Int extends DataType {
  86487. constructor(isSigned, bitWidth) {
  86488. super();
  86489. _defineProperty(this, "isSigned", void 0);
  86490. _defineProperty(this, "bitWidth", void 0);
  86491. this.isSigned = isSigned;
  86492. this.bitWidth = bitWidth;
  86493. }
  86494. get typeId() {
  86495. return Type.Int;
  86496. }
  86497. get [_Symbol$toStringTag]() {
  86498. return 'Int';
  86499. }
  86500. toString() {
  86501. return "".concat(this.isSigned ? 'I' : 'Ui', "nt").concat(this.bitWidth);
  86502. }
  86503. }
  86504. class Int8 extends Int {
  86505. constructor() {
  86506. super(true, 8);
  86507. }
  86508. }
  86509. class Int16 extends Int {
  86510. constructor() {
  86511. super(true, 16);
  86512. }
  86513. }
  86514. class Int32 extends Int {
  86515. constructor() {
  86516. super(true, 32);
  86517. }
  86518. }
  86519. class Uint8 extends Int {
  86520. constructor() {
  86521. super(false, 8);
  86522. }
  86523. }
  86524. class Uint16 extends Int {
  86525. constructor() {
  86526. super(false, 16);
  86527. }
  86528. }
  86529. class Uint32 extends Int {
  86530. constructor() {
  86531. super(false, 32);
  86532. }
  86533. }
  86534. const Precision = {
  86535. HALF: 16,
  86536. SINGLE: 32,
  86537. DOUBLE: 64
  86538. };
  86539. _Symbol$toStringTag2 = Symbol.toStringTag;
  86540. class Float extends DataType {
  86541. constructor(precision) {
  86542. super();
  86543. _defineProperty(this, "precision", void 0);
  86544. this.precision = precision;
  86545. }
  86546. get typeId() {
  86547. return Type.Float;
  86548. }
  86549. get [_Symbol$toStringTag2]() {
  86550. return 'Float';
  86551. }
  86552. toString() {
  86553. return "Float".concat(this.precision);
  86554. }
  86555. }
  86556. class Float32 extends Float {
  86557. constructor() {
  86558. super(Precision.SINGLE);
  86559. }
  86560. }
  86561. class Float64 extends Float {
  86562. constructor() {
  86563. super(Precision.DOUBLE);
  86564. }
  86565. }
  86566. _Symbol$toStringTag7 = Symbol.toStringTag;
  86567. class FixedSizeList extends DataType {
  86568. constructor(listSize, child) {
  86569. super();
  86570. _defineProperty(this, "listSize", void 0);
  86571. _defineProperty(this, "children", void 0);
  86572. this.listSize = listSize;
  86573. this.children = [child];
  86574. }
  86575. get typeId() {
  86576. return Type.FixedSizeList;
  86577. }
  86578. get valueType() {
  86579. return this.children[0].type;
  86580. }
  86581. get valueField() {
  86582. return this.children[0];
  86583. }
  86584. get [_Symbol$toStringTag7]() {
  86585. return 'FixedSizeList';
  86586. }
  86587. toString() {
  86588. return "FixedSizeList[".concat(this.listSize, "]<").concat(this.valueType, ">");
  86589. }
  86590. }
  86591. function getArrowTypeFromTypedArray(array) {
  86592. switch (array.constructor) {
  86593. case Int8Array:
  86594. return new Int8();
  86595. case Uint8Array:
  86596. return new Uint8();
  86597. case Int16Array:
  86598. return new Int16();
  86599. case Uint16Array:
  86600. return new Uint16();
  86601. case Int32Array:
  86602. return new Int32();
  86603. case Uint32Array:
  86604. return new Uint32();
  86605. case Float32Array:
  86606. return new Float32();
  86607. case Float64Array:
  86608. return new Float64();
  86609. default:
  86610. throw new Error('array type not supported');
  86611. }
  86612. }
  86613. function deduceMeshField(attributeName, attribute, optionalMetadata) {
  86614. const type = getArrowTypeFromTypedArray(attribute.value);
  86615. const metadata = optionalMetadata ? optionalMetadata : makeMeshAttributeMetadata(attribute);
  86616. const field = new Field(attributeName, new FixedSizeList(attribute.size, new Field('value', type)), false, metadata);
  86617. return field;
  86618. }
  86619. function makeMeshAttributeMetadata(attribute) {
  86620. const result = new Map();
  86621. if ('byteOffset' in attribute) {
  86622. result.set('byteOffset', attribute.byteOffset.toString(10));
  86623. }
  86624. if ('byteStride' in attribute) {
  86625. result.set('byteStride', attribute.byteStride.toString(10));
  86626. }
  86627. if ('normalized' in attribute) {
  86628. result.set('normalized', attribute.normalized.toString());
  86629. }
  86630. return result;
  86631. }
  86632. function getDracoSchema(attributes, loaderData, indices) {
  86633. const metadataMap = makeMetadata(loaderData.metadata);
  86634. const fields = [];
  86635. const namedLoaderDataAttributes = transformAttributesLoaderData(loaderData.attributes);
  86636. for (const attributeName in attributes) {
  86637. const attribute = attributes[attributeName];
  86638. const field = getArrowFieldFromAttribute(attributeName, attribute, namedLoaderDataAttributes[attributeName]);
  86639. fields.push(field);
  86640. }
  86641. if (indices) {
  86642. const indicesField = getArrowFieldFromAttribute('indices', indices);
  86643. fields.push(indicesField);
  86644. }
  86645. return new Schema(fields, metadataMap);
  86646. }
  86647. function transformAttributesLoaderData(loaderData) {
  86648. const result = {};
  86649. for (const key in loaderData) {
  86650. const dracoAttribute = loaderData[key];
  86651. result[dracoAttribute.name || 'undefined'] = dracoAttribute;
  86652. }
  86653. return result;
  86654. }
  86655. function getArrowFieldFromAttribute(attributeName, attribute, loaderData) {
  86656. const metadataMap = loaderData ? makeMetadata(loaderData.metadata) : undefined;
  86657. const field = deduceMeshField(attributeName, attribute, metadataMap);
  86658. return field;
  86659. }
  86660. function makeMetadata(metadata) {
  86661. const metadataMap = new Map();
  86662. for (const key in metadata) {
  86663. metadataMap.set("".concat(key, ".string"), JSON.stringify(metadata[key]));
  86664. }
  86665. return metadataMap;
  86666. }
  86667. const DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP = {
  86668. POSITION: 'POSITION',
  86669. NORMAL: 'NORMAL',
  86670. COLOR: 'COLOR_0',
  86671. TEX_COORD: 'TEXCOORD_0'
  86672. };
  86673. const DRACO_DATA_TYPE_TO_TYPED_ARRAY_MAP = {
  86674. 1: Int8Array,
  86675. 2: Uint8Array,
  86676. 3: Int16Array,
  86677. 4: Uint16Array,
  86678. 5: Int32Array,
  86679. 6: Uint32Array,
  86680. 9: Float32Array
  86681. };
  86682. const INDEX_ITEM_SIZE = 4;
  86683. class DracoParser {
  86684. constructor(draco) {
  86685. _defineProperty(this, "draco", void 0);
  86686. _defineProperty(this, "decoder", void 0);
  86687. _defineProperty(this, "metadataQuerier", void 0);
  86688. this.draco = draco;
  86689. this.decoder = new this.draco.Decoder();
  86690. this.metadataQuerier = new this.draco.MetadataQuerier();
  86691. }
  86692. destroy() {
  86693. this.draco.destroy(this.decoder);
  86694. this.draco.destroy(this.metadataQuerier);
  86695. }
  86696. parseSync(arrayBuffer, options = {}) {
  86697. const buffer = new this.draco.DecoderBuffer();
  86698. buffer.Init(new Int8Array(arrayBuffer), arrayBuffer.byteLength);
  86699. this._disableAttributeTransforms(options);
  86700. const geometry_type = this.decoder.GetEncodedGeometryType(buffer);
  86701. const dracoGeometry = geometry_type === this.draco.TRIANGULAR_MESH ? new this.draco.Mesh() : new this.draco.PointCloud();
  86702. try {
  86703. let dracoStatus;
  86704. switch (geometry_type) {
  86705. case this.draco.TRIANGULAR_MESH:
  86706. dracoStatus = this.decoder.DecodeBufferToMesh(buffer, dracoGeometry);
  86707. break;
  86708. case this.draco.POINT_CLOUD:
  86709. dracoStatus = this.decoder.DecodeBufferToPointCloud(buffer, dracoGeometry);
  86710. break;
  86711. default:
  86712. throw new Error('DRACO: Unknown geometry type.');
  86713. }
  86714. if (!dracoStatus.ok() || !dracoGeometry.ptr) {
  86715. const message = "DRACO decompression failed: ".concat(dracoStatus.error_msg());
  86716. throw new Error(message);
  86717. }
  86718. const loaderData = this._getDracoLoaderData(dracoGeometry, geometry_type, options);
  86719. const geometry = this._getMeshData(dracoGeometry, loaderData, options);
  86720. const boundingBox = getMeshBoundingBox(geometry.attributes);
  86721. const schema = getDracoSchema(geometry.attributes, loaderData, geometry.indices);
  86722. const data = {
  86723. loader: 'draco',
  86724. loaderData,
  86725. header: {
  86726. vertexCount: dracoGeometry.num_points(),
  86727. boundingBox
  86728. },
  86729. ...geometry,
  86730. schema
  86731. };
  86732. return data;
  86733. } finally {
  86734. this.draco.destroy(buffer);
  86735. if (dracoGeometry) {
  86736. this.draco.destroy(dracoGeometry);
  86737. }
  86738. }
  86739. }
  86740. _getDracoLoaderData(dracoGeometry, geometry_type, options) {
  86741. const metadata = this._getTopLevelMetadata(dracoGeometry);
  86742. const attributes = this._getDracoAttributes(dracoGeometry, options);
  86743. return {
  86744. geometry_type,
  86745. num_attributes: dracoGeometry.num_attributes(),
  86746. num_points: dracoGeometry.num_points(),
  86747. num_faces: dracoGeometry instanceof this.draco.Mesh ? dracoGeometry.num_faces() : 0,
  86748. metadata,
  86749. attributes
  86750. };
  86751. }
  86752. _getDracoAttributes(dracoGeometry, options) {
  86753. const dracoAttributes = {};
  86754. for (let attributeId = 0; attributeId < dracoGeometry.num_attributes(); attributeId++) {
  86755. const dracoAttribute = this.decoder.GetAttribute(dracoGeometry, attributeId);
  86756. const metadata = this._getAttributeMetadata(dracoGeometry, attributeId);
  86757. dracoAttributes[dracoAttribute.unique_id()] = {
  86758. unique_id: dracoAttribute.unique_id(),
  86759. attribute_type: dracoAttribute.attribute_type(),
  86760. data_type: dracoAttribute.data_type(),
  86761. num_components: dracoAttribute.num_components(),
  86762. byte_offset: dracoAttribute.byte_offset(),
  86763. byte_stride: dracoAttribute.byte_stride(),
  86764. normalized: dracoAttribute.normalized(),
  86765. attribute_index: attributeId,
  86766. metadata
  86767. };
  86768. const quantization = this._getQuantizationTransform(dracoAttribute, options);
  86769. if (quantization) {
  86770. dracoAttributes[dracoAttribute.unique_id()].quantization_transform = quantization;
  86771. }
  86772. const octahedron = this._getOctahedronTransform(dracoAttribute, options);
  86773. if (octahedron) {
  86774. dracoAttributes[dracoAttribute.unique_id()].octahedron_transform = octahedron;
  86775. }
  86776. }
  86777. return dracoAttributes;
  86778. }
  86779. _getMeshData(dracoGeometry, loaderData, options) {
  86780. const attributes = this._getMeshAttributes(loaderData, dracoGeometry, options);
  86781. const positionAttribute = attributes.POSITION;
  86782. if (!positionAttribute) {
  86783. throw new Error('DRACO: No position attribute found.');
  86784. }
  86785. if (dracoGeometry instanceof this.draco.Mesh) {
  86786. switch (options.topology) {
  86787. case 'triangle-strip':
  86788. return {
  86789. topology: 'triangle-strip',
  86790. mode: 4,
  86791. attributes,
  86792. indices: {
  86793. value: this._getTriangleStripIndices(dracoGeometry),
  86794. size: 1
  86795. }
  86796. };
  86797. case 'triangle-list':
  86798. default:
  86799. return {
  86800. topology: 'triangle-list',
  86801. mode: 5,
  86802. attributes,
  86803. indices: {
  86804. value: this._getTriangleListIndices(dracoGeometry),
  86805. size: 1
  86806. }
  86807. };
  86808. }
  86809. }
  86810. return {
  86811. topology: 'point-list',
  86812. mode: 0,
  86813. attributes
  86814. };
  86815. }
  86816. _getMeshAttributes(loaderData, dracoGeometry, options) {
  86817. const attributes = {};
  86818. for (const loaderAttribute of Object.values(loaderData.attributes)) {
  86819. const attributeName = this._deduceAttributeName(loaderAttribute, options);
  86820. loaderAttribute.name = attributeName;
  86821. const {
  86822. value,
  86823. size
  86824. } = this._getAttributeValues(dracoGeometry, loaderAttribute);
  86825. attributes[attributeName] = {
  86826. value,
  86827. size,
  86828. byteOffset: loaderAttribute.byte_offset,
  86829. byteStride: loaderAttribute.byte_stride,
  86830. normalized: loaderAttribute.normalized
  86831. };
  86832. }
  86833. return attributes;
  86834. }
  86835. _getTriangleListIndices(dracoGeometry) {
  86836. const numFaces = dracoGeometry.num_faces();
  86837. const numIndices = numFaces * 3;
  86838. const byteLength = numIndices * INDEX_ITEM_SIZE;
  86839. const ptr = this.draco._malloc(byteLength);
  86840. try {
  86841. this.decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr);
  86842. return new Uint32Array(this.draco.HEAPF32.buffer, ptr, numIndices).slice();
  86843. } finally {
  86844. this.draco._free(ptr);
  86845. }
  86846. }
  86847. _getTriangleStripIndices(dracoGeometry) {
  86848. const dracoArray = new this.draco.DracoInt32Array();
  86849. try {
  86850. this.decoder.GetTriangleStripsFromMesh(dracoGeometry, dracoArray);
  86851. return getUint32Array(dracoArray);
  86852. } finally {
  86853. this.draco.destroy(dracoArray);
  86854. }
  86855. }
  86856. _getAttributeValues(dracoGeometry, attribute) {
  86857. const TypedArrayCtor = DRACO_DATA_TYPE_TO_TYPED_ARRAY_MAP[attribute.data_type];
  86858. const numComponents = attribute.num_components;
  86859. const numPoints = dracoGeometry.num_points();
  86860. const numValues = numPoints * numComponents;
  86861. const byteLength = numValues * TypedArrayCtor.BYTES_PER_ELEMENT;
  86862. const dataType = getDracoDataType(this.draco, TypedArrayCtor);
  86863. let value;
  86864. const ptr = this.draco._malloc(byteLength);
  86865. try {
  86866. const dracoAttribute = this.decoder.GetAttribute(dracoGeometry, attribute.attribute_index);
  86867. this.decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, dracoAttribute, dataType, byteLength, ptr);
  86868. value = new TypedArrayCtor(this.draco.HEAPF32.buffer, ptr, numValues).slice();
  86869. } finally {
  86870. this.draco._free(ptr);
  86871. }
  86872. return {
  86873. value,
  86874. size: numComponents
  86875. };
  86876. }
  86877. _deduceAttributeName(attribute, options) {
  86878. const uniqueId = attribute.unique_id;
  86879. for (const [attributeName, attributeUniqueId] of Object.entries(options.extraAttributes || {})) {
  86880. if (attributeUniqueId === uniqueId) {
  86881. return attributeName;
  86882. }
  86883. }
  86884. const thisAttributeType = attribute.attribute_type;
  86885. for (const dracoAttributeConstant in DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP) {
  86886. const attributeType = this.draco[dracoAttributeConstant];
  86887. if (attributeType === thisAttributeType) {
  86888. return DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP[dracoAttributeConstant];
  86889. }
  86890. }
  86891. const entryName = options.attributeNameEntry || 'name';
  86892. if (attribute.metadata[entryName]) {
  86893. return attribute.metadata[entryName].string;
  86894. }
  86895. return "CUSTOM_ATTRIBUTE_".concat(uniqueId);
  86896. }
  86897. _getTopLevelMetadata(dracoGeometry) {
  86898. const dracoMetadata = this.decoder.GetMetadata(dracoGeometry);
  86899. return this._getDracoMetadata(dracoMetadata);
  86900. }
  86901. _getAttributeMetadata(dracoGeometry, attributeId) {
  86902. const dracoMetadata = this.decoder.GetAttributeMetadata(dracoGeometry, attributeId);
  86903. return this._getDracoMetadata(dracoMetadata);
  86904. }
  86905. _getDracoMetadata(dracoMetadata) {
  86906. if (!dracoMetadata || !dracoMetadata.ptr) {
  86907. return {};
  86908. }
  86909. const result = {};
  86910. const numEntries = this.metadataQuerier.NumEntries(dracoMetadata);
  86911. for (let entryIndex = 0; entryIndex < numEntries; entryIndex++) {
  86912. const entryName = this.metadataQuerier.GetEntryName(dracoMetadata, entryIndex);
  86913. result[entryName] = this._getDracoMetadataField(dracoMetadata, entryName);
  86914. }
  86915. return result;
  86916. }
  86917. _getDracoMetadataField(dracoMetadata, entryName) {
  86918. const dracoArray = new this.draco.DracoInt32Array();
  86919. try {
  86920. this.metadataQuerier.GetIntEntryArray(dracoMetadata, entryName, dracoArray);
  86921. const intArray = getInt32Array(dracoArray);
  86922. return {
  86923. int: this.metadataQuerier.GetIntEntry(dracoMetadata, entryName),
  86924. string: this.metadataQuerier.GetStringEntry(dracoMetadata, entryName),
  86925. double: this.metadataQuerier.GetDoubleEntry(dracoMetadata, entryName),
  86926. intArray
  86927. };
  86928. } finally {
  86929. this.draco.destroy(dracoArray);
  86930. }
  86931. }
  86932. _disableAttributeTransforms(options) {
  86933. const {
  86934. quantizedAttributes = [],
  86935. octahedronAttributes = []
  86936. } = options;
  86937. const skipAttributes = [...quantizedAttributes, ...octahedronAttributes];
  86938. for (const dracoAttributeName of skipAttributes) {
  86939. this.decoder.SkipAttributeTransform(this.draco[dracoAttributeName]);
  86940. }
  86941. }
  86942. _getQuantizationTransform(dracoAttribute, options) {
  86943. const {
  86944. quantizedAttributes = []
  86945. } = options;
  86946. const attribute_type = dracoAttribute.attribute_type();
  86947. const skip = quantizedAttributes.map(type => this.decoder[type]).includes(attribute_type);
  86948. if (skip) {
  86949. const transform = new this.draco.AttributeQuantizationTransform();
  86950. try {
  86951. if (transform.InitFromAttribute(dracoAttribute)) {
  86952. return {
  86953. quantization_bits: transform.quantization_bits(),
  86954. range: transform.range(),
  86955. min_values: new Float32Array([1, 2, 3]).map(i => transform.min_value(i))
  86956. };
  86957. }
  86958. } finally {
  86959. this.draco.destroy(transform);
  86960. }
  86961. }
  86962. return null;
  86963. }
  86964. _getOctahedronTransform(dracoAttribute, options) {
  86965. const {
  86966. octahedronAttributes = []
  86967. } = options;
  86968. const attribute_type = dracoAttribute.attribute_type();
  86969. const octahedron = octahedronAttributes.map(type => this.decoder[type]).includes(attribute_type);
  86970. if (octahedron) {
  86971. const transform = new this.draco.AttributeQuantizationTransform();
  86972. try {
  86973. if (transform.InitFromAttribute(dracoAttribute)) {
  86974. return {
  86975. quantization_bits: transform.quantization_bits()
  86976. };
  86977. }
  86978. } finally {
  86979. this.draco.destroy(transform);
  86980. }
  86981. }
  86982. return null;
  86983. }
  86984. }
  86985. function getDracoDataType(draco, attributeType) {
  86986. switch (attributeType) {
  86987. case Float32Array:
  86988. return draco.DT_FLOAT32;
  86989. case Int8Array:
  86990. return draco.DT_INT8;
  86991. case Int16Array:
  86992. return draco.DT_INT16;
  86993. case Int32Array:
  86994. return draco.DT_INT32;
  86995. case Uint8Array:
  86996. return draco.DT_UINT8;
  86997. case Uint16Array:
  86998. return draco.DT_UINT16;
  86999. case Uint32Array:
  87000. return draco.DT_UINT32;
  87001. default:
  87002. return draco.DT_INVALID;
  87003. }
  87004. }
  87005. function getInt32Array(dracoArray) {
  87006. const numValues = dracoArray.size();
  87007. const intArray = new Int32Array(numValues);
  87008. for (let i = 0; i < numValues; i++) {
  87009. intArray[i] = dracoArray.GetValue(i);
  87010. }
  87011. return intArray;
  87012. }
  87013. function getUint32Array(dracoArray) {
  87014. const numValues = dracoArray.size();
  87015. const intArray = new Int32Array(numValues);
  87016. for (let i = 0; i < numValues; i++) {
  87017. intArray[i] = dracoArray.GetValue(i);
  87018. }
  87019. return intArray;
  87020. }
  87021. const DRACO_VERSION = '1.4.1';
  87022. const DRACO_JS_DECODER_URL = "https://www.gstatic.com/draco/versioned/decoders/".concat(DRACO_VERSION, "/draco_decoder.js");
  87023. const DRACO_WASM_WRAPPER_URL = "https://www.gstatic.com/draco/versioned/decoders/".concat(DRACO_VERSION, "/draco_wasm_wrapper.js");
  87024. const DRACO_WASM_DECODER_URL = "https://www.gstatic.com/draco/versioned/decoders/".concat(DRACO_VERSION, "/draco_decoder.wasm");
  87025. let loadDecoderPromise;
  87026. async function loadDracoDecoderModule(options) {
  87027. const modules = options.modules || {};
  87028. if (modules.draco3d) {
  87029. loadDecoderPromise = loadDecoderPromise || modules.draco3d.createDecoderModule({}).then(draco => {
  87030. return {
  87031. draco
  87032. };
  87033. });
  87034. } else {
  87035. loadDecoderPromise = loadDecoderPromise || loadDracoDecoder(options);
  87036. }
  87037. return await loadDecoderPromise;
  87038. }
  87039. async function loadDracoDecoder(options) {
  87040. let DracoDecoderModule;
  87041. let wasmBinary;
  87042. switch (options.draco && options.draco.decoderType) {
  87043. case 'js':
  87044. DracoDecoderModule = await loadLibrary(DRACO_JS_DECODER_URL, 'draco', options);
  87045. break;
  87046. case 'wasm':
  87047. default:
  87048. [DracoDecoderModule, wasmBinary] = await Promise.all([await loadLibrary(DRACO_WASM_WRAPPER_URL, 'draco', options), await loadLibrary(DRACO_WASM_DECODER_URL, 'draco', options)]);
  87049. }
  87050. DracoDecoderModule = DracoDecoderModule || globalThis.DracoDecoderModule;
  87051. return await initializeDracoDecoder(DracoDecoderModule, wasmBinary);
  87052. }
  87053. function initializeDracoDecoder(DracoDecoderModule, wasmBinary) {
  87054. const options = {};
  87055. if (wasmBinary) {
  87056. options.wasmBinary = wasmBinary;
  87057. }
  87058. return new Promise(resolve => {
  87059. DracoDecoderModule({ ...options,
  87060. onModuleLoaded: draco => resolve({
  87061. draco
  87062. })
  87063. });
  87064. });
  87065. }
  87066. const DracoLoader = { ...DracoLoader$1,
  87067. parse: parse$2
  87068. };
  87069. async function parse$2(arrayBuffer, options) {
  87070. const {
  87071. draco
  87072. } = await loadDracoDecoderModule(options);
  87073. const dracoParser = new DracoParser(draco);
  87074. try {
  87075. return dracoParser.parseSync(arrayBuffer, options === null || options === void 0 ? void 0 : options.draco);
  87076. } finally {
  87077. dracoParser.destroy();
  87078. }
  87079. }
  87080. const GL_PRIMITIVE_MODE = {
  87081. POINTS: 0x0000,
  87082. LINES: 0x0001,
  87083. LINE_LOOP: 0x0002,
  87084. LINE_STRIP: 0x0003,
  87085. TRIANGLES: 0x0004,
  87086. TRIANGLE_STRIP: 0x0005,
  87087. TRIANGLE_FAN: 0x0006
  87088. };
  87089. const GL_TYPE = {
  87090. BYTE: 5120,
  87091. UNSIGNED_BYTE: 5121,
  87092. SHORT: 5122,
  87093. UNSIGNED_SHORT: 5123,
  87094. INT: 5124,
  87095. UNSIGNED_INT: 5125,
  87096. FLOAT: 5126,
  87097. DOUBLE: 5130
  87098. };
  87099. const GL$1 = { ...GL_PRIMITIVE_MODE,
  87100. ...GL_TYPE
  87101. };
  87102. const GL_TYPE_TO_ARRAY_TYPE = {
  87103. [GL_TYPE.DOUBLE]: Float64Array,
  87104. [GL_TYPE.FLOAT]: Float32Array,
  87105. [GL_TYPE.UNSIGNED_SHORT]: Uint16Array,
  87106. [GL_TYPE.UNSIGNED_INT]: Uint32Array,
  87107. [GL_TYPE.UNSIGNED_BYTE]: Uint8Array,
  87108. [GL_TYPE.BYTE]: Int8Array,
  87109. [GL_TYPE.SHORT]: Int16Array,
  87110. [GL_TYPE.INT]: Int32Array
  87111. };
  87112. const NAME_TO_GL_TYPE = {
  87113. DOUBLE: GL_TYPE.DOUBLE,
  87114. FLOAT: GL_TYPE.FLOAT,
  87115. UNSIGNED_SHORT: GL_TYPE.UNSIGNED_SHORT,
  87116. UNSIGNED_INT: GL_TYPE.UNSIGNED_INT,
  87117. UNSIGNED_BYTE: GL_TYPE.UNSIGNED_BYTE,
  87118. BYTE: GL_TYPE.BYTE,
  87119. SHORT: GL_TYPE.SHORT,
  87120. INT: GL_TYPE.INT
  87121. };
  87122. const ERR_TYPE_CONVERSION = 'Failed to convert GL type';
  87123. class GLType {
  87124. static fromTypedArray(arrayOrType) {
  87125. arrayOrType = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
  87126. for (const glType in GL_TYPE_TO_ARRAY_TYPE) {
  87127. const ArrayType = GL_TYPE_TO_ARRAY_TYPE[glType];
  87128. if (ArrayType === arrayOrType) {
  87129. return glType;
  87130. }
  87131. }
  87132. throw new Error(ERR_TYPE_CONVERSION);
  87133. }
  87134. static fromName(name) {
  87135. const glType = NAME_TO_GL_TYPE[name];
  87136. if (!glType) {
  87137. throw new Error(ERR_TYPE_CONVERSION);
  87138. }
  87139. return glType;
  87140. }
  87141. static getArrayType(glType) {
  87142. switch (glType) {
  87143. case GL_TYPE.UNSIGNED_SHORT_5_6_5:
  87144. case GL_TYPE.UNSIGNED_SHORT_4_4_4_4:
  87145. case GL_TYPE.UNSIGNED_SHORT_5_5_5_1:
  87146. return Uint16Array;
  87147. default:
  87148. const ArrayType = GL_TYPE_TO_ARRAY_TYPE[glType];
  87149. if (!ArrayType) {
  87150. throw new Error(ERR_TYPE_CONVERSION);
  87151. }
  87152. return ArrayType;
  87153. }
  87154. }
  87155. static getByteSize(glType) {
  87156. const ArrayType = GLType.getArrayType(glType);
  87157. return ArrayType.BYTES_PER_ELEMENT;
  87158. }
  87159. static validate(glType) {
  87160. return Boolean(GLType.getArrayType(glType));
  87161. }
  87162. static createTypedArray(glType, buffer, byteOffset = 0, length) {
  87163. if (length === undefined) {
  87164. length = (buffer.byteLength - byteOffset) / GLType.getByteSize(glType);
  87165. }
  87166. const ArrayType = GLType.getArrayType(glType);
  87167. return new ArrayType(buffer, byteOffset, length);
  87168. }
  87169. }
  87170. function assert$2(condition, message) {
  87171. if (!condition) {
  87172. throw new Error("math.gl assertion failed. ".concat(message));
  87173. }
  87174. }
  87175. function decodeRGB565(rgb565, target = [0, 0, 0]) {
  87176. const r5 = rgb565 >> 11 & 31;
  87177. const g6 = rgb565 >> 5 & 63;
  87178. const b5 = rgb565 & 31;
  87179. target[0] = r5 << 3;
  87180. target[1] = g6 << 2;
  87181. target[2] = b5 << 3;
  87182. return target;
  87183. }
  87184. new Vector2$1();
  87185. new Vector3$1();
  87186. new Vector2$1();
  87187. new Vector2$1();
  87188. function fromSNorm(value, rangeMaximum = 255) {
  87189. return clamp(value, 0.0, rangeMaximum) / rangeMaximum * 2.0 - 1.0;
  87190. }
  87191. function signNotZero(value) {
  87192. return value < 0.0 ? -1.0 : 1.0;
  87193. }
  87194. function octDecodeInRange(x, y, rangeMax, result) {
  87195. assert$2(result);
  87196. if (x < 0 || x > rangeMax || y < 0 || y > rangeMax) {
  87197. throw new Error("x and y must be unsigned normalized integers between 0 and ".concat(rangeMax));
  87198. }
  87199. result.x = fromSNorm(x, rangeMax);
  87200. result.y = fromSNorm(y, rangeMax);
  87201. result.z = 1.0 - (Math.abs(result.x) + Math.abs(result.y));
  87202. if (result.z < 0.0) {
  87203. const oldVX = result.x;
  87204. result.x = (1.0 - Math.abs(result.y)) * signNotZero(oldVX);
  87205. result.y = (1.0 - Math.abs(oldVX)) * signNotZero(result.y);
  87206. }
  87207. return result.normalize();
  87208. }
  87209. function octDecode(x, y, result) {
  87210. return octDecodeInRange(x, y, 255, result);
  87211. }
  87212. class Tile3DFeatureTable {
  87213. constructor(featureTableJson, featureTableBinary) {
  87214. _defineProperty(this, "json", void 0);
  87215. _defineProperty(this, "buffer", void 0);
  87216. _defineProperty(this, "featuresLength", 0);
  87217. _defineProperty(this, "_cachedTypedArrays", {});
  87218. this.json = featureTableJson;
  87219. this.buffer = featureTableBinary;
  87220. }
  87221. getExtension(extensionName) {
  87222. return this.json.extensions && this.json.extensions[extensionName];
  87223. }
  87224. hasProperty(propertyName) {
  87225. return Boolean(this.json[propertyName]);
  87226. }
  87227. getGlobalProperty(propertyName, componentType = GL$1.UNSIGNED_INT, componentLength = 1) {
  87228. const jsonValue = this.json[propertyName];
  87229. if (jsonValue && Number.isFinite(jsonValue.byteOffset)) {
  87230. return this._getTypedArrayFromBinary(propertyName, componentType, componentLength, 1, jsonValue.byteOffset);
  87231. }
  87232. return jsonValue;
  87233. }
  87234. getPropertyArray(propertyName, componentType, componentLength) {
  87235. const jsonValue = this.json[propertyName];
  87236. if (jsonValue && Number.isFinite(jsonValue.byteOffset)) {
  87237. if ('componentType' in jsonValue) {
  87238. componentType = GLType.fromName(jsonValue.componentType);
  87239. }
  87240. return this._getTypedArrayFromBinary(propertyName, componentType, componentLength, this.featuresLength, jsonValue.byteOffset);
  87241. }
  87242. return this._getTypedArrayFromArray(propertyName, componentType, jsonValue);
  87243. }
  87244. getProperty(propertyName, componentType, componentLength, featureId, result) {
  87245. const jsonValue = this.json[propertyName];
  87246. if (!jsonValue) {
  87247. return jsonValue;
  87248. }
  87249. const typedArray = this.getPropertyArray(propertyName, componentType, componentLength);
  87250. if (componentLength === 1) {
  87251. return typedArray[featureId];
  87252. }
  87253. for (let i = 0; i < componentLength; ++i) {
  87254. result[i] = typedArray[componentLength * featureId + i];
  87255. }
  87256. return result;
  87257. }
  87258. _getTypedArrayFromBinary(propertyName, componentType, componentLength, count, byteOffset) {
  87259. const cachedTypedArrays = this._cachedTypedArrays;
  87260. let typedArray = cachedTypedArrays[propertyName];
  87261. if (!typedArray) {
  87262. typedArray = GLType.createTypedArray(componentType, this.buffer.buffer, this.buffer.byteOffset + byteOffset, count * componentLength);
  87263. cachedTypedArrays[propertyName] = typedArray;
  87264. }
  87265. return typedArray;
  87266. }
  87267. _getTypedArrayFromArray(propertyName, componentType, array) {
  87268. const cachedTypedArrays = this._cachedTypedArrays;
  87269. let typedArray = cachedTypedArrays[propertyName];
  87270. if (!typedArray) {
  87271. typedArray = GLType.createTypedArray(componentType, array);
  87272. cachedTypedArrays[propertyName] = typedArray;
  87273. }
  87274. return typedArray;
  87275. }
  87276. }
  87277. const COMPONENTS_PER_ATTRIBUTE = {
  87278. SCALAR: 1,
  87279. VEC2: 2,
  87280. VEC3: 3,
  87281. VEC4: 4,
  87282. MAT2: 4,
  87283. MAT3: 9,
  87284. MAT4: 16
  87285. };
  87286. const UNPACKER = {
  87287. SCALAR: (values, i) => values[i],
  87288. VEC2: (values, i) => [values[2 * i + 0], values[2 * i + 1]],
  87289. VEC3: (values, i) => [values[3 * i + 0], values[3 * i + 1], values[3 * i + 2]],
  87290. VEC4: (values, i) => [values[4 * i + 0], values[4 * i + 1], values[4 * i + 2], values[4 * i + 3]],
  87291. MAT2: (values, i) => [values[4 * i + 0], values[4 * i + 1], values[4 * i + 2], values[4 * i + 3]],
  87292. MAT3: (values, i) => [values[9 * i + 0], values[9 * i + 1], values[9 * i + 2], values[9 * i + 3], values[9 * i + 4], values[9 * i + 5], values[9 * i + 6], values[9 * i + 7], values[9 * i + 8]],
  87293. MAT4: (values, i) => [values[16 * i + 0], values[16 * i + 1], values[16 * i + 2], values[16 * i + 3], values[16 * i + 4], values[16 * i + 5], values[16 * i + 6], values[16 * i + 7], values[16 * i + 8], values[16 * i + 9], values[16 * i + 10], values[16 * i + 11], values[16 * i + 12], values[16 * i + 13], values[16 * i + 14], values[16 * i + 15]]
  87294. };
  87295. const PACKER = {
  87296. SCALAR: (x, values, i) => {
  87297. values[i] = x;
  87298. },
  87299. VEC2: (x, values, i) => {
  87300. values[2 * i + 0] = x[0];
  87301. values[2 * i + 1] = x[1];
  87302. },
  87303. VEC3: (x, values, i) => {
  87304. values[3 * i + 0] = x[0];
  87305. values[3 * i + 1] = x[1];
  87306. values[3 * i + 2] = x[2];
  87307. },
  87308. VEC4: (x, values, i) => {
  87309. values[4 * i + 0] = x[0];
  87310. values[4 * i + 1] = x[1];
  87311. values[4 * i + 2] = x[2];
  87312. values[4 * i + 3] = x[3];
  87313. },
  87314. MAT2: (x, values, i) => {
  87315. values[4 * i + 0] = x[0];
  87316. values[4 * i + 1] = x[1];
  87317. values[4 * i + 2] = x[2];
  87318. values[4 * i + 3] = x[3];
  87319. },
  87320. MAT3: (x, values, i) => {
  87321. values[9 * i + 0] = x[0];
  87322. values[9 * i + 1] = x[1];
  87323. values[9 * i + 2] = x[2];
  87324. values[9 * i + 3] = x[3];
  87325. values[9 * i + 4] = x[4];
  87326. values[9 * i + 5] = x[5];
  87327. values[9 * i + 6] = x[6];
  87328. values[9 * i + 7] = x[7];
  87329. values[9 * i + 8] = x[8];
  87330. values[9 * i + 9] = x[9];
  87331. },
  87332. MAT4: (x, values, i) => {
  87333. values[16 * i + 0] = x[0];
  87334. values[16 * i + 1] = x[1];
  87335. values[16 * i + 2] = x[2];
  87336. values[16 * i + 3] = x[3];
  87337. values[16 * i + 4] = x[4];
  87338. values[16 * i + 5] = x[5];
  87339. values[16 * i + 6] = x[6];
  87340. values[16 * i + 7] = x[7];
  87341. values[16 * i + 8] = x[8];
  87342. values[16 * i + 9] = x[9];
  87343. values[16 * i + 10] = x[10];
  87344. values[16 * i + 11] = x[11];
  87345. values[16 * i + 12] = x[12];
  87346. values[16 * i + 13] = x[13];
  87347. values[16 * i + 14] = x[14];
  87348. values[16 * i + 15] = x[15];
  87349. }
  87350. };
  87351. function createTypedArrayFromAccessor(tile3DAccessor, buffer, byteOffset, length) {
  87352. const {
  87353. componentType
  87354. } = tile3DAccessor;
  87355. assert$7(tile3DAccessor.componentType);
  87356. const type = typeof componentType === 'string' ? GLType.fromName(componentType) : componentType;
  87357. const size = COMPONENTS_PER_ATTRIBUTE[tile3DAccessor.type];
  87358. const unpacker = UNPACKER[tile3DAccessor.type];
  87359. const packer = PACKER[tile3DAccessor.type];
  87360. byteOffset += tile3DAccessor.byteOffset;
  87361. const values = GLType.createTypedArray(type, buffer, byteOffset, size * length);
  87362. return {
  87363. values,
  87364. type,
  87365. size,
  87366. unpacker,
  87367. packer
  87368. };
  87369. }
  87370. const defined$1 = x => x !== undefined;
  87371. function initializeHierarchy(batchTable, jsonHeader, binaryBody) {
  87372. if (!jsonHeader) {
  87373. return null;
  87374. }
  87375. let hierarchy = batchTable.getExtension('3DTILES_batch_table_hierarchy');
  87376. const legacyHierarchy = jsonHeader.HIERARCHY;
  87377. if (legacyHierarchy) {
  87378. console.warn('3D Tile Parser: HIERARCHY is deprecated. Use 3DTILES_batch_table_hierarchy.');
  87379. jsonHeader.extensions = jsonHeader.extensions || {};
  87380. jsonHeader.extensions['3DTILES_batch_table_hierarchy'] = legacyHierarchy;
  87381. hierarchy = legacyHierarchy;
  87382. }
  87383. if (!hierarchy) {
  87384. return null;
  87385. }
  87386. return initializeHierarchyValues(hierarchy, binaryBody);
  87387. }
  87388. function initializeHierarchyValues(hierarchyJson, binaryBody) {
  87389. let i;
  87390. let classId;
  87391. let binaryAccessor;
  87392. const instancesLength = hierarchyJson.instancesLength;
  87393. const classes = hierarchyJson.classes;
  87394. let classIds = hierarchyJson.classIds;
  87395. let parentCounts = hierarchyJson.parentCounts;
  87396. let parentIds = hierarchyJson.parentIds;
  87397. let parentIdsLength = instancesLength;
  87398. if (defined$1(classIds.byteOffset)) {
  87399. classIds.componentType = defaultValue(classIds.componentType, GL.UNSIGNED_SHORT);
  87400. classIds.type = AttributeType.SCALAR;
  87401. binaryAccessor = getBinaryAccessor(classIds);
  87402. classIds = binaryAccessor.createArrayBufferView(binaryBody.buffer, binaryBody.byteOffset + classIds.byteOffset, instancesLength);
  87403. }
  87404. let parentIndexes;
  87405. if (defined$1(parentCounts)) {
  87406. if (defined$1(parentCounts.byteOffset)) {
  87407. parentCounts.componentType = defaultValue(parentCounts.componentType, GL.UNSIGNED_SHORT);
  87408. parentCounts.type = AttributeType.SCALAR;
  87409. binaryAccessor = getBinaryAccessor(parentCounts);
  87410. parentCounts = binaryAccessor.createArrayBufferView(binaryBody.buffer, binaryBody.byteOffset + parentCounts.byteOffset, instancesLength);
  87411. }
  87412. parentIndexes = new Uint16Array(instancesLength);
  87413. parentIdsLength = 0;
  87414. for (i = 0; i < instancesLength; ++i) {
  87415. parentIndexes[i] = parentIdsLength;
  87416. parentIdsLength += parentCounts[i];
  87417. }
  87418. }
  87419. if (defined$1(parentIds) && defined$1(parentIds.byteOffset)) {
  87420. parentIds.componentType = defaultValue(parentIds.componentType, GL.UNSIGNED_SHORT);
  87421. parentIds.type = AttributeType.SCALAR;
  87422. binaryAccessor = getBinaryAccessor(parentIds);
  87423. parentIds = binaryAccessor.createArrayBufferView(binaryBody.buffer, binaryBody.byteOffset + parentIds.byteOffset, parentIdsLength);
  87424. }
  87425. const classesLength = classes.length;
  87426. for (i = 0; i < classesLength; ++i) {
  87427. const classInstancesLength = classes[i].length;
  87428. const properties = classes[i].instances;
  87429. const binaryProperties = getBinaryProperties(classInstancesLength, properties, binaryBody);
  87430. classes[i].instances = combine(binaryProperties, properties);
  87431. }
  87432. const classCounts = new Array(classesLength).fill(0);
  87433. const classIndexes = new Uint16Array(instancesLength);
  87434. for (i = 0; i < instancesLength; ++i) {
  87435. classId = classIds[i];
  87436. classIndexes[i] = classCounts[classId];
  87437. ++classCounts[classId];
  87438. }
  87439. const hierarchy = {
  87440. classes,
  87441. classIds,
  87442. classIndexes,
  87443. parentCounts,
  87444. parentIndexes,
  87445. parentIds
  87446. };
  87447. validateHierarchy(hierarchy);
  87448. return hierarchy;
  87449. }
  87450. function traverseHierarchy(hierarchy, instanceIndex, endConditionCallback) {
  87451. if (!hierarchy) {
  87452. return;
  87453. }
  87454. const parentCounts = hierarchy.parentCounts;
  87455. const parentIds = hierarchy.parentIds;
  87456. if (parentIds) {
  87457. return endConditionCallback(hierarchy, instanceIndex);
  87458. }
  87459. if (parentCounts > 0) {
  87460. return traverseHierarchyMultipleParents(hierarchy, instanceIndex, endConditionCallback);
  87461. }
  87462. return traverseHierarchySingleParent(hierarchy, instanceIndex, endConditionCallback);
  87463. }
  87464. function traverseHierarchyMultipleParents(hierarchy, instanceIndex, endConditionCallback) {
  87465. const classIds = hierarchy.classIds;
  87466. const parentCounts = hierarchy.parentCounts;
  87467. const parentIds = hierarchy.parentIds;
  87468. const parentIndexes = hierarchy.parentIndexes;
  87469. const instancesLength = classIds.length;
  87470. const visited = scratchVisited;
  87471. visited.length = Math.max(visited.length, instancesLength);
  87472. const visitedMarker = ++marker;
  87473. const stack = scratchStack;
  87474. stack.length = 0;
  87475. stack.push(instanceIndex);
  87476. while (stack.length > 0) {
  87477. instanceIndex = stack.pop();
  87478. if (visited[instanceIndex] === visitedMarker) {
  87479. continue;
  87480. }
  87481. visited[instanceIndex] = visitedMarker;
  87482. const result = endConditionCallback(hierarchy, instanceIndex);
  87483. if (defined$1(result)) {
  87484. return result;
  87485. }
  87486. const parentCount = parentCounts[instanceIndex];
  87487. const parentIndex = parentIndexes[instanceIndex];
  87488. for (let i = 0; i < parentCount; ++i) {
  87489. const parentId = parentIds[parentIndex + i];
  87490. if (parentId !== instanceIndex) {
  87491. stack.push(parentId);
  87492. }
  87493. }
  87494. }
  87495. return null;
  87496. }
  87497. function traverseHierarchySingleParent(hierarchy, instanceIndex, endConditionCallback) {
  87498. let hasParent = true;
  87499. while (hasParent) {
  87500. const result = endConditionCallback(hierarchy, instanceIndex);
  87501. if (defined$1(result)) {
  87502. return result;
  87503. }
  87504. const parentId = hierarchy.parentIds[instanceIndex];
  87505. hasParent = parentId !== instanceIndex;
  87506. instanceIndex = parentId;
  87507. }
  87508. throw new Error('traverseHierarchySingleParent');
  87509. }
  87510. function validateHierarchy(hierarchy) {
  87511. const classIds = hierarchy.classIds;
  87512. const instancesLength = classIds.length;
  87513. for (let i = 0; i < instancesLength; ++i) {
  87514. validateInstance(hierarchy, i, stack);
  87515. }
  87516. }
  87517. function validateInstance(hierarchy, instanceIndex, stack) {
  87518. const parentCounts = hierarchy.parentCounts;
  87519. const parentIds = hierarchy.parentIds;
  87520. const parentIndexes = hierarchy.parentIndexes;
  87521. const classIds = hierarchy.classIds;
  87522. const instancesLength = classIds.length;
  87523. if (!defined$1(parentIds)) {
  87524. return;
  87525. }
  87526. assert(instanceIndex < instancesLength, "Parent index ".concat(instanceIndex, " exceeds the total number of instances: ").concat(instancesLength));
  87527. assert(stack.indexOf(instanceIndex) === -1, 'Circular dependency detected in the batch table hierarchy.');
  87528. stack.push(instanceIndex);
  87529. const parentCount = defined$1(parentCounts) ? parentCounts[instanceIndex] : 1;
  87530. const parentIndex = defined$1(parentCounts) ? parentIndexes[instanceIndex] : instanceIndex;
  87531. for (let i = 0; i < parentCount; ++i) {
  87532. const parentId = parentIds[parentIndex + i];
  87533. if (parentId !== instanceIndex) {
  87534. validateInstance(hierarchy, parentId, stack);
  87535. }
  87536. }
  87537. stack.pop(instanceIndex);
  87538. }
  87539. function defined(x) {
  87540. return x !== undefined && x !== null;
  87541. }
  87542. const clone = (x, y) => x;
  87543. const IGNORED_PROPERTY_FIELDS = {
  87544. HIERARCHY: true,
  87545. extensions: true,
  87546. extras: true
  87547. };
  87548. class Tile3DBatchTableParser {
  87549. constructor(json, binary, featureCount, options = {}) {
  87550. var _this$json;
  87551. _defineProperty(this, "json", void 0);
  87552. _defineProperty(this, "binary", void 0);
  87553. _defineProperty(this, "featureCount", void 0);
  87554. _defineProperty(this, "_extensions", void 0);
  87555. _defineProperty(this, "_properties", void 0);
  87556. _defineProperty(this, "_binaryProperties", void 0);
  87557. _defineProperty(this, "_hierarchy", void 0);
  87558. assert$7(featureCount >= 0);
  87559. this.json = json || {};
  87560. this.binary = binary;
  87561. this.featureCount = featureCount;
  87562. this._extensions = ((_this$json = this.json) === null || _this$json === void 0 ? void 0 : _this$json.extensions) || {};
  87563. this._properties = {};
  87564. for (const propertyName in this.json) {
  87565. if (!IGNORED_PROPERTY_FIELDS[propertyName]) {
  87566. this._properties[propertyName] = this.json[propertyName];
  87567. }
  87568. }
  87569. this._binaryProperties = this._initializeBinaryProperties();
  87570. if (options['3DTILES_batch_table_hierarchy']) {
  87571. this._hierarchy = initializeHierarchy(this, this.json, this.binary);
  87572. }
  87573. }
  87574. getExtension(extensionName) {
  87575. return this.json && this.json.extensions && this.json.extensions[extensionName];
  87576. }
  87577. memorySizeInBytes() {
  87578. return 0;
  87579. }
  87580. isClass(batchId, className) {
  87581. this._checkBatchId(batchId);
  87582. assert$7(typeof className === 'string', className);
  87583. if (this._hierarchy) {
  87584. const result = traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
  87585. const classId = hierarchy.classIds[instanceIndex];
  87586. const instanceClass = hierarchy.classes[classId];
  87587. return instanceClass.name === className;
  87588. });
  87589. return defined(result);
  87590. }
  87591. return false;
  87592. }
  87593. isExactClass(batchId, className) {
  87594. assert$7(typeof className === 'string', className);
  87595. return this.getExactClassName(batchId) === className;
  87596. }
  87597. getExactClassName(batchId) {
  87598. this._checkBatchId(batchId);
  87599. if (this._hierarchy) {
  87600. const classId = this._hierarchy.classIds[batchId];
  87601. const instanceClass = this._hierarchy.classes[classId];
  87602. return instanceClass.name;
  87603. }
  87604. return undefined;
  87605. }
  87606. hasProperty(batchId, name) {
  87607. this._checkBatchId(batchId);
  87608. assert$7(typeof name === 'string', name);
  87609. return defined(this._properties[name]) || this._hasPropertyInHierarchy(batchId, name);
  87610. }
  87611. getPropertyNames(batchId, results) {
  87612. this._checkBatchId(batchId);
  87613. results = defined(results) ? results : [];
  87614. results.length = 0;
  87615. const propertyNames = Object.keys(this._properties);
  87616. results.push(...propertyNames);
  87617. if (this._hierarchy) {
  87618. this._getPropertyNamesInHierarchy(batchId, results);
  87619. }
  87620. return results;
  87621. }
  87622. getProperty(batchId, name) {
  87623. this._checkBatchId(batchId);
  87624. assert$7(typeof name === 'string', name);
  87625. if (this._binaryProperties) {
  87626. const binaryProperty = this._binaryProperties[name];
  87627. if (defined(binaryProperty)) {
  87628. return this._getBinaryProperty(binaryProperty, batchId);
  87629. }
  87630. }
  87631. const propertyValues = this._properties[name];
  87632. if (defined(propertyValues)) {
  87633. return clone(propertyValues[batchId]);
  87634. }
  87635. if (this._hierarchy) {
  87636. const hierarchyProperty = this._getHierarchyProperty(batchId, name);
  87637. if (defined(hierarchyProperty)) {
  87638. return hierarchyProperty;
  87639. }
  87640. }
  87641. return undefined;
  87642. }
  87643. setProperty(batchId, name, value) {
  87644. const featureCount = this.featureCount;
  87645. this._checkBatchId(batchId);
  87646. assert$7(typeof name === 'string', name);
  87647. if (this._binaryProperties) {
  87648. const binaryProperty = this._binaryProperties[name];
  87649. if (binaryProperty) {
  87650. this._setBinaryProperty(binaryProperty, batchId, value);
  87651. return;
  87652. }
  87653. }
  87654. if (this._hierarchy) {
  87655. if (this._setHierarchyProperty(this, batchId, name, value)) {
  87656. return;
  87657. }
  87658. }
  87659. let propertyValues = this._properties[name];
  87660. if (!defined(propertyValues)) {
  87661. this._properties[name] = new Array(featureCount);
  87662. propertyValues = this._properties[name];
  87663. }
  87664. propertyValues[batchId] = clone(value);
  87665. }
  87666. _checkBatchId(batchId) {
  87667. const valid = batchId >= 0 && batchId < this.featureCount;
  87668. if (!valid) {
  87669. throw new Error('batchId not in range [0, featureCount - 1].');
  87670. }
  87671. }
  87672. _getBinaryProperty(binaryProperty, index) {
  87673. return binaryProperty.unpack(binaryProperty.typedArray, index);
  87674. }
  87675. _setBinaryProperty(binaryProperty, index, value) {
  87676. binaryProperty.pack(value, binaryProperty.typedArray, index);
  87677. }
  87678. _initializeBinaryProperties() {
  87679. let binaryProperties = null;
  87680. for (const name in this._properties) {
  87681. const property = this._properties[name];
  87682. const binaryProperty = this._initializeBinaryProperty(name, property);
  87683. if (binaryProperty) {
  87684. binaryProperties = binaryProperties || {};
  87685. binaryProperties[name] = binaryProperty;
  87686. }
  87687. }
  87688. return binaryProperties;
  87689. }
  87690. _initializeBinaryProperty(name, property) {
  87691. if ('byteOffset' in property) {
  87692. const tile3DAccessor = property;
  87693. assert$7(this.binary, "Property ".concat(name, " requires a batch table binary."));
  87694. assert$7(tile3DAccessor.type, "Property ".concat(name, " requires a type."));
  87695. const accessor = createTypedArrayFromAccessor(tile3DAccessor, this.binary.buffer, this.binary.byteOffset | 0, this.featureCount);
  87696. return {
  87697. typedArray: accessor.values,
  87698. componentCount: accessor.size,
  87699. unpack: accessor.unpacker,
  87700. pack: accessor.packer
  87701. };
  87702. }
  87703. return null;
  87704. }
  87705. _hasPropertyInHierarchy(batchId, name) {
  87706. if (!this._hierarchy) {
  87707. return false;
  87708. }
  87709. const result = traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
  87710. const classId = hierarchy.classIds[instanceIndex];
  87711. const instances = hierarchy.classes[classId].instances;
  87712. return defined(instances[name]);
  87713. });
  87714. return defined(result);
  87715. }
  87716. _getPropertyNamesInHierarchy(batchId, results) {
  87717. traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
  87718. const classId = hierarchy.classIds[instanceIndex];
  87719. const instances = hierarchy.classes[classId].instances;
  87720. for (const name in instances) {
  87721. if (instances.hasOwnProperty(name)) {
  87722. if (results.indexOf(name) === -1) {
  87723. results.push(name);
  87724. }
  87725. }
  87726. }
  87727. });
  87728. }
  87729. _getHierarchyProperty(batchId, name) {
  87730. return traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
  87731. const classId = hierarchy.classIds[instanceIndex];
  87732. const instanceClass = hierarchy.classes[classId];
  87733. const indexInClass = hierarchy.classIndexes[instanceIndex];
  87734. const propertyValues = instanceClass.instances[name];
  87735. if (defined(propertyValues)) {
  87736. if (defined(propertyValues.typedArray)) {
  87737. return this._getBinaryProperty(propertyValues, indexInClass);
  87738. }
  87739. return clone(propertyValues[indexInClass]);
  87740. }
  87741. return null;
  87742. });
  87743. }
  87744. _setHierarchyProperty(batchTable, batchId, name, value) {
  87745. const result = traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
  87746. const classId = hierarchy.classIds[instanceIndex];
  87747. const instanceClass = hierarchy.classes[classId];
  87748. const indexInClass = hierarchy.classIndexes[instanceIndex];
  87749. const propertyValues = instanceClass.instances[name];
  87750. if (defined(propertyValues)) {
  87751. assert$7(instanceIndex === batchId, "Inherited property \"".concat(name, "\" is read-only."));
  87752. if (defined(propertyValues.typedArray)) {
  87753. this._setBinaryProperty(propertyValues, indexInClass, value);
  87754. } else {
  87755. propertyValues[indexInClass] = clone(value);
  87756. }
  87757. return true;
  87758. }
  87759. return false;
  87760. });
  87761. return defined(result);
  87762. }
  87763. }
  87764. const SIZEOF_UINT32$1 = 4;
  87765. function parse3DTileHeaderSync(tile, arrayBuffer, byteOffset = 0) {
  87766. const view = new DataView(arrayBuffer);
  87767. tile.magic = view.getUint32(byteOffset, true);
  87768. byteOffset += SIZEOF_UINT32$1;
  87769. tile.version = view.getUint32(byteOffset, true);
  87770. byteOffset += SIZEOF_UINT32$1;
  87771. tile.byteLength = view.getUint32(byteOffset, true);
  87772. byteOffset += SIZEOF_UINT32$1;
  87773. if (tile.version !== 1) {
  87774. throw new Error("3D Tile Version ".concat(tile.version, " not supported"));
  87775. }
  87776. return byteOffset;
  87777. }
  87778. const SIZEOF_UINT32 = 4;
  87779. const DEPRECATION_WARNING = 'b3dm tile in legacy format.';
  87780. function parse3DTileTablesHeaderSync(tile, arrayBuffer, byteOffset) {
  87781. const view = new DataView(arrayBuffer);
  87782. let batchLength;
  87783. tile.header = tile.header || {};
  87784. let featureTableJsonByteLength = view.getUint32(byteOffset, true);
  87785. byteOffset += SIZEOF_UINT32;
  87786. let featureTableBinaryByteLength = view.getUint32(byteOffset, true);
  87787. byteOffset += SIZEOF_UINT32;
  87788. let batchTableJsonByteLength = view.getUint32(byteOffset, true);
  87789. byteOffset += SIZEOF_UINT32;
  87790. let batchTableBinaryByteLength = view.getUint32(byteOffset, true);
  87791. byteOffset += SIZEOF_UINT32;
  87792. if (batchTableJsonByteLength >= 570425344) {
  87793. byteOffset -= SIZEOF_UINT32 * 2;
  87794. batchLength = featureTableJsonByteLength;
  87795. batchTableJsonByteLength = featureTableBinaryByteLength;
  87796. batchTableBinaryByteLength = 0;
  87797. featureTableJsonByteLength = 0;
  87798. featureTableBinaryByteLength = 0;
  87799. console.warn(DEPRECATION_WARNING);
  87800. } else if (batchTableBinaryByteLength >= 570425344) {
  87801. byteOffset -= SIZEOF_UINT32;
  87802. batchLength = batchTableJsonByteLength;
  87803. batchTableJsonByteLength = featureTableJsonByteLength;
  87804. batchTableBinaryByteLength = featureTableBinaryByteLength;
  87805. featureTableJsonByteLength = 0;
  87806. featureTableBinaryByteLength = 0;
  87807. console.warn(DEPRECATION_WARNING);
  87808. }
  87809. tile.header.featureTableJsonByteLength = featureTableJsonByteLength;
  87810. tile.header.featureTableBinaryByteLength = featureTableBinaryByteLength;
  87811. tile.header.batchTableJsonByteLength = batchTableJsonByteLength;
  87812. tile.header.batchTableBinaryByteLength = batchTableBinaryByteLength;
  87813. tile.header.batchLength = batchLength;
  87814. return byteOffset;
  87815. }
  87816. function parse3DTileTablesSync(tile, arrayBuffer, byteOffset, options) {
  87817. byteOffset = parse3DTileFeatureTable(tile, arrayBuffer, byteOffset);
  87818. byteOffset = parse3DTileBatchTable(tile, arrayBuffer, byteOffset);
  87819. return byteOffset;
  87820. }
  87821. function parse3DTileFeatureTable(tile, arrayBuffer, byteOffset, options) {
  87822. const {
  87823. featureTableJsonByteLength,
  87824. featureTableBinaryByteLength,
  87825. batchLength
  87826. } = tile.header;
  87827. tile.featureTableJson = {
  87828. BATCH_LENGTH: batchLength || 0
  87829. };
  87830. if (featureTableJsonByteLength > 0) {
  87831. const featureTableString = getStringFromArrayBuffer(arrayBuffer, byteOffset, featureTableJsonByteLength);
  87832. tile.featureTableJson = JSON.parse(featureTableString);
  87833. }
  87834. byteOffset += featureTableJsonByteLength;
  87835. tile.featureTableBinary = new Uint8Array(arrayBuffer, byteOffset, featureTableBinaryByteLength);
  87836. byteOffset += featureTableBinaryByteLength;
  87837. return byteOffset;
  87838. }
  87839. function parse3DTileBatchTable(tile, arrayBuffer, byteOffset, options) {
  87840. const {
  87841. batchTableJsonByteLength,
  87842. batchTableBinaryByteLength
  87843. } = tile.header;
  87844. if (batchTableJsonByteLength > 0) {
  87845. const batchTableString = getStringFromArrayBuffer(arrayBuffer, byteOffset, batchTableJsonByteLength);
  87846. tile.batchTableJson = JSON.parse(batchTableString);
  87847. byteOffset += batchTableJsonByteLength;
  87848. if (batchTableBinaryByteLength > 0) {
  87849. tile.batchTableBinary = new Uint8Array(arrayBuffer, byteOffset, batchTableBinaryByteLength);
  87850. tile.batchTableBinary = new Uint8Array(tile.batchTableBinary);
  87851. byteOffset += batchTableBinaryByteLength;
  87852. }
  87853. }
  87854. return byteOffset;
  87855. }
  87856. function normalize3DTileColorAttribute(tile, colors, batchTable) {
  87857. if (!colors && (!tile || !tile.batchIds || !batchTable)) {
  87858. return null;
  87859. }
  87860. const {
  87861. batchIds,
  87862. isRGB565,
  87863. pointCount
  87864. } = tile;
  87865. if (batchIds && batchTable) {
  87866. const colorArray = new Uint8ClampedArray(pointCount * 3);
  87867. for (let i = 0; i < pointCount; i++) {
  87868. const batchId = batchIds[i];
  87869. const dimensions = batchTable.getProperty(batchId, 'dimensions');
  87870. const color = dimensions.map(d => d * 255);
  87871. colorArray[i * 3] = color[0];
  87872. colorArray[i * 3 + 1] = color[1];
  87873. colorArray[i * 3 + 2] = color[2];
  87874. }
  87875. return {
  87876. type: GL$1.UNSIGNED_BYTE,
  87877. value: colorArray,
  87878. size: 3,
  87879. normalized: true
  87880. };
  87881. }
  87882. if (isRGB565) {
  87883. const colorArray = new Uint8ClampedArray(pointCount * 3);
  87884. for (let i = 0; i < pointCount; i++) {
  87885. const color = decodeRGB565(colors[i]);
  87886. colorArray[i * 3] = color[0];
  87887. colorArray[i * 3 + 1] = color[1];
  87888. colorArray[i * 3 + 2] = color[2];
  87889. }
  87890. return {
  87891. type: GL$1.UNSIGNED_BYTE,
  87892. value: colorArray,
  87893. size: 3,
  87894. normalized: true
  87895. };
  87896. }
  87897. if (colors && colors.length === pointCount * 3) {
  87898. return {
  87899. type: GL$1.UNSIGNED_BYTE,
  87900. value: colors,
  87901. size: 3,
  87902. normalized: true
  87903. };
  87904. }
  87905. return {
  87906. type: GL$1.UNSIGNED_BYTE,
  87907. value: colors,
  87908. size: 4,
  87909. normalized: true
  87910. };
  87911. }
  87912. const scratchNormal = new Vector3$1();
  87913. function normalize3DTileNormalAttribute(tile, normals) {
  87914. if (!normals) {
  87915. return null;
  87916. }
  87917. if (tile.isOctEncoded16P) {
  87918. const decodedArray = new Float32Array(tile.pointsLength * 3);
  87919. for (let i = 0; i < tile.pointsLength; i++) {
  87920. octDecode(normals[i * 2], normals[i * 2 + 1], scratchNormal);
  87921. scratchNormal.toArray(decodedArray, i * 3);
  87922. }
  87923. return {
  87924. type: GL$1.FLOAT,
  87925. size: 2,
  87926. value: decodedArray
  87927. };
  87928. }
  87929. return {
  87930. type: GL$1.FLOAT,
  87931. size: 2,
  87932. value: normals
  87933. };
  87934. }
  87935. function normalize3DTilePositionAttribute(tile, positions, options) {
  87936. if (!tile.isQuantized) {
  87937. return positions;
  87938. }
  87939. if (options['3d-tiles'] && options['3d-tiles'].decodeQuantizedPositions) {
  87940. tile.isQuantized = false;
  87941. return decodeQuantizedPositions(tile, positions);
  87942. }
  87943. return {
  87944. type: GL$1.UNSIGNED_SHORT,
  87945. value: positions,
  87946. size: 3,
  87947. normalized: true
  87948. };
  87949. }
  87950. function decodeQuantizedPositions(tile, positions) {
  87951. const scratchPosition = new Vector3$1();
  87952. const decodedArray = new Float32Array(tile.pointCount * 3);
  87953. for (let i = 0; i < tile.pointCount; i++) {
  87954. scratchPosition.set(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]).scale(1 / tile.quantizedRange).multiply(tile.quantizedVolumeScale).add(tile.quantizedVolumeOffset).toArray(decodedArray, i * 3);
  87955. }
  87956. return decodedArray;
  87957. }
  87958. async function parsePointCloud3DTile(tile, arrayBuffer, byteOffset, options, context) {
  87959. byteOffset = parse3DTileHeaderSync(tile, arrayBuffer, byteOffset);
  87960. byteOffset = parse3DTileTablesHeaderSync(tile, arrayBuffer, byteOffset);
  87961. byteOffset = parse3DTileTablesSync(tile, arrayBuffer, byteOffset);
  87962. initializeTile(tile);
  87963. const {
  87964. featureTable,
  87965. batchTable
  87966. } = parsePointCloudTables(tile);
  87967. await parseDraco(tile, featureTable, batchTable, options, context);
  87968. parsePositions(tile, featureTable, options);
  87969. parseColors(tile, featureTable, batchTable);
  87970. parseNormals(tile, featureTable);
  87971. return byteOffset;
  87972. }
  87973. function initializeTile(tile) {
  87974. tile.attributes = {
  87975. positions: null,
  87976. colors: null,
  87977. normals: null,
  87978. batchIds: null
  87979. };
  87980. tile.isQuantized = false;
  87981. tile.isTranslucent = false;
  87982. tile.isRGB565 = false;
  87983. tile.isOctEncoded16P = false;
  87984. }
  87985. function parsePointCloudTables(tile) {
  87986. const featureTable = new Tile3DFeatureTable(tile.featureTableJson, tile.featureTableBinary);
  87987. const pointsLength = featureTable.getGlobalProperty('POINTS_LENGTH');
  87988. if (!Number.isFinite(pointsLength)) {
  87989. throw new Error('POINTS_LENGTH must be defined');
  87990. }
  87991. featureTable.featuresLength = pointsLength;
  87992. tile.featuresLength = pointsLength;
  87993. tile.pointsLength = pointsLength;
  87994. tile.pointCount = pointsLength;
  87995. tile.rtcCenter = featureTable.getGlobalProperty('RTC_CENTER', GL$1.FLOAT, 3);
  87996. const batchTable = parseBatchIds(tile, featureTable);
  87997. return {
  87998. featureTable,
  87999. batchTable
  88000. };
  88001. }
  88002. function parsePositions(tile, featureTable, options) {
  88003. if (!tile.attributes.positions) {
  88004. if (featureTable.hasProperty('POSITION')) {
  88005. tile.attributes.positions = featureTable.getPropertyArray('POSITION', GL$1.FLOAT, 3);
  88006. } else if (featureTable.hasProperty('POSITION_QUANTIZED')) {
  88007. const positions = featureTable.getPropertyArray('POSITION_QUANTIZED', GL$1.UNSIGNED_SHORT, 3);
  88008. tile.isQuantized = true;
  88009. tile.quantizedRange = (1 << 16) - 1;
  88010. tile.quantizedVolumeScale = featureTable.getGlobalProperty('QUANTIZED_VOLUME_SCALE', GL$1.FLOAT, 3);
  88011. if (!tile.quantizedVolumeScale) {
  88012. throw new Error('QUANTIZED_VOLUME_SCALE must be defined for quantized positions.');
  88013. }
  88014. tile.quantizedVolumeOffset = featureTable.getGlobalProperty('QUANTIZED_VOLUME_OFFSET', GL$1.FLOAT, 3);
  88015. if (!tile.quantizedVolumeOffset) {
  88016. throw new Error('QUANTIZED_VOLUME_OFFSET must be defined for quantized positions.');
  88017. }
  88018. tile.attributes.positions = normalize3DTilePositionAttribute(tile, positions, options);
  88019. }
  88020. }
  88021. if (!tile.attributes.positions) {
  88022. throw new Error('Either POSITION or POSITION_QUANTIZED must be defined.');
  88023. }
  88024. }
  88025. function parseColors(tile, featureTable, batchTable) {
  88026. if (!tile.attributes.colors) {
  88027. let colors = null;
  88028. if (featureTable.hasProperty('RGBA')) {
  88029. colors = featureTable.getPropertyArray('RGBA', GL$1.UNSIGNED_BYTE, 4);
  88030. tile.isTranslucent = true;
  88031. } else if (featureTable.hasProperty('RGB')) {
  88032. colors = featureTable.getPropertyArray('RGB', GL$1.UNSIGNED_BYTE, 3);
  88033. } else if (featureTable.hasProperty('RGB565')) {
  88034. colors = featureTable.getPropertyArray('RGB565', GL$1.UNSIGNED_SHORT, 1);
  88035. tile.isRGB565 = true;
  88036. }
  88037. tile.attributes.colors = normalize3DTileColorAttribute(tile, colors, batchTable);
  88038. }
  88039. if (featureTable.hasProperty('CONSTANT_RGBA')) {
  88040. tile.constantRGBA = featureTable.getGlobalProperty('CONSTANT_RGBA', GL$1.UNSIGNED_BYTE, 4);
  88041. }
  88042. }
  88043. function parseNormals(tile, featureTable) {
  88044. if (!tile.attributes.normals) {
  88045. let normals = null;
  88046. if (featureTable.hasProperty('NORMAL')) {
  88047. normals = featureTable.getPropertyArray('NORMAL', GL$1.FLOAT, 3);
  88048. } else if (featureTable.hasProperty('NORMAL_OCT16P')) {
  88049. normals = featureTable.getPropertyArray('NORMAL_OCT16P', GL$1.UNSIGNED_BYTE, 2);
  88050. tile.isOctEncoded16P = true;
  88051. }
  88052. tile.attributes.normals = normalize3DTileNormalAttribute(tile, normals);
  88053. }
  88054. }
  88055. function parseBatchIds(tile, featureTable) {
  88056. let batchTable = null;
  88057. if (!tile.batchIds && featureTable.hasProperty('BATCH_ID')) {
  88058. tile.batchIds = featureTable.getPropertyArray('BATCH_ID', GL$1.UNSIGNED_SHORT, 1);
  88059. if (tile.batchIds) {
  88060. const batchFeatureLength = featureTable.getGlobalProperty('BATCH_LENGTH');
  88061. if (!batchFeatureLength) {
  88062. throw new Error('Global property: BATCH_LENGTH must be defined when BATCH_ID is defined.');
  88063. }
  88064. const {
  88065. batchTableJson,
  88066. batchTableBinary
  88067. } = tile;
  88068. batchTable = new Tile3DBatchTableParser(batchTableJson, batchTableBinary, batchFeatureLength);
  88069. }
  88070. }
  88071. return batchTable;
  88072. }
  88073. async function parseDraco(tile, featureTable, batchTable, options, context) {
  88074. let dracoBuffer;
  88075. let dracoFeatureTableProperties;
  88076. let dracoBatchTableProperties;
  88077. const batchTableDraco = tile.batchTableJson && tile.batchTableJson.extensions && tile.batchTableJson.extensions['3DTILES_draco_point_compression'];
  88078. if (batchTableDraco) {
  88079. dracoBatchTableProperties = batchTableDraco.properties;
  88080. }
  88081. const featureTableDraco = featureTable.getExtension('3DTILES_draco_point_compression');
  88082. if (featureTableDraco) {
  88083. dracoFeatureTableProperties = featureTableDraco.properties;
  88084. const dracoByteOffset = featureTableDraco.byteOffset;
  88085. const dracoByteLength = featureTableDraco.byteLength;
  88086. if (!dracoFeatureTableProperties || !Number.isFinite(dracoByteOffset) || !dracoByteLength) {
  88087. throw new Error('Draco properties, byteOffset, and byteLength must be defined');
  88088. }
  88089. dracoBuffer = tile.featureTableBinary.slice(dracoByteOffset, dracoByteOffset + dracoByteLength);
  88090. tile.hasPositions = Number.isFinite(dracoFeatureTableProperties.POSITION);
  88091. tile.hasColors = Number.isFinite(dracoFeatureTableProperties.RGB) || Number.isFinite(dracoFeatureTableProperties.RGBA);
  88092. tile.hasNormals = Number.isFinite(dracoFeatureTableProperties.NORMAL);
  88093. tile.hasBatchIds = Number.isFinite(dracoFeatureTableProperties.BATCH_ID);
  88094. tile.isTranslucent = Number.isFinite(dracoFeatureTableProperties.RGBA);
  88095. }
  88096. if (!dracoBuffer) {
  88097. return true;
  88098. }
  88099. const dracoData = {
  88100. buffer: dracoBuffer,
  88101. properties: { ...dracoFeatureTableProperties,
  88102. ...dracoBatchTableProperties
  88103. },
  88104. featureTableProperties: dracoFeatureTableProperties,
  88105. batchTableProperties: dracoBatchTableProperties,
  88106. dequantizeInShader: false
  88107. };
  88108. return await loadDraco(tile, dracoData, options, context);
  88109. }
  88110. async function loadDraco(tile, dracoData, options, context) {
  88111. const {
  88112. parse
  88113. } = context;
  88114. const dracoOptions = { ...options,
  88115. draco: { ...options.draco,
  88116. extraAttributes: dracoData.batchTableProperties || {}
  88117. }
  88118. };
  88119. delete dracoOptions['3d-tiles'];
  88120. const data = await parse(dracoData.buffer, DracoLoader, dracoOptions);
  88121. const decodedPositions = data.attributes.POSITION && data.attributes.POSITION.value;
  88122. const decodedColors = data.attributes.COLOR_0 && data.attributes.COLOR_0.value;
  88123. const decodedNormals = data.attributes.NORMAL && data.attributes.NORMAL.value;
  88124. const decodedBatchIds = data.attributes.BATCH_ID && data.attributes.BATCH_ID.value;
  88125. const isQuantizedDraco = decodedPositions && data.attributes.POSITION.value.quantization;
  88126. const isOctEncodedDraco = decodedNormals && data.attributes.NORMAL.value.quantization;
  88127. if (isQuantizedDraco) {
  88128. const quantization = data.POSITION.data.quantization;
  88129. const range = quantization.range;
  88130. tile.quantizedVolumeScale = new Vector3$1(range, range, range);
  88131. tile.quantizedVolumeOffset = new Vector3$1(quantization.minValues);
  88132. tile.quantizedRange = (1 << quantization.quantizationBits) - 1.0;
  88133. tile.isQuantizedDraco = true;
  88134. }
  88135. if (isOctEncodedDraco) {
  88136. tile.octEncodedRange = (1 << data.NORMAL.data.quantization.quantizationBits) - 1.0;
  88137. tile.isOctEncodedDraco = true;
  88138. }
  88139. const batchTableAttributes = {};
  88140. if (dracoData.batchTableProperties) {
  88141. for (const attributeName of Object.keys(dracoData.batchTableProperties)) {
  88142. if (data.attributes[attributeName] && data.attributes[attributeName].value) {
  88143. batchTableAttributes[attributeName.toLowerCase()] = data.attributes[attributeName].value;
  88144. }
  88145. }
  88146. }
  88147. tile.attributes = {
  88148. positions: decodedPositions,
  88149. colors: normalize3DTileColorAttribute(tile, decodedColors, undefined),
  88150. normals: decodedNormals,
  88151. batchIds: decodedBatchIds,
  88152. ...batchTableAttributes
  88153. };
  88154. }
  88155. const VERSION$3 = "3.1.4" ;
  88156. const VERSION$2 = "3.1.4" ;
  88157. const VERSION$1 = "3.1.4" ;
  88158. const BASIS_CDN_ENCODER_WASM = "https://unpkg.com/@loaders.gl/textures@".concat(VERSION$1, "/dist/libs/basis_encoder.wasm");
  88159. const BASIS_CDN_ENCODER_JS = "https://unpkg.com/@loaders.gl/textures@".concat(VERSION$1, "/dist/libs/basis_encoder.js");
  88160. let loadBasisTranscoderPromise;
  88161. async function loadBasisTrascoderModule(options) {
  88162. const modules = options.modules || {};
  88163. if (modules.basis) {
  88164. return modules.basis;
  88165. }
  88166. loadBasisTranscoderPromise = loadBasisTranscoderPromise || loadBasisTrascoder(options);
  88167. return await loadBasisTranscoderPromise;
  88168. }
  88169. async function loadBasisTrascoder(options) {
  88170. let BASIS = null;
  88171. let wasmBinary = null;
  88172. [BASIS, wasmBinary] = await Promise.all([await loadLibrary('basis_transcoder.js', 'textures', options), await loadLibrary('basis_transcoder.wasm', 'textures', options)]);
  88173. BASIS = BASIS || globalThis.BASIS;
  88174. return await initializeBasisTrascoderModule(BASIS, wasmBinary);
  88175. }
  88176. function initializeBasisTrascoderModule(BasisModule, wasmBinary) {
  88177. const options = {};
  88178. if (wasmBinary) {
  88179. options.wasmBinary = wasmBinary;
  88180. }
  88181. return new Promise(resolve => {
  88182. BasisModule(options).then(module => {
  88183. const {
  88184. BasisFile,
  88185. initializeBasis
  88186. } = module;
  88187. initializeBasis();
  88188. resolve({
  88189. BasisFile
  88190. });
  88191. });
  88192. });
  88193. }
  88194. let loadBasisEncoderPromise;
  88195. async function loadBasisEncoderModule(options) {
  88196. const modules = options.modules || {};
  88197. if (modules.basisEncoder) {
  88198. return modules.basisEncoder;
  88199. }
  88200. loadBasisEncoderPromise = loadBasisEncoderPromise || loadBasisEncoder(options);
  88201. return await loadBasisEncoderPromise;
  88202. }
  88203. async function loadBasisEncoder(options) {
  88204. let BASIS_ENCODER = null;
  88205. let wasmBinary = null;
  88206. [BASIS_ENCODER, wasmBinary] = await Promise.all([await loadLibrary(BASIS_CDN_ENCODER_JS, 'textures', options), await loadLibrary(BASIS_CDN_ENCODER_WASM, 'textures', options)]);
  88207. BASIS_ENCODER = BASIS_ENCODER || globalThis.BASIS;
  88208. return await initializeBasisEncoderModule(BASIS_ENCODER, wasmBinary);
  88209. }
  88210. function initializeBasisEncoderModule(BasisEncoderModule, wasmBinary) {
  88211. const options = {};
  88212. if (wasmBinary) {
  88213. options.wasmBinary = wasmBinary;
  88214. }
  88215. return new Promise(resolve => {
  88216. BasisEncoderModule(options).then(module => {
  88217. const {
  88218. BasisFile,
  88219. KTX2File,
  88220. initializeBasis,
  88221. BasisEncoder
  88222. } = module;
  88223. initializeBasis();
  88224. resolve({
  88225. BasisFile,
  88226. KTX2File,
  88227. BasisEncoder
  88228. });
  88229. });
  88230. });
  88231. }
  88232. const GL_EXTENSIONS_CONSTANTS = {
  88233. COMPRESSED_RGB_S3TC_DXT1_EXT: 0x83f0,
  88234. COMPRESSED_RGBA_S3TC_DXT1_EXT: 0x83f1,
  88235. COMPRESSED_RGBA_S3TC_DXT3_EXT: 0x83f2,
  88236. COMPRESSED_RGBA_S3TC_DXT5_EXT: 0x83f3,
  88237. COMPRESSED_R11_EAC: 0x9270,
  88238. COMPRESSED_SIGNED_R11_EAC: 0x9271,
  88239. COMPRESSED_RG11_EAC: 0x9272,
  88240. COMPRESSED_SIGNED_RG11_EAC: 0x9273,
  88241. COMPRESSED_RGB8_ETC2: 0x9274,
  88242. COMPRESSED_RGBA8_ETC2_EAC: 0x9275,
  88243. COMPRESSED_SRGB8_ETC2: 0x9276,
  88244. COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 0x9277,
  88245. COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 0x9278,
  88246. COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 0x9279,
  88247. COMPRESSED_RGB_PVRTC_4BPPV1_IMG: 0x8c00,
  88248. COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: 0x8c02,
  88249. COMPRESSED_RGB_PVRTC_2BPPV1_IMG: 0x8c01,
  88250. COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: 0x8c03,
  88251. COMPRESSED_RGB_ETC1_WEBGL: 0x8d64,
  88252. COMPRESSED_RGB_ATC_WEBGL: 0x8c92,
  88253. COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL: 0x8c93,
  88254. COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL: 0x87ee,
  88255. COMPRESSED_RGBA_ASTC_4X4_KHR: 0x93b0,
  88256. COMPRESSED_RGBA_ASTC_5X4_KHR: 0x93b1,
  88257. COMPRESSED_RGBA_ASTC_5X5_KHR: 0x93b2,
  88258. COMPRESSED_RGBA_ASTC_6X5_KHR: 0x93b3,
  88259. COMPRESSED_RGBA_ASTC_6X6_KHR: 0x93b4,
  88260. COMPRESSED_RGBA_ASTC_8X5_KHR: 0x93b5,
  88261. COMPRESSED_RGBA_ASTC_8X6_KHR: 0x93b6,
  88262. COMPRESSED_RGBA_ASTC_8X8_KHR: 0x93b7,
  88263. COMPRESSED_RGBA_ASTC_10X5_KHR: 0x93b8,
  88264. COMPRESSED_RGBA_ASTC_10X6_KHR: 0x93b9,
  88265. COMPRESSED_RGBA_ASTC_10X8_KHR: 0x93ba,
  88266. COMPRESSED_RGBA_ASTC_10X10_KHR: 0x93bb,
  88267. COMPRESSED_RGBA_ASTC_12X10_KHR: 0x93bc,
  88268. COMPRESSED_RGBA_ASTC_12X12_KHR: 0x93bd,
  88269. COMPRESSED_SRGB8_ALPHA8_ASTC_4X4_KHR: 0x93d0,
  88270. COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR: 0x93d1,
  88271. COMPRESSED_SRGB8_ALPHA8_ASTC_5X5_KHR: 0x93d2,
  88272. COMPRESSED_SRGB8_ALPHA8_ASTC_6X5_KHR: 0x93d3,
  88273. COMPRESSED_SRGB8_ALPHA8_ASTC_6X6_KHR: 0x93d4,
  88274. COMPRESSED_SRGB8_ALPHA8_ASTC_8X5_KHR: 0x93d5,
  88275. COMPRESSED_SRGB8_ALPHA8_ASTC_8X6_KHR: 0x93d6,
  88276. COMPRESSED_SRGB8_ALPHA8_ASTC_8X8_KHR: 0x93d7,
  88277. COMPRESSED_SRGB8_ALPHA8_ASTC_10X5_KHR: 0x93d8,
  88278. COMPRESSED_SRGB8_ALPHA8_ASTC_10X6_KHR: 0x93d9,
  88279. COMPRESSED_SRGB8_ALPHA8_ASTC_10X8_KHR: 0x93da,
  88280. COMPRESSED_SRGB8_ALPHA8_ASTC_10X10_KHR: 0x93db,
  88281. COMPRESSED_SRGB8_ALPHA8_ASTC_12X10_KHR: 0x93dc,
  88282. COMPRESSED_SRGB8_ALPHA8_ASTC_12X12_KHR: 0x93dd,
  88283. COMPRESSED_RED_RGTC1_EXT: 0x8dbb,
  88284. COMPRESSED_SIGNED_RED_RGTC1_EXT: 0x8dbc,
  88285. COMPRESSED_RED_GREEN_RGTC2_EXT: 0x8dbd,
  88286. COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 0x8dbe,
  88287. COMPRESSED_SRGB_S3TC_DXT1_EXT: 0x8c4c,
  88288. COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 0x8c4d,
  88289. COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 0x8c4e,
  88290. COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 0x8c4f
  88291. };
  88292. const BROWSER_PREFIXES = ['', 'WEBKIT_', 'MOZ_'];
  88293. const WEBGL_EXTENSIONS = {
  88294. WEBGL_compressed_texture_s3tc: 'dxt',
  88295. WEBGL_compressed_texture_s3tc_srgb: 'dxt-srgb',
  88296. WEBGL_compressed_texture_etc1: 'etc1',
  88297. WEBGL_compressed_texture_etc: 'etc2',
  88298. WEBGL_compressed_texture_pvrtc: 'pvrtc',
  88299. WEBGL_compressed_texture_atc: 'atc',
  88300. WEBGL_compressed_texture_astc: 'astc',
  88301. EXT_texture_compression_rgtc: 'rgtc'
  88302. };
  88303. let formats = null;
  88304. function getSupportedGPUTextureFormats(gl) {
  88305. if (!formats) {
  88306. gl = gl || getWebGLContext() || undefined;
  88307. formats = new Set();
  88308. for (const prefix of BROWSER_PREFIXES) {
  88309. for (const extension in WEBGL_EXTENSIONS) {
  88310. if (gl && gl.getExtension("".concat(prefix).concat(extension))) {
  88311. const gpuTextureFormat = WEBGL_EXTENSIONS[extension];
  88312. formats.add(gpuTextureFormat);
  88313. }
  88314. }
  88315. }
  88316. }
  88317. return formats;
  88318. }
  88319. function getWebGLContext() {
  88320. try {
  88321. const canvas = document.createElement('canvas');
  88322. return canvas.getContext('webgl');
  88323. } catch (error) {
  88324. return null;
  88325. }
  88326. }
  88327. var n$2,i$2,s$1,a$2,r$1,o$1,l$1,f$1;!function(t){t[t.NONE=0]="NONE",t[t.BASISLZ=1]="BASISLZ",t[t.ZSTD=2]="ZSTD",t[t.ZLIB=3]="ZLIB";}(n$2||(n$2={})),function(t){t[t.BASICFORMAT=0]="BASICFORMAT";}(i$2||(i$2={})),function(t){t[t.UNSPECIFIED=0]="UNSPECIFIED",t[t.ETC1S=163]="ETC1S",t[t.UASTC=166]="UASTC";}(s$1||(s$1={})),function(t){t[t.UNSPECIFIED=0]="UNSPECIFIED",t[t.SRGB=1]="SRGB";}(a$2||(a$2={})),function(t){t[t.UNSPECIFIED=0]="UNSPECIFIED",t[t.LINEAR=1]="LINEAR",t[t.SRGB=2]="SRGB",t[t.ITU=3]="ITU",t[t.NTSC=4]="NTSC",t[t.SLOG=5]="SLOG",t[t.SLOG2=6]="SLOG2";}(r$1||(r$1={})),function(t){t[t.ALPHA_STRAIGHT=0]="ALPHA_STRAIGHT",t[t.ALPHA_PREMULTIPLIED=1]="ALPHA_PREMULTIPLIED";}(o$1||(o$1={})),function(t){t[t.RGB=0]="RGB",t[t.RRR=3]="RRR",t[t.GGG=4]="GGG",t[t.AAA=15]="AAA";}(l$1||(l$1={})),function(t){t[t.RGB=0]="RGB",t[t.RGBA=3]="RGBA",t[t.RRR=4]="RRR",t[t.RRRG=5]="RRRG";}(f$1||(f$1={}));
  88328. const KTX2_ID = [0xab, 0x4b, 0x54, 0x58, 0x20, 0x32, 0x30, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a];
  88329. function isKTX(data) {
  88330. const id = new Uint8Array(data);
  88331. const notKTX = id.byteLength < KTX2_ID.length || id[0] !== KTX2_ID[0] || id[1] !== KTX2_ID[1] || id[2] !== KTX2_ID[2] || id[3] !== KTX2_ID[3] || id[4] !== KTX2_ID[4] || id[5] !== KTX2_ID[5] || id[6] !== KTX2_ID[6] || id[7] !== KTX2_ID[7] || id[8] !== KTX2_ID[8] || id[9] !== KTX2_ID[9] || id[10] !== KTX2_ID[10] || id[11] !== KTX2_ID[11];
  88332. return !notKTX;
  88333. }
  88334. const OutputFormat = {
  88335. etc1: {
  88336. basisFormat: 0,
  88337. compressed: true,
  88338. format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_ETC1_WEBGL
  88339. },
  88340. etc2: {
  88341. basisFormat: 1,
  88342. compressed: true
  88343. },
  88344. bc1: {
  88345. basisFormat: 2,
  88346. compressed: true,
  88347. format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT
  88348. },
  88349. bc3: {
  88350. basisFormat: 3,
  88351. compressed: true,
  88352. format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT
  88353. },
  88354. bc4: {
  88355. basisFormat: 4,
  88356. compressed: true
  88357. },
  88358. bc5: {
  88359. basisFormat: 5,
  88360. compressed: true
  88361. },
  88362. 'bc7-m6-opaque-only': {
  88363. basisFormat: 6,
  88364. compressed: true
  88365. },
  88366. 'bc7-m5': {
  88367. basisFormat: 7,
  88368. compressed: true
  88369. },
  88370. 'pvrtc1-4-rgb': {
  88371. basisFormat: 8,
  88372. compressed: true,
  88373. format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
  88374. },
  88375. 'pvrtc1-4-rgba': {
  88376. basisFormat: 9,
  88377. compressed: true,
  88378. format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
  88379. },
  88380. 'astc-4x4': {
  88381. basisFormat: 10,
  88382. compressed: true,
  88383. format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_4X4_KHR
  88384. },
  88385. 'atc-rgb': {
  88386. basisFormat: 11,
  88387. compressed: true
  88388. },
  88389. 'atc-rgba-interpolated-alpha': {
  88390. basisFormat: 12,
  88391. compressed: true
  88392. },
  88393. rgba32: {
  88394. basisFormat: 13,
  88395. compressed: false
  88396. },
  88397. rgb565: {
  88398. basisFormat: 14,
  88399. compressed: false
  88400. },
  88401. bgr565: {
  88402. basisFormat: 15,
  88403. compressed: false
  88404. },
  88405. rgba4444: {
  88406. basisFormat: 16,
  88407. compressed: false
  88408. }
  88409. };
  88410. async function parseBasis(data, options) {
  88411. if (options.basis.containerFormat === 'auto') {
  88412. if (isKTX(data)) {
  88413. const fileConstructors = await loadBasisEncoderModule(options);
  88414. return parseKTX2File(fileConstructors.KTX2File, data, options);
  88415. }
  88416. const {
  88417. BasisFile
  88418. } = await loadBasisTrascoderModule(options);
  88419. return parseBasisFile(BasisFile, data, options);
  88420. }
  88421. switch (options.basis.module) {
  88422. case 'encoder':
  88423. const fileConstructors = await loadBasisEncoderModule(options);
  88424. switch (options.basis.containerFormat) {
  88425. case 'ktx2':
  88426. return parseKTX2File(fileConstructors.KTX2File, data, options);
  88427. case 'basis':
  88428. default:
  88429. return parseBasisFile(fileConstructors.BasisFile, data, options);
  88430. }
  88431. case 'transcoder':
  88432. default:
  88433. const {
  88434. BasisFile
  88435. } = await loadBasisTrascoderModule(options);
  88436. return parseBasisFile(BasisFile, data, options);
  88437. }
  88438. }
  88439. function parseBasisFile(BasisFile, data, options) {
  88440. const basisFile = new BasisFile(new Uint8Array(data));
  88441. try {
  88442. if (!basisFile.startTranscoding()) {
  88443. return null;
  88444. }
  88445. const imageCount = basisFile.getNumImages();
  88446. const images = [];
  88447. for (let imageIndex = 0; imageIndex < imageCount; imageIndex++) {
  88448. const levelsCount = basisFile.getNumLevels(imageIndex);
  88449. const levels = [];
  88450. for (let levelIndex = 0; levelIndex < levelsCount; levelIndex++) {
  88451. levels.push(transcodeImage(basisFile, imageIndex, levelIndex, options));
  88452. }
  88453. images.push(levels);
  88454. }
  88455. return images;
  88456. } finally {
  88457. basisFile.close();
  88458. basisFile.delete();
  88459. }
  88460. }
  88461. function transcodeImage(basisFile, imageIndex, levelIndex, options) {
  88462. const width = basisFile.getImageWidth(imageIndex, levelIndex);
  88463. const height = basisFile.getImageHeight(imageIndex, levelIndex);
  88464. const hasAlpha = basisFile.getHasAlpha();
  88465. const {
  88466. compressed,
  88467. format,
  88468. basisFormat
  88469. } = getBasisOptions(options, hasAlpha);
  88470. const decodedSize = basisFile.getImageTranscodedSizeInBytes(imageIndex, levelIndex, basisFormat);
  88471. const decodedData = new Uint8Array(decodedSize);
  88472. if (!basisFile.transcodeImage(decodedData, imageIndex, levelIndex, basisFormat, 0, 0)) {
  88473. return null;
  88474. }
  88475. return {
  88476. width,
  88477. height,
  88478. data: decodedData,
  88479. compressed,
  88480. hasAlpha,
  88481. format
  88482. };
  88483. }
  88484. function parseKTX2File(KTX2File, data, options) {
  88485. const ktx2File = new KTX2File(new Uint8Array(data));
  88486. try {
  88487. if (!ktx2File.startTranscoding()) {
  88488. return null;
  88489. }
  88490. const levelsCount = ktx2File.getLevels();
  88491. const levels = [];
  88492. for (let levelIndex = 0; levelIndex < levelsCount; levelIndex++) {
  88493. levels.push(transcodeKTX2Image(ktx2File, levelIndex, options));
  88494. break;
  88495. }
  88496. return levels;
  88497. } finally {
  88498. ktx2File.close();
  88499. ktx2File.delete();
  88500. }
  88501. }
  88502. function transcodeKTX2Image(ktx2File, levelIndex, options) {
  88503. const {
  88504. alphaFlag,
  88505. height,
  88506. width
  88507. } = ktx2File.getImageLevelInfo(levelIndex, 0, 0);
  88508. const {
  88509. compressed,
  88510. format,
  88511. basisFormat
  88512. } = getBasisOptions(options, alphaFlag);
  88513. const decodedSize = ktx2File.getImageTranscodedSizeInBytes(levelIndex, 0, 0, basisFormat);
  88514. const decodedData = new Uint8Array(decodedSize);
  88515. if (!ktx2File.transcodeImage(decodedData, levelIndex, 0, 0, basisFormat, 0, -1, -1)) {
  88516. return null;
  88517. }
  88518. return {
  88519. width,
  88520. height,
  88521. data: decodedData,
  88522. compressed,
  88523. alphaFlag,
  88524. format
  88525. };
  88526. }
  88527. function getBasisOptions(options, hasAlpha) {
  88528. let format = options && options.basis && options.basis.format;
  88529. if (format === 'auto') {
  88530. format = selectSupportedBasisFormat();
  88531. }
  88532. if (typeof format === 'object') {
  88533. format = hasAlpha ? format.alpha : format.noAlpha;
  88534. }
  88535. format = format.toLowerCase();
  88536. return OutputFormat[format];
  88537. }
  88538. function selectSupportedBasisFormat() {
  88539. const supportedFormats = getSupportedGPUTextureFormats();
  88540. if (supportedFormats.has('astc')) {
  88541. return 'astc-4x4';
  88542. } else if (supportedFormats.has('dxt')) {
  88543. return {
  88544. alpha: 'bc3',
  88545. noAlpha: 'bc1'
  88546. };
  88547. } else if (supportedFormats.has('pvrtc')) {
  88548. return {
  88549. alpha: 'pvrtc1-4-rgba',
  88550. noAlpha: 'pvrtc1-4-rgb'
  88551. };
  88552. } else if (supportedFormats.has('etc1')) {
  88553. return 'etc1';
  88554. } else if (supportedFormats.has('etc2')) {
  88555. return 'etc2';
  88556. }
  88557. return 'rgb565';
  88558. }
  88559. const BasisWorkerLoader = {
  88560. name: 'Basis',
  88561. id: 'basis',
  88562. module: 'textures',
  88563. version: VERSION$2,
  88564. worker: true,
  88565. extensions: ['basis', 'ktx2'],
  88566. mimeTypes: ['application/octet-stream', 'image/ktx2'],
  88567. tests: ['sB'],
  88568. binary: true,
  88569. options: {
  88570. basis: {
  88571. format: 'auto',
  88572. libraryPath: 'libs/',
  88573. containerFormat: 'auto',
  88574. module: 'transcoder'
  88575. }
  88576. }
  88577. };
  88578. const BasisLoader = { ...BasisWorkerLoader,
  88579. parse: parseBasis
  88580. };
  88581. const VERSION = "3.1.4" ;
  88582. const {
  88583. _parseImageNode
  88584. } = globalThis;
  88585. const IMAGE_SUPPORTED = typeof Image !== 'undefined';
  88586. const IMAGE_BITMAP_SUPPORTED = typeof ImageBitmap !== 'undefined';
  88587. const NODE_IMAGE_SUPPORTED = Boolean(_parseImageNode);
  88588. const DATA_SUPPORTED = isBrowser$2 ? true : NODE_IMAGE_SUPPORTED;
  88589. function isImageTypeSupported(type) {
  88590. switch (type) {
  88591. case 'auto':
  88592. return IMAGE_BITMAP_SUPPORTED || IMAGE_SUPPORTED || DATA_SUPPORTED;
  88593. case 'imagebitmap':
  88594. return IMAGE_BITMAP_SUPPORTED;
  88595. case 'image':
  88596. return IMAGE_SUPPORTED;
  88597. case 'data':
  88598. return DATA_SUPPORTED;
  88599. default:
  88600. throw new Error("@loaders.gl/images: image ".concat(type, " not supported in this environment"));
  88601. }
  88602. }
  88603. function getDefaultImageType() {
  88604. if (IMAGE_BITMAP_SUPPORTED) {
  88605. return 'imagebitmap';
  88606. }
  88607. if (IMAGE_SUPPORTED) {
  88608. return 'image';
  88609. }
  88610. if (DATA_SUPPORTED) {
  88611. return 'data';
  88612. }
  88613. throw new Error('Install \'@loaders.gl/polyfills\' to parse images under Node.js');
  88614. }
  88615. function getImageType(image) {
  88616. const format = getImageTypeOrNull(image);
  88617. if (!format) {
  88618. throw new Error('Not an image');
  88619. }
  88620. return format;
  88621. }
  88622. function getImageData(image) {
  88623. switch (getImageType(image)) {
  88624. case 'data':
  88625. return image;
  88626. case 'image':
  88627. case 'imagebitmap':
  88628. const canvas = document.createElement('canvas');
  88629. const context = canvas.getContext('2d');
  88630. if (!context) {
  88631. throw new Error('getImageData');
  88632. }
  88633. canvas.width = image.width;
  88634. canvas.height = image.height;
  88635. context.drawImage(image, 0, 0);
  88636. return context.getImageData(0, 0, image.width, image.height);
  88637. default:
  88638. throw new Error('getImageData');
  88639. }
  88640. }
  88641. function getImageTypeOrNull(image) {
  88642. if (typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap) {
  88643. return 'imagebitmap';
  88644. }
  88645. if (typeof Image !== 'undefined' && image instanceof Image) {
  88646. return 'image';
  88647. }
  88648. if (image && typeof image === 'object' && image.data && image.width && image.height) {
  88649. return 'data';
  88650. }
  88651. return null;
  88652. }
  88653. const SVG_DATA_URL_PATTERN = /^data:image\/svg\+xml/;
  88654. const SVG_URL_PATTERN = /\.svg((\?|#).*)?$/;
  88655. function isSVG(url) {
  88656. return url && (SVG_DATA_URL_PATTERN.test(url) || SVG_URL_PATTERN.test(url));
  88657. }
  88658. function getBlobOrSVGDataUrl(arrayBuffer, url) {
  88659. if (isSVG(url)) {
  88660. const textDecoder = new TextDecoder();
  88661. let xmlText = textDecoder.decode(arrayBuffer);
  88662. try {
  88663. if (typeof unescape === 'function' && typeof encodeURIComponent === 'function') {
  88664. xmlText = unescape(encodeURIComponent(xmlText));
  88665. }
  88666. } catch (error) {
  88667. throw new Error(error.message);
  88668. }
  88669. const src = "data:image/svg+xml;base64,".concat(btoa(xmlText));
  88670. return src;
  88671. }
  88672. return getBlob(arrayBuffer, url);
  88673. }
  88674. function getBlob(arrayBuffer, url) {
  88675. if (isSVG(url)) {
  88676. throw new Error('SVG cannot be parsed directly to imagebitmap');
  88677. }
  88678. return new Blob([new Uint8Array(arrayBuffer)]);
  88679. }
  88680. async function parseToImage(arrayBuffer, options, url) {
  88681. const blobOrDataUrl = getBlobOrSVGDataUrl(arrayBuffer, url);
  88682. const URL = self.URL || self.webkitURL;
  88683. const objectUrl = typeof blobOrDataUrl !== 'string' && URL.createObjectURL(blobOrDataUrl);
  88684. try {
  88685. return await loadToImage(objectUrl || blobOrDataUrl, options);
  88686. } finally {
  88687. if (objectUrl) {
  88688. URL.revokeObjectURL(objectUrl);
  88689. }
  88690. }
  88691. }
  88692. async function loadToImage(url, options) {
  88693. const image = new Image();
  88694. image.src = url;
  88695. if (options.image && options.image.decode && image.decode) {
  88696. await image.decode();
  88697. return image;
  88698. }
  88699. return await new Promise((resolve, reject) => {
  88700. try {
  88701. image.onload = () => resolve(image);
  88702. image.onerror = err => reject(new Error("Could not load image ".concat(url, ": ").concat(err)));
  88703. } catch (error) {
  88704. reject(error);
  88705. }
  88706. });
  88707. }
  88708. const EMPTY_OBJECT = {};
  88709. let imagebitmapOptionsSupported = true;
  88710. async function parseToImageBitmap(arrayBuffer, options, url) {
  88711. let blob;
  88712. if (isSVG(url)) {
  88713. const image = await parseToImage(arrayBuffer, options, url);
  88714. blob = image;
  88715. } else {
  88716. blob = getBlob(arrayBuffer, url);
  88717. }
  88718. const imagebitmapOptions = options && options.imagebitmap;
  88719. return await safeCreateImageBitmap(blob, imagebitmapOptions);
  88720. }
  88721. async function safeCreateImageBitmap(blob, imagebitmapOptions = null) {
  88722. if (isEmptyObject(imagebitmapOptions) || !imagebitmapOptionsSupported) {
  88723. imagebitmapOptions = null;
  88724. }
  88725. if (imagebitmapOptions) {
  88726. try {
  88727. return await createImageBitmap(blob, imagebitmapOptions);
  88728. } catch (error) {
  88729. console.warn(error);
  88730. imagebitmapOptionsSupported = false;
  88731. }
  88732. }
  88733. return await createImageBitmap(blob);
  88734. }
  88735. function isEmptyObject(object) {
  88736. for (const key in object || EMPTY_OBJECT) {
  88737. return false;
  88738. }
  88739. return true;
  88740. }
  88741. const BIG_ENDIAN = false;
  88742. const LITTLE_ENDIAN = true;
  88743. function getBinaryImageMetadata(binaryData) {
  88744. const dataView = toDataView(binaryData);
  88745. return getPngMetadata(dataView) || getJpegMetadata(dataView) || getGifMetadata(dataView) || getBmpMetadata(dataView);
  88746. }
  88747. function getPngMetadata(binaryData) {
  88748. const dataView = toDataView(binaryData);
  88749. const isPng = dataView.byteLength >= 24 && dataView.getUint32(0, BIG_ENDIAN) === 0x89504e47;
  88750. if (!isPng) {
  88751. return null;
  88752. }
  88753. return {
  88754. mimeType: 'image/png',
  88755. width: dataView.getUint32(16, BIG_ENDIAN),
  88756. height: dataView.getUint32(20, BIG_ENDIAN)
  88757. };
  88758. }
  88759. function getGifMetadata(binaryData) {
  88760. const dataView = toDataView(binaryData);
  88761. const isGif = dataView.byteLength >= 10 && dataView.getUint32(0, BIG_ENDIAN) === 0x47494638;
  88762. if (!isGif) {
  88763. return null;
  88764. }
  88765. return {
  88766. mimeType: 'image/gif',
  88767. width: dataView.getUint16(6, LITTLE_ENDIAN),
  88768. height: dataView.getUint16(8, LITTLE_ENDIAN)
  88769. };
  88770. }
  88771. function getBmpMetadata(binaryData) {
  88772. const dataView = toDataView(binaryData);
  88773. const isBmp = dataView.byteLength >= 14 && dataView.getUint16(0, BIG_ENDIAN) === 0x424d && dataView.getUint32(2, LITTLE_ENDIAN) === dataView.byteLength;
  88774. if (!isBmp) {
  88775. return null;
  88776. }
  88777. return {
  88778. mimeType: 'image/bmp',
  88779. width: dataView.getUint32(18, LITTLE_ENDIAN),
  88780. height: dataView.getUint32(22, LITTLE_ENDIAN)
  88781. };
  88782. }
  88783. function getJpegMetadata(binaryData) {
  88784. const dataView = toDataView(binaryData);
  88785. const isJpeg = dataView.byteLength >= 3 && dataView.getUint16(0, BIG_ENDIAN) === 0xffd8 && dataView.getUint8(2) === 0xff;
  88786. if (!isJpeg) {
  88787. return null;
  88788. }
  88789. const {
  88790. tableMarkers,
  88791. sofMarkers
  88792. } = getJpegMarkers();
  88793. let i = 2;
  88794. while (i + 9 < dataView.byteLength) {
  88795. const marker = dataView.getUint16(i, BIG_ENDIAN);
  88796. if (sofMarkers.has(marker)) {
  88797. return {
  88798. mimeType: 'image/jpeg',
  88799. height: dataView.getUint16(i + 5, BIG_ENDIAN),
  88800. width: dataView.getUint16(i + 7, BIG_ENDIAN)
  88801. };
  88802. }
  88803. if (!tableMarkers.has(marker)) {
  88804. return null;
  88805. }
  88806. i += 2;
  88807. i += dataView.getUint16(i, BIG_ENDIAN);
  88808. }
  88809. return null;
  88810. }
  88811. function getJpegMarkers() {
  88812. const tableMarkers = new Set([0xffdb, 0xffc4, 0xffcc, 0xffdd, 0xfffe]);
  88813. for (let i = 0xffe0; i < 0xfff0; ++i) {
  88814. tableMarkers.add(i);
  88815. }
  88816. const sofMarkers = new Set([0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc5, 0xffc6, 0xffc7, 0xffc9, 0xffca, 0xffcb, 0xffcd, 0xffce, 0xffcf, 0xffde]);
  88817. return {
  88818. tableMarkers,
  88819. sofMarkers
  88820. };
  88821. }
  88822. function toDataView(data) {
  88823. if (data instanceof DataView) {
  88824. return data;
  88825. }
  88826. if (ArrayBuffer.isView(data)) {
  88827. return new DataView(data.buffer);
  88828. }
  88829. if (data instanceof ArrayBuffer) {
  88830. return new DataView(data);
  88831. }
  88832. throw new Error('toDataView');
  88833. }
  88834. async function parseToNodeImage(arrayBuffer, options) {
  88835. const {
  88836. mimeType
  88837. } = getBinaryImageMetadata(arrayBuffer) || {};
  88838. const _parseImageNode = globalThis._parseImageNode;
  88839. assert$7(_parseImageNode);
  88840. return await _parseImageNode(arrayBuffer, mimeType);
  88841. }
  88842. async function parseImage(arrayBuffer, options, context) {
  88843. options = options || {};
  88844. const imageOptions = options.image || {};
  88845. const imageType = imageOptions.type || 'auto';
  88846. const {
  88847. url
  88848. } = context || {};
  88849. const loadType = getLoadableImageType(imageType);
  88850. let image;
  88851. switch (loadType) {
  88852. case 'imagebitmap':
  88853. image = await parseToImageBitmap(arrayBuffer, options, url);
  88854. break;
  88855. case 'image':
  88856. image = await parseToImage(arrayBuffer, options, url);
  88857. break;
  88858. case 'data':
  88859. image = await parseToNodeImage(arrayBuffer);
  88860. break;
  88861. default:
  88862. assert$7(false);
  88863. }
  88864. if (imageType === 'data') {
  88865. image = getImageData(image);
  88866. }
  88867. return image;
  88868. }
  88869. function getLoadableImageType(type) {
  88870. switch (type) {
  88871. case 'auto':
  88872. case 'data':
  88873. return getDefaultImageType();
  88874. default:
  88875. isImageTypeSupported(type);
  88876. return type;
  88877. }
  88878. }
  88879. const EXTENSIONS$1 = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'ico', 'svg'];
  88880. const MIME_TYPES = ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/bmp', 'image/vnd.microsoft.icon', 'image/svg+xml'];
  88881. const DEFAULT_IMAGE_LOADER_OPTIONS = {
  88882. image: {
  88883. type: 'auto',
  88884. decode: true
  88885. }
  88886. };
  88887. const ImageLoader$1 = {
  88888. id: 'image',
  88889. module: 'images',
  88890. name: 'Images',
  88891. version: VERSION,
  88892. mimeTypes: MIME_TYPES,
  88893. extensions: EXTENSIONS$1,
  88894. parse: parseImage,
  88895. tests: [arrayBuffer => Boolean(getBinaryImageMetadata(new DataView(arrayBuffer)))],
  88896. options: DEFAULT_IMAGE_LOADER_OPTIONS
  88897. };
  88898. const NODE_FORMAT_SUPPORT = ['image/png', 'image/jpeg', 'image/gif'];
  88899. const mimeTypeSupported = {};
  88900. function _isImageFormatSupported(mimeType) {
  88901. if (mimeTypeSupported[mimeType] === undefined) {
  88902. mimeTypeSupported[mimeType] = checkFormatSupport(mimeType);
  88903. }
  88904. return mimeTypeSupported[mimeType];
  88905. }
  88906. function checkFormatSupport(mimeType) {
  88907. switch (mimeType) {
  88908. case 'image/webp':
  88909. return checkWebPSupport();
  88910. case 'image/svg':
  88911. return isBrowser$2;
  88912. default:
  88913. if (!isBrowser$2) {
  88914. const {
  88915. _parseImageNode
  88916. } = globalThis;
  88917. return Boolean(_parseImageNode) && NODE_FORMAT_SUPPORT.includes(mimeType);
  88918. }
  88919. return true;
  88920. }
  88921. }
  88922. function checkWebPSupport() {
  88923. if (!isBrowser$2) {
  88924. return false;
  88925. }
  88926. try {
  88927. const element = document.createElement('canvas');
  88928. return element.toDataURL('image/webp').indexOf('data:image/webp') === 0;
  88929. } catch {
  88930. return false;
  88931. }
  88932. }
  88933. function assert$1(condition, message) {
  88934. if (!condition) {
  88935. throw new Error(message || 'assert failed: gltf');
  88936. }
  88937. }
  88938. function resolveUrl(url, options) {
  88939. const absolute = url.startsWith('data:') || url.startsWith('http:') || url.startsWith('https:');
  88940. if (absolute) {
  88941. return url;
  88942. }
  88943. const baseUrl = options.baseUri || options.uri;
  88944. if (!baseUrl) {
  88945. throw new Error("'baseUri' must be provided to resolve relative url ".concat(url));
  88946. }
  88947. return baseUrl.substr(0, baseUrl.lastIndexOf('/') + 1) + url;
  88948. }
  88949. function getTypedArrayForBufferView(json, buffers, bufferViewIndex) {
  88950. const bufferView = json.bufferViews[bufferViewIndex];
  88951. assert$1(bufferView);
  88952. const bufferIndex = bufferView.buffer;
  88953. const binChunk = buffers[bufferIndex];
  88954. assert$1(binChunk);
  88955. const byteOffset = (bufferView.byteOffset || 0) + binChunk.byteOffset;
  88956. return new Uint8Array(binChunk.arrayBuffer, byteOffset, bufferView.byteLength);
  88957. }
  88958. const TYPES = ['SCALAR', 'VEC2', 'VEC3', 'VEC4'];
  88959. const ARRAY_CONSTRUCTOR_TO_WEBGL_CONSTANT = [[Int8Array, 5120], [Uint8Array, 5121], [Int16Array, 5122], [Uint16Array, 5123], [Uint32Array, 5125], [Float32Array, 5126], [Float64Array, 5130]];
  88960. const ARRAY_TO_COMPONENT_TYPE = new Map(ARRAY_CONSTRUCTOR_TO_WEBGL_CONSTANT);
  88961. const ATTRIBUTE_TYPE_TO_COMPONENTS = {
  88962. SCALAR: 1,
  88963. VEC2: 2,
  88964. VEC3: 3,
  88965. VEC4: 4,
  88966. MAT2: 4,
  88967. MAT3: 9,
  88968. MAT4: 16
  88969. };
  88970. const ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE = {
  88971. 5120: 1,
  88972. 5121: 1,
  88973. 5122: 2,
  88974. 5123: 2,
  88975. 5125: 4,
  88976. 5126: 4
  88977. };
  88978. const ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = {
  88979. 5120: Int8Array,
  88980. 5121: Uint8Array,
  88981. 5122: Int16Array,
  88982. 5123: Uint16Array,
  88983. 5125: Uint32Array,
  88984. 5126: Float32Array
  88985. };
  88986. function getAccessorTypeFromSize(size) {
  88987. const type = TYPES[size - 1];
  88988. return type || TYPES[0];
  88989. }
  88990. function getComponentTypeFromArray(typedArray) {
  88991. const componentType = ARRAY_TO_COMPONENT_TYPE.get(typedArray.constructor);
  88992. if (!componentType) {
  88993. throw new Error('Illegal typed array');
  88994. }
  88995. return componentType;
  88996. }
  88997. function getAccessorArrayTypeAndLength(accessor, bufferView) {
  88998. const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];
  88999. const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];
  89000. const bytesPerComponent = ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE[accessor.componentType];
  89001. const length = accessor.count * components;
  89002. const byteLength = accessor.count * components * bytesPerComponent;
  89003. assert$1(byteLength >= 0 && byteLength <= bufferView.byteLength);
  89004. return {
  89005. ArrayType,
  89006. length,
  89007. byteLength
  89008. };
  89009. }
  89010. const DEFAULT_GLTF_JSON = {
  89011. asset: {
  89012. version: '2.0',
  89013. generator: 'loaders.gl'
  89014. },
  89015. buffers: []
  89016. };
  89017. class GLTFScenegraph {
  89018. constructor(gltf) {
  89019. _defineProperty(this, "gltf", void 0);
  89020. _defineProperty(this, "sourceBuffers", void 0);
  89021. _defineProperty(this, "byteLength", void 0);
  89022. this.gltf = gltf || {
  89023. json: { ...DEFAULT_GLTF_JSON
  89024. },
  89025. buffers: []
  89026. };
  89027. this.sourceBuffers = [];
  89028. this.byteLength = 0;
  89029. if (this.gltf.buffers && this.gltf.buffers[0]) {
  89030. this.byteLength = this.gltf.buffers[0].byteLength;
  89031. this.sourceBuffers = [this.gltf.buffers[0]];
  89032. }
  89033. }
  89034. get json() {
  89035. return this.gltf.json;
  89036. }
  89037. getApplicationData(key) {
  89038. const data = this.json[key];
  89039. return data;
  89040. }
  89041. getExtraData(key) {
  89042. const extras = this.json.extras || {};
  89043. return extras[key];
  89044. }
  89045. getExtension(extensionName) {
  89046. const isExtension = this.getUsedExtensions().find(name => name === extensionName);
  89047. const extensions = this.json.extensions || {};
  89048. return isExtension ? extensions[extensionName] || true : null;
  89049. }
  89050. getRequiredExtension(extensionName) {
  89051. const isRequired = this.getRequiredExtensions().find(name => name === extensionName);
  89052. return isRequired ? this.getExtension(extensionName) : null;
  89053. }
  89054. getRequiredExtensions() {
  89055. return this.json.extensionsRequired || [];
  89056. }
  89057. getUsedExtensions() {
  89058. return this.json.extensionsUsed || [];
  89059. }
  89060. getObjectExtension(object, extensionName) {
  89061. const extensions = object.extensions || {};
  89062. return extensions[extensionName];
  89063. }
  89064. getScene(index) {
  89065. return this.getObject('scenes', index);
  89066. }
  89067. getNode(index) {
  89068. return this.getObject('nodes', index);
  89069. }
  89070. getSkin(index) {
  89071. return this.getObject('skins', index);
  89072. }
  89073. getMesh(index) {
  89074. return this.getObject('meshes', index);
  89075. }
  89076. getMaterial(index) {
  89077. return this.getObject('materials', index);
  89078. }
  89079. getAccessor(index) {
  89080. return this.getObject('accessors', index);
  89081. }
  89082. getTexture(index) {
  89083. return this.getObject('textures', index);
  89084. }
  89085. getSampler(index) {
  89086. return this.getObject('samplers', index);
  89087. }
  89088. getImage(index) {
  89089. return this.getObject('images', index);
  89090. }
  89091. getBufferView(index) {
  89092. return this.getObject('bufferViews', index);
  89093. }
  89094. getBuffer(index) {
  89095. return this.getObject('buffers', index);
  89096. }
  89097. getObject(array, index) {
  89098. if (typeof index === 'object') {
  89099. return index;
  89100. }
  89101. const object = this.json[array] && this.json[array][index];
  89102. if (!object) {
  89103. throw new Error("glTF file error: Could not find ".concat(array, "[").concat(index, "]"));
  89104. }
  89105. return object;
  89106. }
  89107. getTypedArrayForBufferView(bufferView) {
  89108. bufferView = this.getBufferView(bufferView);
  89109. const bufferIndex = bufferView.buffer;
  89110. const binChunk = this.gltf.buffers[bufferIndex];
  89111. assert$1(binChunk);
  89112. const byteOffset = (bufferView.byteOffset || 0) + binChunk.byteOffset;
  89113. return new Uint8Array(binChunk.arrayBuffer, byteOffset, bufferView.byteLength);
  89114. }
  89115. getTypedArrayForAccessor(accessor) {
  89116. accessor = this.getAccessor(accessor);
  89117. const bufferView = this.getBufferView(accessor.bufferView);
  89118. const buffer = this.getBuffer(bufferView.buffer);
  89119. const arrayBuffer = buffer.data;
  89120. const {
  89121. ArrayType,
  89122. length
  89123. } = getAccessorArrayTypeAndLength(accessor, bufferView);
  89124. const byteOffset = bufferView.byteOffset + accessor.byteOffset;
  89125. return new ArrayType(arrayBuffer, byteOffset, length);
  89126. }
  89127. getTypedArrayForImageData(image) {
  89128. image = this.getAccessor(image);
  89129. const bufferView = this.getBufferView(image.bufferView);
  89130. const buffer = this.getBuffer(bufferView.buffer);
  89131. const arrayBuffer = buffer.data;
  89132. const byteOffset = bufferView.byteOffset || 0;
  89133. return new Uint8Array(arrayBuffer, byteOffset, bufferView.byteLength);
  89134. }
  89135. addApplicationData(key, data) {
  89136. this.json[key] = data;
  89137. return this;
  89138. }
  89139. addExtraData(key, data) {
  89140. this.json.extras = this.json.extras || {};
  89141. this.json.extras[key] = data;
  89142. return this;
  89143. }
  89144. addObjectExtension(object, extensionName, data) {
  89145. object.extensions = object.extensions || {};
  89146. object.extensions[extensionName] = data;
  89147. this.registerUsedExtension(extensionName);
  89148. return this;
  89149. }
  89150. setObjectExtension(object, extensionName, data) {
  89151. const extensions = object.extensions || {};
  89152. extensions[extensionName] = data;
  89153. }
  89154. removeObjectExtension(object, extensionName) {
  89155. const extensions = object.extensions || {};
  89156. const extension = extensions[extensionName];
  89157. delete extensions[extensionName];
  89158. return extension;
  89159. }
  89160. addExtension(extensionName, extensionData = {}) {
  89161. assert$1(extensionData);
  89162. this.json.extensions = this.json.extensions || {};
  89163. this.json.extensions[extensionName] = extensionData;
  89164. this.registerUsedExtension(extensionName);
  89165. return extensionData;
  89166. }
  89167. addRequiredExtension(extensionName, extensionData = {}) {
  89168. assert$1(extensionData);
  89169. this.addExtension(extensionName, extensionData);
  89170. this.registerRequiredExtension(extensionName);
  89171. return extensionData;
  89172. }
  89173. registerUsedExtension(extensionName) {
  89174. this.json.extensionsUsed = this.json.extensionsUsed || [];
  89175. if (!this.json.extensionsUsed.find(ext => ext === extensionName)) {
  89176. this.json.extensionsUsed.push(extensionName);
  89177. }
  89178. }
  89179. registerRequiredExtension(extensionName) {
  89180. this.registerUsedExtension(extensionName);
  89181. this.json.extensionsRequired = this.json.extensionsRequired || [];
  89182. if (!this.json.extensionsRequired.find(ext => ext === extensionName)) {
  89183. this.json.extensionsRequired.push(extensionName);
  89184. }
  89185. }
  89186. removeExtension(extensionName) {
  89187. if (this.json.extensionsRequired) {
  89188. this._removeStringFromArray(this.json.extensionsRequired, extensionName);
  89189. }
  89190. if (this.json.extensionsUsed) {
  89191. this._removeStringFromArray(this.json.extensionsUsed, extensionName);
  89192. }
  89193. if (this.json.extensions) {
  89194. delete this.json.extensions[extensionName];
  89195. }
  89196. }
  89197. setDefaultScene(sceneIndex) {
  89198. this.json.scene = sceneIndex;
  89199. }
  89200. addScene(scene) {
  89201. const {
  89202. nodeIndices
  89203. } = scene;
  89204. this.json.scenes = this.json.scenes || [];
  89205. this.json.scenes.push({
  89206. nodes: nodeIndices
  89207. });
  89208. return this.json.scenes.length - 1;
  89209. }
  89210. addNode(node) {
  89211. const {
  89212. meshIndex,
  89213. matrix
  89214. } = node;
  89215. this.json.nodes = this.json.nodes || [];
  89216. const nodeData = {
  89217. mesh: meshIndex
  89218. };
  89219. if (matrix) {
  89220. nodeData.matrix = matrix;
  89221. }
  89222. this.json.nodes.push(nodeData);
  89223. return this.json.nodes.length - 1;
  89224. }
  89225. addMesh(mesh) {
  89226. const {
  89227. attributes,
  89228. indices,
  89229. material,
  89230. mode = 4
  89231. } = mesh;
  89232. const accessors = this._addAttributes(attributes);
  89233. const glTFMesh = {
  89234. primitives: [{
  89235. attributes: accessors,
  89236. mode
  89237. }]
  89238. };
  89239. if (indices) {
  89240. const indicesAccessor = this._addIndices(indices);
  89241. glTFMesh.primitives[0].indices = indicesAccessor;
  89242. }
  89243. if (Number.isFinite(material)) {
  89244. glTFMesh.primitives[0].material = material;
  89245. }
  89246. this.json.meshes = this.json.meshes || [];
  89247. this.json.meshes.push(glTFMesh);
  89248. return this.json.meshes.length - 1;
  89249. }
  89250. addPointCloud(attributes) {
  89251. const accessorIndices = this._addAttributes(attributes);
  89252. const glTFMesh = {
  89253. primitives: [{
  89254. attributes: accessorIndices,
  89255. mode: 0
  89256. }]
  89257. };
  89258. this.json.meshes = this.json.meshes || [];
  89259. this.json.meshes.push(glTFMesh);
  89260. return this.json.meshes.length - 1;
  89261. }
  89262. addImage(imageData, mimeTypeOpt) {
  89263. const metadata = getBinaryImageMetadata(imageData);
  89264. const mimeType = mimeTypeOpt || (metadata === null || metadata === void 0 ? void 0 : metadata.mimeType);
  89265. const bufferViewIndex = this.addBufferView(imageData);
  89266. const glTFImage = {
  89267. bufferView: bufferViewIndex,
  89268. mimeType
  89269. };
  89270. this.json.images = this.json.images || [];
  89271. this.json.images.push(glTFImage);
  89272. return this.json.images.length - 1;
  89273. }
  89274. addBufferView(buffer) {
  89275. const byteLength = buffer.byteLength;
  89276. assert$1(Number.isFinite(byteLength));
  89277. this.sourceBuffers = this.sourceBuffers || [];
  89278. this.sourceBuffers.push(buffer);
  89279. const glTFBufferView = {
  89280. buffer: 0,
  89281. byteOffset: this.byteLength,
  89282. byteLength
  89283. };
  89284. this.byteLength += padToNBytes(byteLength, 4);
  89285. this.json.bufferViews = this.json.bufferViews || [];
  89286. this.json.bufferViews.push(glTFBufferView);
  89287. return this.json.bufferViews.length - 1;
  89288. }
  89289. addAccessor(bufferViewIndex, accessor) {
  89290. const glTFAccessor = {
  89291. bufferView: bufferViewIndex,
  89292. type: getAccessorTypeFromSize(accessor.size),
  89293. componentType: accessor.componentType,
  89294. count: accessor.count,
  89295. max: accessor.max,
  89296. min: accessor.min
  89297. };
  89298. this.json.accessors = this.json.accessors || [];
  89299. this.json.accessors.push(glTFAccessor);
  89300. return this.json.accessors.length - 1;
  89301. }
  89302. addBinaryBuffer(sourceBuffer, accessor = {
  89303. size: 3
  89304. }) {
  89305. const bufferViewIndex = this.addBufferView(sourceBuffer);
  89306. let minMax = {
  89307. min: accessor.min,
  89308. max: accessor.max
  89309. };
  89310. if (!minMax.min || !minMax.max) {
  89311. minMax = this._getAccessorMinMax(sourceBuffer, accessor.size);
  89312. }
  89313. const accessorDefaults = {
  89314. size: accessor.size,
  89315. componentType: getComponentTypeFromArray(sourceBuffer),
  89316. count: Math.round(sourceBuffer.length / accessor.size),
  89317. min: minMax.min,
  89318. max: minMax.max
  89319. };
  89320. return this.addAccessor(bufferViewIndex, Object.assign(accessorDefaults, accessor));
  89321. }
  89322. addTexture(texture) {
  89323. const {
  89324. imageIndex
  89325. } = texture;
  89326. const glTFTexture = {
  89327. source: imageIndex
  89328. };
  89329. this.json.textures = this.json.textures || [];
  89330. this.json.textures.push(glTFTexture);
  89331. return this.json.textures.length - 1;
  89332. }
  89333. addMaterial(pbrMaterialInfo) {
  89334. this.json.materials = this.json.materials || [];
  89335. this.json.materials.push(pbrMaterialInfo);
  89336. return this.json.materials.length - 1;
  89337. }
  89338. createBinaryChunk() {
  89339. var _this$json, _this$json$buffers;
  89340. this.gltf.buffers = [];
  89341. const totalByteLength = this.byteLength;
  89342. const arrayBuffer = new ArrayBuffer(totalByteLength);
  89343. const targetArray = new Uint8Array(arrayBuffer);
  89344. let dstByteOffset = 0;
  89345. for (const sourceBuffer of this.sourceBuffers || []) {
  89346. dstByteOffset = copyToArray(sourceBuffer, targetArray, dstByteOffset);
  89347. }
  89348. if ((_this$json = this.json) !== null && _this$json !== void 0 && (_this$json$buffers = _this$json.buffers) !== null && _this$json$buffers !== void 0 && _this$json$buffers[0]) {
  89349. this.json.buffers[0].byteLength = totalByteLength;
  89350. } else {
  89351. this.json.buffers = [{
  89352. byteLength: totalByteLength
  89353. }];
  89354. }
  89355. this.gltf.binary = arrayBuffer;
  89356. this.sourceBuffers = [arrayBuffer];
  89357. }
  89358. _removeStringFromArray(array, string) {
  89359. let found = true;
  89360. while (found) {
  89361. const index = array.indexOf(string);
  89362. if (index > -1) {
  89363. array.splice(index, 1);
  89364. } else {
  89365. found = false;
  89366. }
  89367. }
  89368. }
  89369. _addAttributes(attributes = {}) {
  89370. const result = {};
  89371. for (const attributeKey in attributes) {
  89372. const attributeData = attributes[attributeKey];
  89373. const attrName = this._getGltfAttributeName(attributeKey);
  89374. const accessor = this.addBinaryBuffer(attributeData.value, attributeData);
  89375. result[attrName] = accessor;
  89376. }
  89377. return result;
  89378. }
  89379. _addIndices(indices) {
  89380. return this.addBinaryBuffer(indices, {
  89381. size: 1
  89382. });
  89383. }
  89384. _getGltfAttributeName(attributeName) {
  89385. switch (attributeName.toLowerCase()) {
  89386. case 'position':
  89387. case 'positions':
  89388. case 'vertices':
  89389. return 'POSITION';
  89390. case 'normal':
  89391. case 'normals':
  89392. return 'NORMAL';
  89393. case 'color':
  89394. case 'colors':
  89395. return 'COLOR_0';
  89396. case 'texcoord':
  89397. case 'texcoords':
  89398. return 'TEXCOORD_0';
  89399. default:
  89400. return attributeName;
  89401. }
  89402. }
  89403. _getAccessorMinMax(buffer, size) {
  89404. const result = {
  89405. min: null,
  89406. max: null
  89407. };
  89408. if (buffer.length < size) {
  89409. return result;
  89410. }
  89411. result.min = [];
  89412. result.max = [];
  89413. const initValues = buffer.subarray(0, size);
  89414. for (const value of initValues) {
  89415. result.min.push(value);
  89416. result.max.push(value);
  89417. }
  89418. for (let index = size; index < buffer.length; index += size) {
  89419. for (let componentIndex = 0; componentIndex < size; componentIndex++) {
  89420. result.min[0 + componentIndex] = Math.min(result.min[0 + componentIndex], buffer[index + componentIndex]);
  89421. result.max[0 + componentIndex] = Math.max(result.max[0 + componentIndex], buffer[index + componentIndex]);
  89422. }
  89423. }
  89424. return result;
  89425. }
  89426. }
  89427. const isWebAssemblySupported = typeof WebAssembly !== 'object';
  89428. const wasm_base = 'B9h9z9tFBBBF8fL9gBB9gLaaaaaFa9gEaaaB9gFaFa9gEaaaFaEMcBFFFGGGEIIILF9wFFFLEFBFKNFaFCx/IFMO/LFVK9tv9t9vq95GBt9f9f939h9z9t9f9j9h9s9s9f9jW9vq9zBBp9tv9z9o9v9wW9f9kv9j9v9kv9WvqWv94h919m9mvqBF8Z9tv9z9o9v9wW9f9kv9j9v9kv9J9u9kv94h919m9mvqBGy9tv9z9o9v9wW9f9kv9j9v9kv9J9u9kv949TvZ91v9u9jvBEn9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9P9jWBIi9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9R919hWBLn9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9F949wBKI9z9iqlBOc+x8ycGBM/qQFTa8jUUUUBCU/EBlHL8kUUUUBC9+RKGXAGCFJAI9LQBCaRKAE2BBC+gF9HQBALAEAIJHOAGlAGTkUUUBRNCUoBAG9uC/wgBZHKCUGAKCUG9JyRVAECFJRICBRcGXEXAcAF9PQFAVAFAclAcAVJAF9JyRMGXGXAG9FQBAMCbJHKC9wZRSAKCIrCEJCGrRQANCUGJRfCBRbAIRTEXGXAOATlAQ9PQBCBRISEMATAQJRIGXAS9FQBCBRtCBREEXGXAOAIlCi9PQBCBRISLMANCU/CBJAEJRKGXGXGXGXGXATAECKrJ2BBAtCKZrCEZfIBFGEBMAKhB83EBAKCNJhB83EBSEMAKAI2BIAI2BBHmCKrHYAYCE6HYy86BBAKCFJAICIJAYJHY2BBAmCIrCEZHPAPCE6HPy86BBAKCGJAYAPJHY2BBAmCGrCEZHPAPCE6HPy86BBAKCEJAYAPJHY2BBAmCEZHmAmCE6Hmy86BBAKCIJAYAmJHY2BBAI2BFHmCKrHPAPCE6HPy86BBAKCLJAYAPJHY2BBAmCIrCEZHPAPCE6HPy86BBAKCKJAYAPJHY2BBAmCGrCEZHPAPCE6HPy86BBAKCOJAYAPJHY2BBAmCEZHmAmCE6Hmy86BBAKCNJAYAmJHY2BBAI2BGHmCKrHPAPCE6HPy86BBAKCVJAYAPJHY2BBAmCIrCEZHPAPCE6HPy86BBAKCcJAYAPJHY2BBAmCGrCEZHPAPCE6HPy86BBAKCMJAYAPJHY2BBAmCEZHmAmCE6Hmy86BBAKCSJAYAmJHm2BBAI2BEHICKrHYAYCE6HYy86BBAKCQJAmAYJHm2BBAICIrCEZHYAYCE6HYy86BBAKCfJAmAYJHm2BBAICGrCEZHYAYCE6HYy86BBAKCbJAmAYJHK2BBAICEZHIAICE6HIy86BBAKAIJRISGMAKAI2BNAI2BBHmCIrHYAYCb6HYy86BBAKCFJAICNJAYJHY2BBAmCbZHmAmCb6Hmy86BBAKCGJAYAmJHm2BBAI2BFHYCIrHPAPCb6HPy86BBAKCEJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCIJAmAYJHm2BBAI2BGHYCIrHPAPCb6HPy86BBAKCLJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCKJAmAYJHm2BBAI2BEHYCIrHPAPCb6HPy86BBAKCOJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCNJAmAYJHm2BBAI2BIHYCIrHPAPCb6HPy86BBAKCVJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCcJAmAYJHm2BBAI2BLHYCIrHPAPCb6HPy86BBAKCMJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCSJAmAYJHm2BBAI2BKHYCIrHPAPCb6HPy86BBAKCQJAmAPJHm2BBAYCbZHYAYCb6HYy86BBAKCfJAmAYJHm2BBAI2BOHICIrHYAYCb6HYy86BBAKCbJAmAYJHK2BBAICbZHIAICb6HIy86BBAKAIJRISFMAKAI8pBB83BBAKCNJAICNJ8pBB83BBAICTJRIMAtCGJRtAECTJHEAS9JQBMMGXAIQBCBRISEMGXAM9FQBANAbJ2BBRtCBRKAfREEXAEANCU/CBJAKJ2BBHTCFrCBATCFZl9zAtJHt86BBAEAGJREAKCFJHKAM9HQBMMAfCFJRfAIRTAbCFJHbAG9HQBMMABAcAG9sJANCUGJAMAG9sTkUUUBpANANCUGJAMCaJAG9sJAGTkUUUBpMAMCBAIyAcJRcAIQBMC9+RKSFMCBC99AOAIlAGCAAGCA9Ly6yRKMALCU/EBJ8kUUUUBAKM+OmFTa8jUUUUBCoFlHL8kUUUUBC9+RKGXAFCE9uHOCtJAI9LQBCaRKAE2BBHNC/wFZC/gF9HQBANCbZHVCF9LQBALCoBJCgFCUFT+JUUUBpALC84Jha83EBALC8wJha83EBALC8oJha83EBALCAJha83EBALCiJha83EBALCTJha83EBALha83ENALha83EBAEAIJC9wJRcAECFJHNAOJRMGXAF9FQBCQCbAVCF6yRSABRECBRVCBRQCBRfCBRICBRKEXGXAMAcuQBC9+RKSEMGXGXAN2BBHOC/vF9LQBALCoBJAOCIrCa9zAKJCbZCEWJHb8oGIRTAb8oGBRtGXAOCbZHbAS9PQBALAOCa9zAIJCbZCGWJ8oGBAVAbyROAb9FRbGXGXAGCG9HQBABAt87FBABCIJAO87FBABCGJAT87FBSFMAEAtjGBAECNJAOjGBAECIJATjGBMAVAbJRVALCoBJAKCEWJHmAOjGBAmATjGIALAICGWJAOjGBALCoBJAKCFJCbZHKCEWJHTAtjGBATAOjGIAIAbJRIAKCFJRKSGMGXGXAbCb6QBAQAbJAbC989zJCFJRQSFMAM1BBHbCgFZROGXGXAbCa9MQBAMCFJRMSFMAM1BFHbCgBZCOWAOCgBZqROGXAbCa9MQBAMCGJRMSFMAM1BGHbCgBZCfWAOqROGXAbCa9MQBAMCEJRMSFMAM1BEHbCgBZCdWAOqROGXAbCa9MQBAMCIJRMSFMAM2BIC8cWAOqROAMCLJRMMAOCFrCBAOCFZl9zAQJRQMGXGXAGCG9HQBABAt87FBABCIJAQ87FBABCGJAT87FBSFMAEAtjGBAECNJAQjGBAECIJATjGBMALCoBJAKCEWJHOAQjGBAOATjGIALAICGWJAQjGBALCoBJAKCFJCbZHKCEWJHOAtjGBAOAQjGIAICFJRIAKCFJRKSFMGXAOCDF9LQBALAIAcAOCbZJ2BBHbCIrHTlCbZCGWJ8oGBAVCFJHtATyROALAIAblCbZCGWJ8oGBAtAT9FHmJHtAbCbZHTyRbAT9FRTGXGXAGCG9HQBABAV87FBABCIJAb87FBABCGJAO87FBSFMAEAVjGBAECNJAbjGBAECIJAOjGBMALAICGWJAVjGBALCoBJAKCEWJHYAOjGBAYAVjGIALAICFJHICbZCGWJAOjGBALCoBJAKCFJCbZCEWJHYAbjGBAYAOjGIALAIAmJCbZHICGWJAbjGBALCoBJAKCGJCbZHKCEWJHOAVjGBAOAbjGIAKCFJRKAIATJRIAtATJRVSFMAVCBAM2BBHYyHTAOC/+F6HPJROAYCbZRtGXGXAYCIrHmQBAOCFJRbSFMAORbALAIAmlCbZCGWJ8oGBROMGXGXAtQBAbCFJRVSFMAbRVALAIAYlCbZCGWJ8oGBRbMGXGXAP9FQBAMCFJRYSFMAM1BFHYCgFZRTGXGXAYCa9MQBAMCGJRYSFMAM1BGHYCgBZCOWATCgBZqRTGXAYCa9MQBAMCEJRYSFMAM1BEHYCgBZCfWATqRTGXAYCa9MQBAMCIJRYSFMAM1BIHYCgBZCdWATqRTGXAYCa9MQBAMCLJRYSFMAMCKJRYAM2BLC8cWATqRTMATCFrCBATCFZl9zAQJHQRTMGXGXAmCb6QBAYRPSFMAY1BBHMCgFZROGXGXAMCa9MQBAYCFJRPSFMAY1BFHMCgBZCOWAOCgBZqROGXAMCa9MQBAYCGJRPSFMAY1BGHMCgBZCfWAOqROGXAMCa9MQBAYCEJRPSFMAY1BEHMCgBZCdWAOqROGXAMCa9MQBAYCIJRPSFMAYCLJRPAY2BIC8cWAOqROMAOCFrCBAOCFZl9zAQJHQROMGXGXAtCb6QBAPRMSFMAP1BBHMCgFZRbGXGXAMCa9MQBAPCFJRMSFMAP1BFHMCgBZCOWAbCgBZqRbGXAMCa9MQBAPCGJRMSFMAP1BGHMCgBZCfWAbqRbGXAMCa9MQBAPCEJRMSFMAP1BEHMCgBZCdWAbqRbGXAMCa9MQBAPCIJRMSFMAPCLJRMAP2BIC8cWAbqRbMAbCFrCBAbCFZl9zAQJHQRbMGXGXAGCG9HQBABAT87FBABCIJAb87FBABCGJAO87FBSFMAEATjGBAECNJAbjGBAECIJAOjGBMALCoBJAKCEWJHYAOjGBAYATjGIALAICGWJATjGBALCoBJAKCFJCbZCEWJHYAbjGBAYAOjGIALAICFJHICbZCGWJAOjGBALCoBJAKCGJCbZCEWJHOATjGBAOAbjGIALAIAm9FAmCb6qJHICbZCGWJAbjGBAIAt9FAtCb6qJRIAKCEJRKMANCFJRNABCKJRBAECSJREAKCbZRKAICbZRIAfCEJHfAF9JQBMMCBC99AMAc6yRKMALCoFJ8kUUUUBAKM/tIFGa8jUUUUBCTlRLC9+RKGXAFCLJAI9LQBCaRKAE2BBC/+FZC/QF9HQBALhB83ENAECFJRKAEAIJC98JREGXAF9FQBGXAGCG6QBEXGXAKAE9JQBC9+bMAK1BBHGCgFZRIGXGXAGCa9MQBAKCFJRKSFMAK1BFHGCgBZCOWAICgBZqRIGXAGCa9MQBAKCGJRKSFMAK1BGHGCgBZCfWAIqRIGXAGCa9MQBAKCEJRKSFMAK1BEHGCgBZCdWAIqRIGXAGCa9MQBAKCIJRKSFMAK2BIC8cWAIqRIAKCLJRKMALCNJAICFZCGWqHGAICGrCBAICFrCFZl9zAG8oGBJHIjGBABAIjGBABCIJRBAFCaJHFQBSGMMEXGXAKAE9JQBC9+bMAK1BBHGCgFZRIGXGXAGCa9MQBAKCFJRKSFMAK1BFHGCgBZCOWAICgBZqRIGXAGCa9MQBAKCGJRKSFMAK1BGHGCgBZCfWAIqRIGXAGCa9MQBAKCEJRKSFMAK1BEHGCgBZCdWAIqRIGXAGCa9MQBAKCIJRKSFMAK2BIC8cWAIqRIAKCLJRKMABAICGrCBAICFrCFZl9zALCNJAICFZCGWqHI8oGBJHG87FBAIAGjGBABCGJRBAFCaJHFQBMMCBC99AKAE6yRKMAKM+lLKFaF99GaG99FaG99GXGXAGCI9HQBAF9FQFEXGXGX9DBBB8/9DBBB+/ABCGJHG1BB+yAB1BBHE+yHI+L+TABCFJHL1BBHK+yHO+L+THN9DBBBB9gHVyAN9DBB/+hANAN+U9DBBBBANAVyHcAc+MHMAECa3yAI+SHIAI+UAcAMAKCa3yAO+SHcAc+U+S+S+R+VHO+U+SHN+L9DBBB9P9d9FQBAN+oRESFMCUUUU94REMAGAE86BBGXGX9DBBB8/9DBBB+/Ac9DBBBB9gyAcAO+U+SHN+L9DBBB9P9d9FQBAN+oRGSFMCUUUU94RGMALAG86BBGXGX9DBBB8/9DBBB+/AI9DBBBB9gyAIAO+U+SHN+L9DBBB9P9d9FQBAN+oRGSFMCUUUU94RGMABAG86BBABCIJRBAFCaJHFQBSGMMAF9FQBEXGXGX9DBBB8/9DBBB+/ABCIJHG8uFB+yAB8uFBHE+yHI+L+TABCGJHL8uFBHK+yHO+L+THN9DBBBB9gHVyAN9DB/+g6ANAN+U9DBBBBANAVyHcAc+MHMAECa3yAI+SHIAI+UAcAMAKCa3yAO+SHcAc+U+S+S+R+VHO+U+SHN+L9DBBB9P9d9FQBAN+oRESFMCUUUU94REMAGAE87FBGXGX9DBBB8/9DBBB+/Ac9DBBBB9gyAcAO+U+SHN+L9DBBB9P9d9FQBAN+oRGSFMCUUUU94RGMALAG87FBGXGX9DBBB8/9DBBB+/AI9DBBBB9gyAIAO+U+SHN+L9DBBB9P9d9FQBAN+oRGSFMCUUUU94RGMABAG87FBABCNJRBAFCaJHFQBMMM/SEIEaE99EaF99GXAF9FQBCBREABRIEXGXGX9D/zI818/AICKJ8uFBHLCEq+y+VHKAI8uFB+y+UHO9DB/+g6+U9DBBB8/9DBBB+/AO9DBBBB9gy+SHN+L9DBBB9P9d9FQBAN+oRVSFMCUUUU94RVMAICIJ8uFBRcAICGJ8uFBRMABALCFJCEZAEqCFWJAV87FBGXGXAKAM+y+UHN9DB/+g6+U9DBBB8/9DBBB+/AN9DBBBB9gy+SHS+L9DBBB9P9d9FQBAS+oRMSFMCUUUU94RMMABALCGJCEZAEqCFWJAM87FBGXGXAKAc+y+UHK9DB/+g6+U9DBBB8/9DBBB+/AK9DBBBB9gy+SHS+L9DBBB9P9d9FQBAS+oRcSFMCUUUU94RcMABALCaJCEZAEqCFWJAc87FBGXGX9DBBU8/AOAO+U+TANAN+U+TAKAK+U+THO9DBBBBAO9DBBBB9gy+R9DB/+g6+U9DBBB8/+SHO+L9DBBB9P9d9FQBAO+oRcSFMCUUUU94RcMABALCEZAEqCFWJAc87FBAICNJRIAECIJREAFCaJHFQBMMM9JBGXAGCGrAF9sHF9FQBEXABAB8oGBHGCNWCN91+yAGCi91CnWCUUU/8EJ+++U84GBABCIJRBAFCaJHFQBMMM9TFEaCBCB8oGUkUUBHFABCEJC98ZJHBjGUkUUBGXGXAB8/BCTWHGuQBCaREABAGlCggEJCTrXBCa6QFMAFREMAEM/lFFFaGXGXAFABqCEZ9FQBABRESFMGXGXAGCT9PQBABRESFMABREEXAEAF8oGBjGBAECIJAFCIJ8oGBjGBAECNJAFCNJ8oGBjGBAECSJAFCSJ8oGBjGBAECTJREAFCTJRFAGC9wJHGCb9LQBMMAGCI9JQBEXAEAF8oGBjGBAFCIJRFAECIJREAGC98JHGCE9LQBMMGXAG9FQBEXAEAF2BB86BBAECFJREAFCFJRFAGCaJHGQBMMABMoFFGaGXGXABCEZ9FQBABRESFMAFCgFZC+BwsN9sRIGXGXAGCT9PQBABRESFMABREEXAEAIjGBAECSJAIjGBAECNJAIjGBAECIJAIjGBAECTJREAGC9wJHGCb9LQBMMAGCI9JQBEXAEAIjGBAECIJREAGC98JHGCE9LQBMMGXAG9FQBEXAEAF86BBAECFJREAGCaJHGQBMMABMMMFBCUNMIT9kBB';
  89429. const wasm_simd = 'B9h9z9tFBBBF8dL9gBB9gLaaaaaFa9gEaaaB9gGaaB9gFaFaEQSBBFBFFGEGEGIILF9wFFFLEFBFKNFaFCx/aFMO/LFVK9tv9t9vq95GBt9f9f939h9z9t9f9j9h9s9s9f9jW9vq9zBBp9tv9z9o9v9wW9f9kv9j9v9kv9WvqWv94h919m9mvqBG8Z9tv9z9o9v9wW9f9kv9j9v9kv9J9u9kv94h919m9mvqBIy9tv9z9o9v9wW9f9kv9j9v9kv9J9u9kv949TvZ91v9u9jvBLn9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9P9jWBKi9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9R919hWBNn9tv9z9o9v9wW9f9kv9j9v9kv69p9sWvq9F949wBcI9z9iqlBMc/j9JSIBTEM9+FLa8jUUUUBCTlRBCBRFEXCBRGCBREEXABCNJAGJAECUaAFAGrCFZHIy86BBAEAIJREAGCFJHGCN9HQBMAFCx+YUUBJAE86BBAFCEWCxkUUBJAB8pEN83EBAFCFJHFCUG9HQBMMkRIbaG97FaK978jUUUUBCU/KBlHL8kUUUUBC9+RKGXAGCFJAI9LQBCaRKAE2BBC+gF9HQBALAEAIJHOAGlAG/8cBBCUoBAG9uC/wgBZHKCUGAKCUG9JyRNAECFJRKCBRVGXEXAVAF9PQFANAFAVlAVANJAF9JyRcGXGXAG9FQBAcCbJHIC9wZHMCE9sRSAMCFWRQAICIrCEJCGrRfCBRbEXAKRTCBRtGXEXGXAOATlAf9PQBCBRKSLMALCU/CBJAtAM9sJRmATAfJRKCBREGXAMCoB9JQBAOAKlC/gB9JQBCBRIEXAmAIJREGXGXGXGXGXATAICKrJ2BBHYCEZfIBFGEBMAECBDtDMIBSEMAEAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBAeCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIBAKCIJAnDeBJAeCx+YUUBJ2BBJRKSGMAEAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBAeCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIBAKCNJAnDeBJAeCx+YUUBJ2BBJRKSFMAEAKDBBBDMIBAKCTJRKMGXGXGXGXGXAYCGrCEZfIBFGEBMAECBDtDMITSEMAEAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBAeCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMITAKCIJAnDeBJAeCx+YUUBJ2BBJRKSGMAEAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBAeCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMITAKCNJAnDeBJAeCx+YUUBJ2BBJRKSFMAEAKDBBBDMITAKCTJRKMGXGXGXGXGXAYCIrCEZfIBFGEBMAECBDtDMIASEMAEAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBAeCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIAAKCIJAnDeBJAeCx+YUUBJ2BBJRKSGMAEAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBAeCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIAAKCNJAnDeBJAeCx+YUUBJ2BBJRKSFMAEAKDBBBDMIAAKCTJRKMGXGXGXGXGXAYCKrfIBFGEBMAECBDtDMI8wSEMAEAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HYCEWCxkUUBJDBEBAYCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HYCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMI8wAKCIJAnDeBJAYCx+YUUBJ2BBJRKSGMAEAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HYCEWCxkUUBJDBEBAYCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HYCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMI8wAKCNJAnDeBJAYCx+YUUBJ2BBJRKSFMAEAKDBBBDMI8wAKCTJRKMAICoBJREAICUFJAM9LQFAERIAOAKlC/fB9LQBMMGXAEAM9PQBAECErRIEXGXAOAKlCi9PQBCBRKSOMAmAEJRYGXGXGXGXGXATAECKrJ2BBAICKZrCEZfIBFGEBMAYCBDtDMIBSEMAYAKDBBIAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnHPCGD+MFAPDQBTFtGmEYIPLdKeOnC0+G+MiDtD9OHdCEDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBAeCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIBAKCIJAnDeBJAeCx+YUUBJ2BBJRKSGMAYAKDBBNAKDBBBHPCID+MFAPDQBTFtGmEYIPLdKeOnC+P+e+8/4BDtD9OHdCbDbD8jHPD8dBhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBAeCx+YUUBJDBBBHnAnDQBBBBBBBBBBBBBBBBAPD8dFhUg/8/4/w/goB9+h84k7HeCEWCxkUUBJDBEBD9uDQBFGEILKOTtmYPdenDfAdAPD9SDMIBAKCNJAnDeBJAeCx+YUUBJ2BBJRKSFMAYAKDBBBDMIBAKCTJRKMAICGJRIAECTJHEAM9JQBMMGXAK9FQBAKRTAtCFJHtCI6QGSFMMCBRKSEMGXAM9FQBALCUGJAbJREALAbJDBGBRnCBRYEXAEALCU/CBJAYJHIDBIBHdCFD9tAdCFDbHPD9OD9hD9RHdAIAMJDBIBHiCFD9tAiAPD9OD9hD9RHiDQBTFtGmEYIPLdKeOnH8ZAIAQJDBIBHpCFD9tApAPD9OD9hD9RHpAIASJDBIBHyCFD9tAyAPD9OD9hD9RHyDQBTFtGmEYIPLdKeOnH8cDQBFTtGEmYILPdKOenHPAPDQBFGEBFGEBFGEBFGEAnD9uHnDyBjGBAEAGJHIAnAPAPDQILKOILKOILKOILKOD9uHnDyBjGBAIAGJHIAnAPAPDQNVcMNVcMNVcMNVcMD9uHnDyBjGBAIAGJHIAnAPAPDQSQfbSQfbSQfbSQfbD9uHnDyBjGBAIAGJHIAnA8ZA8cDQNVi8ZcMpySQ8c8dfb8e8fHPAPDQBFGEBFGEBFGEBFGED9uHnDyBjGBAIAGJHIAnAPAPDQILKOILKOILKOILKOD9uHnDyBjGBAIAGJHIAnAPAPDQNVcMNVcMNVcMNVcMD9uHnDyBjGBAIAGJHIAnAPAPDQSQfbSQfbSQfbSQfbD9uHnDyBjGBAIAGJHIAnAdAiDQNiV8ZcpMyS8cQ8df8eb8fHdApAyDQNiV8ZcpMyS8cQ8df8eb8fHiDQBFTtGEmYILPdKOenHPAPDQBFGEBFGEBFGEBFGED9uHnDyBjGBAIAGJHIAnAPAPDQILKOILKOILKOILKOD9uHnDyBjGBAIAGJHIAnAPAPDQNVcMNVcMNVcMNVcMD9uHnDyBjGBAIAGJHIAnAPAPDQSQfbSQfbSQfbSQfbD9uHnDyBjGBAIAGJHIAnAdAiDQNVi8ZcMpySQ8c8dfb8e8fHPAPDQBFGEBFGEBFGEBFGED9uHnDyBjGBAIAGJHIAnAPAPDQILKOILKOILKOILKOD9uHnDyBjGBAIAGJHIAnAPAPDQNVcMNVcMNVcMNVcMD9uHnDyBjGBAIAGJHIAnAPAPDQSQfbSQfbSQfbSQfbD9uHnDyBjGBAIAGJREAYCTJHYAM9JQBMMAbCIJHbAG9JQBMMABAVAG9sJALCUGJAcAG9s/8cBBALALCUGJAcCaJAG9sJAG/8cBBMAcCBAKyAVJRVAKQBMC9+RKSFMCBC99AOAKlAGCAAGCA9Ly6yRKMALCU/KBJ8kUUUUBAKMNBT+BUUUBM+KmFTa8jUUUUBCoFlHL8kUUUUBC9+RKGXAFCE9uHOCtJAI9LQBCaRKAE2BBHNC/wFZC/gF9HQBANCbZHVCF9LQBALCoBJCgFCUF/8MBALC84Jha83EBALC8wJha83EBALC8oJha83EBALCAJha83EBALCiJha83EBALCTJha83EBALha83ENALha83EBAEAIJC9wJRcAECFJHNAOJRMGXAF9FQBCQCbAVCF6yRSABRECBRVCBRQCBRfCBRICBRKEXGXAMAcuQBC9+RKSEMGXGXAN2BBHOC/vF9LQBALCoBJAOCIrCa9zAKJCbZCEWJHb8oGIRTAb8oGBRtGXAOCbZHbAS9PQBALAOCa9zAIJCbZCGWJ8oGBAVAbyROAb9FRbGXGXAGCG9HQBABAt87FBABCIJAO87FBABCGJAT87FBSFMAEAtjGBAECNJAOjGBAECIJATjGBMAVAbJRVALCoBJAKCEWJHmAOjGBAmATjGIALAICGWJAOjGBALCoBJAKCFJCbZHKCEWJHTAtjGBATAOjGIAIAbJRIAKCFJRKSGMGXGXAbCb6QBAQAbJAbC989zJCFJRQSFMAM1BBHbCgFZROGXGXAbCa9MQBAMCFJRMSFMAM1BFHbCgBZCOWAOCgBZqROGXAbCa9MQBAMCGJRMSFMAM1BGHbCgBZCfWAOqROGXAbCa9MQBAMCEJRMSFMAM1BEHbCgBZCdWAOqROGXAbCa9MQBAMCIJRMSFMAM2BIC8cWAOqROAMCLJRMMAOCFrCBAOCFZl9zAQJRQMGXGXAGCG9HQBABAt87FBABCIJAQ87FBABCGJAT87FBSFMAEAtjGBAECNJAQjGBAECIJATjGBMALCoBJAKCEWJHOAQjGBAOATjGIALAICGWJAQjGBALCoBJAKCFJCbZHKCEWJHOAtjGBAOAQjGIAICFJRIAKCFJRKSFMGXAOCDF9LQBALAIAcAOCbZJ2BBHbCIrHTlCbZCGWJ8oGBAVCFJHtATyROALAIAblCbZCGWJ8oGBAtAT9FHmJHtAbCbZHTyRbAT9FRTGXGXAGCG9HQBABAV87FBABCIJAb87FBABCGJAO87FBSFMAEAVjGBAECNJAbjGBAECIJAOjGBMALAICGWJAVjGBALCoBJAKCEWJHYAOjGBAYAVjGIALAICFJHICbZCGWJAOjGBALCoBJAKCFJCbZCEWJHYAbjGBAYAOjGIALAIAmJCbZHICGWJAbjGBALCoBJAKCGJCbZHKCEWJHOAVjGBAOAbjGIAKCFJRKAIATJRIAtATJRVSFMAVCBAM2BBHYyHTAOC/+F6HPJROAYCbZRtGXGXAYCIrHmQBAOCFJRbSFMAORbALAIAmlCbZCGWJ8oGBROMGXGXAtQBAbCFJRVSFMAbRVALAIAYlCbZCGWJ8oGBRbMGXGXAP9FQBAMCFJRYSFMAM1BFHYCgFZRTGXGXAYCa9MQBAMCGJRYSFMAM1BGHYCgBZCOWATCgBZqRTGXAYCa9MQBAMCEJRYSFMAM1BEHYCgBZCfWATqRTGXAYCa9MQBAMCIJRYSFMAM1BIHYCgBZCdWATqRTGXAYCa9MQBAMCLJRYSFMAMCKJRYAM2BLC8cWATqRTMATCFrCBATCFZl9zAQJHQRTMGXGXAmCb6QBAYRPSFMAY1BBHMCgFZROGXGXAMCa9MQBAYCFJRPSFMAY1BFHMCgBZCOWAOCgBZqROGXAMCa9MQBAYCGJRPSFMAY1BGHMCgBZCfWAOqROGXAMCa9MQBAYCEJRPSFMAY1BEHMCgBZCdWAOqROGXAMCa9MQBAYCIJRPSFMAYCLJRPAY2BIC8cWAOqROMAOCFrCBAOCFZl9zAQJHQROMGXGXAtCb6QBAPRMSFMAP1BBHMCgFZRbGXGXAMCa9MQBAPCFJRMSFMAP1BFHMCgBZCOWAbCgBZqRbGXAMCa9MQBAPCGJRMSFMAP1BGHMCgBZCfWAbqRbGXAMCa9MQBAPCEJRMSFMAP1BEHMCgBZCdWAbqRbGXAMCa9MQBAPCIJRMSFMAPCLJRMAP2BIC8cWAbqRbMAbCFrCBAbCFZl9zAQJHQRbMGXGXAGCG9HQBABAT87FBABCIJAb87FBABCGJAO87FBSFMAEATjGBAECNJAbjGBAECIJAOjGBMALCoBJAKCEWJHYAOjGBAYATjGIALAICGWJATjGBALCoBJAKCFJCbZCEWJHYAbjGBAYAOjGIALAICFJHICbZCGWJAOjGBALCoBJAKCGJCbZCEWJHOATjGBAOAbjGIALAIAm9FAmCb6qJHICbZCGWJAbjGBAIAt9FAtCb6qJRIAKCEJRKMANCFJRNABCKJRBAECSJREAKCbZRKAICbZRIAfCEJHfAF9JQBMMCBC99AMAc6yRKMALCoFJ8kUUUUBAKM/tIFGa8jUUUUBCTlRLC9+RKGXAFCLJAI9LQBCaRKAE2BBC/+FZC/QF9HQBALhB83ENAECFJRKAEAIJC98JREGXAF9FQBGXAGCG6QBEXGXAKAE9JQBC9+bMAK1BBHGCgFZRIGXGXAGCa9MQBAKCFJRKSFMAK1BFHGCgBZCOWAICgBZqRIGXAGCa9MQBAKCGJRKSFMAK1BGHGCgBZCfWAIqRIGXAGCa9MQBAKCEJRKSFMAK1BEHGCgBZCdWAIqRIGXAGCa9MQBAKCIJRKSFMAK2BIC8cWAIqRIAKCLJRKMALCNJAICFZCGWqHGAICGrCBAICFrCFZl9zAG8oGBJHIjGBABAIjGBABCIJRBAFCaJHFQBSGMMEXGXAKAE9JQBC9+bMAK1BBHGCgFZRIGXGXAGCa9MQBAKCFJRKSFMAK1BFHGCgBZCOWAICgBZqRIGXAGCa9MQBAKCGJRKSFMAK1BGHGCgBZCfWAIqRIGXAGCa9MQBAKCEJRKSFMAK1BEHGCgBZCdWAIqRIGXAGCa9MQBAKCIJRKSFMAK2BIC8cWAIqRIAKCLJRKMABAICGrCBAICFrCFZl9zALCNJAICFZCGWqHI8oGBJHG87FBAIAGjGBABCGJRBAFCaJHFQBMMCBC99AKAE6yRKMAKM/xLGEaK978jUUUUBCAlHE8kUUUUBGXGXAGCI9HQBGXAFC98ZHI9FQBABRGCBRLEXAGAGDBBBHKCiD+rFCiD+sFD/6FHOAKCND+rFCiD+sFD/6FAOD/gFAKCTD+rFCiD+sFD/6FHND/gFD/kFD/lFHVCBDtD+2FHcAOCUUUU94DtHMD9OD9RD/kFHO9DBB/+hDYAOAOD/mFAVAVD/mFANAcANAMD9OD9RD/kFHOAOD/mFD/kFD/kFD/jFD/nFHND/mF9DBBX9LDYHcD/kFCgFDtD9OAKCUUU94DtD9OD9QAOAND/mFAcD/kFCND+rFCU/+EDtD9OD9QAVAND/mFAcD/kFCTD+rFCUU/8ODtD9OD9QDMBBAGCTJRGALCIJHLAI9JQBMMAIAF9PQFAEAFCEZHLCGWHGqCBCTAGl/8MBAEABAICGWJHIAG/8cBBGXAL9FQBAEAEDBIBHKCiD+rFCiD+sFD/6FHOAKCND+rFCiD+sFD/6FAOD/gFAKCTD+rFCiD+sFD/6FHND/gFD/kFD/lFHVCBDtD+2FHcAOCUUUU94DtHMD9OD9RD/kFHO9DBB/+hDYAOAOD/mFAVAVD/mFANAcANAMD9OD9RD/kFHOAOD/mFD/kFD/kFD/jFD/nFHND/mF9DBBX9LDYHcD/kFCgFDtD9OAKCUUU94DtD9OD9QAOAND/mFAcD/kFCND+rFCU/+EDtD9OD9QAVAND/mFAcD/kFCTD+rFCUU/8ODtD9OD9QDMIBMAIAEAG/8cBBSFMABAFC98ZHGT+HUUUBAGAF9PQBAEAFCEZHICEWHLJCBCAALl/8MBAEABAGCEWJHGAL/8cBBAEAIT+HUUUBAGAEAL/8cBBMAECAJ8kUUUUBM+yEGGaO97GXAF9FQBCBRGEXABCTJHEAEDBBBHICBDtHLCUU98D8cFCUU98D8cEHKD9OABDBBBHOAIDQILKOSQfbPden8c8d8e8fCggFDtD9OD/6FAOAIDQBFGENVcMTtmYi8ZpyHICTD+sFD/6FHND/gFAICTD+rFCTD+sFD/6FHVD/gFD/kFD/lFHI9DB/+g6DYAVAIALD+2FHLAVCUUUU94DtHcD9OD9RD/kFHVAVD/mFAIAID/mFANALANAcD9OD9RD/kFHIAID/mFD/kFD/kFD/jFD/nFHND/mF9DBBX9LDYHLD/kFCTD+rFAVAND/mFALD/kFCggEDtD9OD9QHVAIAND/mFALD/kFCaDbCBDnGCBDnECBDnKCBDnOCBDncCBDnMCBDnfCBDnbD9OHIDQNVi8ZcMpySQ8c8dfb8e8fD9QDMBBABAOAKD9OAVAIDQBFTtGEmYILPdKOenD9QDMBBABCAJRBAGCIJHGAF9JQBMMM94FEa8jUUUUBCAlHE8kUUUUBABAFC98ZHIT+JUUUBGXAIAF9PQBAEAFCEZHLCEWHFJCBCAAFl/8MBAEABAICEWJHBAF/8cBBAEALT+JUUUBABAEAF/8cBBMAECAJ8kUUUUBM/hEIGaF97FaL978jUUUUBCTlRGGXAF9FQBCBREEXAGABDBBBHIABCTJHLDBBBHKDQILKOSQfbPden8c8d8e8fHOCTD+sFHNCID+rFDMIBAB9DBBU8/DY9D/zI818/DYANCEDtD9QD/6FD/nFHNAIAKDQBFGENVcMTtmYi8ZpyHICTD+rFCTD+sFD/6FD/mFHKAKD/mFANAICTD+sFD/6FD/mFHVAVD/mFANAOCTD+rFCTD+sFD/6FD/mFHOAOD/mFD/kFD/kFD/lFCBDtD+4FD/jF9DB/+g6DYHND/mF9DBBX9LDYHID/kFCggEDtHcD9OAVAND/mFAID/kFCTD+rFD9QHVAOAND/mFAID/kFCTD+rFAKAND/mFAID/kFAcD9OD9QHNDQBFTtGEmYILPdKOenHID8dBAGDBIBDyB+t+J83EBABCNJAID8dFAGDBIBDyF+t+J83EBALAVANDQNVi8ZcMpySQ8c8dfb8e8fHND8dBAGDBIBDyG+t+J83EBABCiJAND8dFAGDBIBDyE+t+J83EBABCAJRBAECIJHEAF9JQBMMM/3FGEaF978jUUUUBCoBlREGXAGCGrAF9sHIC98ZHL9FQBCBRGABRFEXAFAFDBBBHKCND+rFCND+sFD/6FAKCiD+sFCnD+rFCUUU/8EDtD+uFD/mFDMBBAFCTJRFAGCIJHGAL9JQBMMGXALAI9PQBAEAICEZHGCGWHFqCBCoBAFl/8MBAEABALCGWJHLAF/8cBBGXAG9FQBAEAEDBIBHKCND+rFCND+sFD/6FAKCiD+sFCnD+rFCUUU/8EDtD+uFD/mFDMIBMALAEAF/8cBBMM9TFEaCBCB8oGUkUUBHFABCEJC98ZJHBjGUkUUBGXGXAB8/BCTWHGuQBCaREABAGlCggEJCTrXBCa6QFMAFREMAEMMMFBCUNMIT9tBB';
  89430. const detector = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 3, 2, 0, 0, 5, 3, 1, 0, 1, 12, 1, 0, 10, 22, 2, 12, 0, 65, 0, 65, 0, 65, 0, 252, 10, 0, 0, 11, 7, 0, 65, 0, 253, 15, 26, 11]);
  89431. const wasmpack = new Uint8Array([32, 0, 65, 253, 3, 1, 2, 34, 4, 106, 6, 5, 11, 8, 7, 20, 13, 33, 12, 16, 128, 9, 116, 64, 19, 113, 127, 15, 10, 21, 22, 14, 255, 66, 24, 54, 136, 107, 18, 23, 192, 26, 114, 118, 132, 17, 77, 101, 130, 144, 27, 87, 131, 44, 45, 74, 156, 154, 70, 167]);
  89432. const FILTERS = {
  89433. 0: '',
  89434. 1: 'meshopt_decodeFilterOct',
  89435. 2: 'meshopt_decodeFilterQuat',
  89436. 3: 'meshopt_decodeFilterExp',
  89437. NONE: '',
  89438. OCTAHEDRAL: 'meshopt_decodeFilterOct',
  89439. QUATERNION: 'meshopt_decodeFilterQuat',
  89440. EXPONENTIAL: 'meshopt_decodeFilterExp'
  89441. };
  89442. const DECODERS = {
  89443. 0: 'meshopt_decodeVertexBuffer',
  89444. 1: 'meshopt_decodeIndexBuffer',
  89445. 2: 'meshopt_decodeIndexSequence',
  89446. ATTRIBUTES: 'meshopt_decodeVertexBuffer',
  89447. TRIANGLES: 'meshopt_decodeIndexBuffer',
  89448. INDICES: 'meshopt_decodeIndexSequence'
  89449. };
  89450. function isMeshoptSupported() {
  89451. return isWebAssemblySupported;
  89452. }
  89453. async function meshoptDecodeGltfBuffer(target, count, size, source, mode, filter = 'NONE') {
  89454. const instance = await loadWasmInstance();
  89455. decode$5(instance, instance.exports[DECODERS[mode]], target, count, size, source, instance.exports[FILTERS[filter || 'NONE']]);
  89456. }
  89457. let wasmPromise;
  89458. async function loadWasmInstance() {
  89459. if (!wasmPromise) {
  89460. wasmPromise = loadWasmModule();
  89461. }
  89462. return wasmPromise;
  89463. }
  89464. async function loadWasmModule() {
  89465. let wasm = wasm_base;
  89466. if (WebAssembly.validate(detector)) {
  89467. wasm = wasm_simd;
  89468. console.log('Warning: meshopt_decoder is using experimental SIMD support');
  89469. }
  89470. const result = await WebAssembly.instantiate(unpack(wasm), {});
  89471. await result.instance.exports.__wasm_call_ctors();
  89472. return result.instance;
  89473. }
  89474. function unpack(data) {
  89475. const result = new Uint8Array(data.length);
  89476. for (let i = 0; i < data.length; ++i) {
  89477. const ch = data.charCodeAt(i);
  89478. result[i] = ch > 96 ? ch - 71 : ch > 64 ? ch - 65 : ch > 47 ? ch + 4 : ch > 46 ? 63 : 62;
  89479. }
  89480. let write = 0;
  89481. for (let i = 0; i < data.length; ++i) {
  89482. result[write++] = result[i] < 60 ? wasmpack[result[i]] : (result[i] - 60) * 64 + result[++i];
  89483. }
  89484. return result.buffer.slice(0, write);
  89485. }
  89486. function decode$5(instance, fun, target, count, size, source, filter) {
  89487. const sbrk = instance.exports.sbrk;
  89488. const count4 = count + 3 & ~3;
  89489. const tp = sbrk(count4 * size);
  89490. const sp = sbrk(source.length);
  89491. const heap = new Uint8Array(instance.exports.memory.buffer);
  89492. heap.set(source, sp);
  89493. const res = fun(tp, count, size, sp, source.length);
  89494. if (res === 0 && filter) {
  89495. filter(tp, count4, size);
  89496. }
  89497. target.set(heap.subarray(tp, tp + count * size));
  89498. sbrk(tp - sbrk(0));
  89499. if (res !== 0) {
  89500. throw new Error("Malformed buffer data: ".concat(res));
  89501. }
  89502. }
  89503. const EXT_MESHOPT_COMPRESSION = 'EXT_meshopt_compression';
  89504. const name$6 = EXT_MESHOPT_COMPRESSION;
  89505. function preprocess$4(gltfData) {
  89506. const scenegraph = new GLTFScenegraph(gltfData);
  89507. if (scenegraph.getRequiredExtensions().includes(EXT_MESHOPT_COMPRESSION) && !isMeshoptSupported()) {
  89508. throw new Error("gltf: Required extension ".concat(EXT_MESHOPT_COMPRESSION, " not supported by browser"));
  89509. }
  89510. }
  89511. async function decode$4(gltfData, options) {
  89512. var _options$gltf;
  89513. const scenegraph = new GLTFScenegraph(gltfData);
  89514. if (!(options !== null && options !== void 0 && (_options$gltf = options.gltf) !== null && _options$gltf !== void 0 && _options$gltf.decompressMeshes)) {
  89515. return;
  89516. }
  89517. const promises = [];
  89518. for (const bufferViewIndex of gltfData.json.bufferViews || []) {
  89519. promises.push(decodeMeshoptBufferView(scenegraph, bufferViewIndex));
  89520. }
  89521. await Promise.all(promises);
  89522. scenegraph.removeExtension(EXT_MESHOPT_COMPRESSION);
  89523. }
  89524. async function decodeMeshoptBufferView(scenegraph, bufferView) {
  89525. const meshoptExtension = scenegraph.getObjectExtension(bufferView, EXT_MESHOPT_COMPRESSION);
  89526. if (meshoptExtension) {
  89527. const buffer = bufferView.buffer;
  89528. const {
  89529. byteOffset = 0,
  89530. byteLength = 0,
  89531. byteStride,
  89532. count,
  89533. mode,
  89534. filter = 'NONE'
  89535. } = meshoptExtension;
  89536. const source = new Uint8Array(buffer, byteOffset, byteLength);
  89537. const result = new ArrayBuffer(count * byteStride);
  89538. await meshoptDecodeGltfBuffer(new Uint8Array(result), count, byteStride, source, mode, filter);
  89539. return result;
  89540. }
  89541. return null;
  89542. }
  89543. var EXT_meshopt_compression = /*#__PURE__*/Object.freeze({
  89544. __proto__: null,
  89545. name: name$6,
  89546. preprocess: preprocess$4,
  89547. decode: decode$4
  89548. });
  89549. const EXT_TEXTURE_WEBP = 'EXT_texture_webp';
  89550. const name$5 = EXT_TEXTURE_WEBP;
  89551. function preprocess$3(gltfData, options) {
  89552. const scenegraph = new GLTFScenegraph(gltfData);
  89553. if (!_isImageFormatSupported('image/webp')) {
  89554. if (scenegraph.getRequiredExtensions().includes(EXT_TEXTURE_WEBP)) {
  89555. throw new Error("gltf: Required extension ".concat(EXT_TEXTURE_WEBP, " not supported by browser"));
  89556. }
  89557. return;
  89558. }
  89559. const {
  89560. json
  89561. } = scenegraph;
  89562. for (const texture of json.textures || []) {
  89563. const extension = scenegraph.getObjectExtension(texture, EXT_TEXTURE_WEBP);
  89564. if (extension) {
  89565. texture.source = extension.source;
  89566. }
  89567. scenegraph.removeObjectExtension(texture, EXT_TEXTURE_WEBP);
  89568. }
  89569. scenegraph.removeExtension(EXT_TEXTURE_WEBP);
  89570. }
  89571. var EXT_texture_webp = /*#__PURE__*/Object.freeze({
  89572. __proto__: null,
  89573. name: name$5,
  89574. preprocess: preprocess$3
  89575. });
  89576. const KHR_TEXTURE_BASISU = 'KHR_texture_basisu';
  89577. const name$4 = KHR_TEXTURE_BASISU;
  89578. function preprocess$2(gltfData, options) {
  89579. const scene = new GLTFScenegraph(gltfData);
  89580. const {
  89581. json
  89582. } = scene;
  89583. for (const texture of json.textures || []) {
  89584. const extension = scene.getObjectExtension(texture, KHR_TEXTURE_BASISU);
  89585. if (extension) {
  89586. texture.source = extension.source;
  89587. }
  89588. scene.removeObjectExtension(texture, KHR_TEXTURE_BASISU);
  89589. }
  89590. scene.removeExtension(KHR_TEXTURE_BASISU);
  89591. }
  89592. var KHR_texture_basisu = /*#__PURE__*/Object.freeze({
  89593. __proto__: null,
  89594. name: name$4,
  89595. preprocess: preprocess$2
  89596. });
  89597. function getGLTFAccessors(attributes) {
  89598. const accessors = {};
  89599. for (const name in attributes) {
  89600. const attribute = attributes[name];
  89601. if (name !== 'indices') {
  89602. const glTFAccessor = getGLTFAccessor(attribute);
  89603. accessors[name] = glTFAccessor;
  89604. }
  89605. }
  89606. return accessors;
  89607. }
  89608. function getGLTFAccessor(attribute) {
  89609. const {
  89610. buffer,
  89611. size,
  89612. count
  89613. } = getAccessorData(attribute);
  89614. const glTFAccessor = {
  89615. value: buffer,
  89616. size,
  89617. byteOffset: 0,
  89618. count,
  89619. type: getAccessorTypeFromSize(size),
  89620. componentType: getComponentTypeFromArray(buffer)
  89621. };
  89622. return glTFAccessor;
  89623. }
  89624. function getAccessorData(attribute) {
  89625. let buffer = attribute;
  89626. let size = 1;
  89627. let count = 0;
  89628. if (attribute && attribute.value) {
  89629. buffer = attribute.value;
  89630. size = attribute.size || 1;
  89631. }
  89632. if (buffer) {
  89633. if (!ArrayBuffer.isView(buffer)) {
  89634. buffer = toTypedArray(buffer, Float32Array);
  89635. }
  89636. count = buffer.length / size;
  89637. }
  89638. return {
  89639. buffer,
  89640. size,
  89641. count
  89642. };
  89643. }
  89644. function toTypedArray(array, ArrayType, convertTypedArrays = false) {
  89645. if (!array) {
  89646. return null;
  89647. }
  89648. if (Array.isArray(array)) {
  89649. return new ArrayType(array);
  89650. }
  89651. if (convertTypedArrays && !(array instanceof ArrayType)) {
  89652. return new ArrayType(array);
  89653. }
  89654. return array;
  89655. }
  89656. const KHR_DRACO_MESH_COMPRESSION = 'KHR_draco_mesh_compression';
  89657. const name$3 = KHR_DRACO_MESH_COMPRESSION;
  89658. function preprocess$1(gltfData, options, context) {
  89659. const scenegraph = new GLTFScenegraph(gltfData);
  89660. for (const primitive of makeMeshPrimitiveIterator(scenegraph)) {
  89661. if (scenegraph.getObjectExtension(primitive, KHR_DRACO_MESH_COMPRESSION)) ;
  89662. }
  89663. }
  89664. async function decode$3(gltfData, options, context) {
  89665. var _options$gltf;
  89666. if (!(options !== null && options !== void 0 && (_options$gltf = options.gltf) !== null && _options$gltf !== void 0 && _options$gltf.decompressMeshes)) {
  89667. return;
  89668. }
  89669. const scenegraph = new GLTFScenegraph(gltfData);
  89670. const promises = [];
  89671. for (const primitive of makeMeshPrimitiveIterator(scenegraph)) {
  89672. if (scenegraph.getObjectExtension(primitive, KHR_DRACO_MESH_COMPRESSION)) {
  89673. promises.push(decompressPrimitive(scenegraph, primitive, options, context));
  89674. }
  89675. }
  89676. await Promise.all(promises);
  89677. scenegraph.removeExtension(KHR_DRACO_MESH_COMPRESSION);
  89678. }
  89679. function encode$3(gltfData, options = {}) {
  89680. const scenegraph = new GLTFScenegraph(gltfData);
  89681. for (const mesh of scenegraph.json.meshes || []) {
  89682. compressMesh(mesh);
  89683. scenegraph.addRequiredExtension(KHR_DRACO_MESH_COMPRESSION);
  89684. }
  89685. }
  89686. async function decompressPrimitive(scenegraph, primitive, options, context) {
  89687. const dracoExtension = scenegraph.getObjectExtension(primitive, KHR_DRACO_MESH_COMPRESSION);
  89688. if (!dracoExtension) {
  89689. return;
  89690. }
  89691. const buffer = scenegraph.getTypedArrayForBufferView(dracoExtension.bufferView);
  89692. const bufferCopy = sliceArrayBuffer(buffer.buffer, buffer.byteOffset);
  89693. const {
  89694. parse
  89695. } = context;
  89696. const dracoOptions = { ...options
  89697. };
  89698. delete dracoOptions['3d-tiles'];
  89699. const decodedData = await parse(bufferCopy, DracoLoader, dracoOptions, context);
  89700. const decodedAttributes = getGLTFAccessors(decodedData.attributes);
  89701. for (const [attributeName, decodedAttribute] of Object.entries(decodedAttributes)) {
  89702. if (attributeName in primitive.attributes) {
  89703. const accessorIndex = primitive.attributes[attributeName];
  89704. const accessor = scenegraph.getAccessor(accessorIndex);
  89705. if (accessor !== null && accessor !== void 0 && accessor.min && accessor !== null && accessor !== void 0 && accessor.max) {
  89706. decodedAttribute.min = accessor.min;
  89707. decodedAttribute.max = accessor.max;
  89708. }
  89709. }
  89710. }
  89711. primitive.attributes = decodedAttributes;
  89712. if (decodedData.indices) {
  89713. primitive.indices = getGLTFAccessor(decodedData.indices);
  89714. }
  89715. checkPrimitive(primitive);
  89716. }
  89717. function compressMesh(attributes, indices, mode = 4, options, context) {
  89718. var _context$parseSync;
  89719. if (!options.DracoWriter) {
  89720. throw new Error('options.gltf.DracoWriter not provided');
  89721. }
  89722. const compressedData = options.DracoWriter.encodeSync({
  89723. attributes
  89724. });
  89725. const decodedData = context === null || context === void 0 ? void 0 : (_context$parseSync = context.parseSync) === null || _context$parseSync === void 0 ? void 0 : _context$parseSync.call(context, {
  89726. attributes
  89727. });
  89728. const fauxAccessors = options._addFauxAttributes(decodedData.attributes);
  89729. const bufferViewIndex = options.addBufferView(compressedData);
  89730. const glTFMesh = {
  89731. primitives: [{
  89732. attributes: fauxAccessors,
  89733. mode,
  89734. extensions: {
  89735. [KHR_DRACO_MESH_COMPRESSION]: {
  89736. bufferView: bufferViewIndex,
  89737. attributes: fauxAccessors
  89738. }
  89739. }
  89740. }]
  89741. };
  89742. return glTFMesh;
  89743. }
  89744. function checkPrimitive(primitive) {
  89745. if (!primitive.attributes && Object.keys(primitive.attributes).length > 0) {
  89746. throw new Error('glTF: Empty primitive detected: Draco decompression failure?');
  89747. }
  89748. }
  89749. function* makeMeshPrimitiveIterator(scenegraph) {
  89750. for (const mesh of scenegraph.json.meshes || []) {
  89751. for (const primitive of mesh.primitives) {
  89752. yield primitive;
  89753. }
  89754. }
  89755. }
  89756. var KHR_draco_mesh_compression = /*#__PURE__*/Object.freeze({
  89757. __proto__: null,
  89758. name: name$3,
  89759. preprocess: preprocess$1,
  89760. decode: decode$3,
  89761. encode: encode$3
  89762. });
  89763. const KHR_LIGHTS_PUNCTUAL = 'KHR_lights_punctual';
  89764. const name$2 = KHR_LIGHTS_PUNCTUAL;
  89765. async function decode$2(gltfData) {
  89766. const gltfScenegraph = new GLTFScenegraph(gltfData);
  89767. const {
  89768. json
  89769. } = gltfScenegraph;
  89770. const extension = gltfScenegraph.getExtension(KHR_LIGHTS_PUNCTUAL);
  89771. if (extension) {
  89772. gltfScenegraph.json.lights = extension.lights;
  89773. gltfScenegraph.removeExtension(KHR_LIGHTS_PUNCTUAL);
  89774. }
  89775. for (const node of json.nodes || []) {
  89776. const nodeExtension = gltfScenegraph.getObjectExtension(node, KHR_LIGHTS_PUNCTUAL);
  89777. if (nodeExtension) {
  89778. node.light = nodeExtension.light;
  89779. }
  89780. gltfScenegraph.removeObjectExtension(node, KHR_LIGHTS_PUNCTUAL);
  89781. }
  89782. }
  89783. async function encode$2(gltfData) {
  89784. const gltfScenegraph = new GLTFScenegraph(gltfData);
  89785. const {
  89786. json
  89787. } = gltfScenegraph;
  89788. if (json.lights) {
  89789. const extension = gltfScenegraph.addExtension(KHR_LIGHTS_PUNCTUAL);
  89790. assert$1(!extension.lights);
  89791. extension.lights = json.lights;
  89792. delete json.lights;
  89793. }
  89794. if (gltfScenegraph.json.lights) {
  89795. for (const light of gltfScenegraph.json.lights) {
  89796. const node = light.node;
  89797. gltfScenegraph.addObjectExtension(node, KHR_LIGHTS_PUNCTUAL, light);
  89798. }
  89799. delete gltfScenegraph.json.lights;
  89800. }
  89801. }
  89802. var KHR_lights_punctual = /*#__PURE__*/Object.freeze({
  89803. __proto__: null,
  89804. name: name$2,
  89805. decode: decode$2,
  89806. encode: encode$2
  89807. });
  89808. const KHR_MATERIALS_UNLIT = 'KHR_materials_unlit';
  89809. const name$1 = KHR_MATERIALS_UNLIT;
  89810. async function decode$1(gltfData) {
  89811. const gltfScenegraph = new GLTFScenegraph(gltfData);
  89812. const {
  89813. json
  89814. } = gltfScenegraph;
  89815. gltfScenegraph.removeExtension(KHR_MATERIALS_UNLIT);
  89816. for (const material of json.materials || []) {
  89817. const extension = material.extensions && material.extensions.KHR_materials_unlit;
  89818. if (extension) {
  89819. material.unlit = true;
  89820. }
  89821. gltfScenegraph.removeObjectExtension(material, KHR_MATERIALS_UNLIT);
  89822. }
  89823. }
  89824. function encode$1(gltfData) {
  89825. const gltfScenegraph = new GLTFScenegraph(gltfData);
  89826. const {
  89827. json
  89828. } = gltfScenegraph;
  89829. if (gltfScenegraph.materials) {
  89830. for (const material of json.materials || []) {
  89831. if (material.unlit) {
  89832. delete material.unlit;
  89833. gltfScenegraph.addObjectExtension(material, KHR_MATERIALS_UNLIT, {});
  89834. gltfScenegraph.addExtension(KHR_MATERIALS_UNLIT);
  89835. }
  89836. }
  89837. }
  89838. }
  89839. var KHR_materials_unlit = /*#__PURE__*/Object.freeze({
  89840. __proto__: null,
  89841. name: name$1,
  89842. decode: decode$1,
  89843. encode: encode$1
  89844. });
  89845. const KHR_TECHNIQUES_WEBGL = 'KHR_techniques_webgl';
  89846. const name = KHR_TECHNIQUES_WEBGL;
  89847. async function decode(gltfData) {
  89848. const gltfScenegraph = new GLTFScenegraph(gltfData);
  89849. const {
  89850. json
  89851. } = gltfScenegraph;
  89852. const extension = gltfScenegraph.getExtension(KHR_TECHNIQUES_WEBGL);
  89853. if (extension) {
  89854. const techniques = resolveTechniques(extension, gltfScenegraph);
  89855. for (const material of json.materials || []) {
  89856. const materialExtension = gltfScenegraph.getObjectExtension(material, KHR_TECHNIQUES_WEBGL);
  89857. if (materialExtension) {
  89858. material.technique = Object.assign({}, materialExtension, techniques[materialExtension.technique]);
  89859. material.technique.values = resolveValues(material.technique, gltfScenegraph);
  89860. }
  89861. gltfScenegraph.removeObjectExtension(material, KHR_TECHNIQUES_WEBGL);
  89862. }
  89863. gltfScenegraph.removeExtension(KHR_TECHNIQUES_WEBGL);
  89864. }
  89865. }
  89866. async function encode(gltfData, options) {}
  89867. function resolveTechniques(techniquesExtension, gltfScenegraph) {
  89868. const {
  89869. programs = [],
  89870. shaders = [],
  89871. techniques = []
  89872. } = techniquesExtension;
  89873. const textDecoder = new TextDecoder();
  89874. shaders.forEach(shader => {
  89875. if (Number.isFinite(shader.bufferView)) {
  89876. shader.code = textDecoder.decode(gltfScenegraph.getTypedArrayForBufferView(shader.bufferView));
  89877. } else {
  89878. throw new Error('KHR_techniques_webgl: no shader code');
  89879. }
  89880. });
  89881. programs.forEach(program => {
  89882. program.fragmentShader = shaders[program.fragmentShader];
  89883. program.vertexShader = shaders[program.vertexShader];
  89884. });
  89885. techniques.forEach(technique => {
  89886. technique.program = programs[technique.program];
  89887. });
  89888. return techniques;
  89889. }
  89890. function resolveValues(technique, gltfScenegraph) {
  89891. const values = Object.assign({}, technique.values);
  89892. Object.keys(technique.uniforms || {}).forEach(uniform => {
  89893. if (technique.uniforms[uniform].value && !(uniform in values)) {
  89894. values[uniform] = technique.uniforms[uniform].value;
  89895. }
  89896. });
  89897. Object.keys(values).forEach(uniform => {
  89898. if (typeof values[uniform] === 'object' && values[uniform].index !== undefined) {
  89899. values[uniform].texture = gltfScenegraph.getTexture(values[uniform].index);
  89900. }
  89901. });
  89902. return values;
  89903. }
  89904. var KHR_techniques_webgl = /*#__PURE__*/Object.freeze({
  89905. __proto__: null,
  89906. name: name,
  89907. decode: decode,
  89908. encode: encode
  89909. });
  89910. const EXTENSIONS$2 = [EXT_meshopt_compression, EXT_texture_webp, KHR_texture_basisu, KHR_draco_mesh_compression, KHR_lights_punctual, KHR_materials_unlit, KHR_techniques_webgl];
  89911. function preprocessExtensions(gltf, options = {}, context) {
  89912. const extensions = EXTENSIONS$2.filter(extension => useExtension(extension.name, options));
  89913. for (const extension of extensions) {
  89914. var _extension$preprocess;
  89915. (_extension$preprocess = extension.preprocess) === null || _extension$preprocess === void 0 ? void 0 : _extension$preprocess.call(extension, gltf, options, context);
  89916. }
  89917. }
  89918. async function decodeExtensions(gltf, options = {}, context) {
  89919. const extensions = EXTENSIONS$2.filter(extension => useExtension(extension.name, options));
  89920. for (const extension of extensions) {
  89921. var _extension$decode;
  89922. await ((_extension$decode = extension.decode) === null || _extension$decode === void 0 ? void 0 : _extension$decode.call(extension, gltf, options, context));
  89923. }
  89924. }
  89925. function useExtension(extensionName, options) {
  89926. var _options$gltf;
  89927. const excludes = (options === null || options === void 0 ? void 0 : (_options$gltf = options.gltf) === null || _options$gltf === void 0 ? void 0 : _options$gltf.excludeExtensions) || {};
  89928. const exclude = extensionName in excludes && !excludes[extensionName];
  89929. return !exclude;
  89930. }
  89931. const KHR_BINARY_GLTF = 'KHR_binary_glTF';
  89932. function preprocess(gltfData) {
  89933. const gltfScenegraph = new GLTFScenegraph(gltfData);
  89934. const {
  89935. json
  89936. } = gltfScenegraph;
  89937. for (const image of json.images || []) {
  89938. const extension = gltfScenegraph.getObjectExtension(image, KHR_BINARY_GLTF);
  89939. if (extension) {
  89940. Object.assign(image, extension);
  89941. }
  89942. gltfScenegraph.removeObjectExtension(image, KHR_BINARY_GLTF);
  89943. }
  89944. if (json.buffers && json.buffers[0]) {
  89945. delete json.buffers[0].uri;
  89946. }
  89947. gltfScenegraph.removeExtension(KHR_BINARY_GLTF);
  89948. }
  89949. const GLTF_ARRAYS = {
  89950. accessors: 'accessor',
  89951. animations: 'animation',
  89952. buffers: 'buffer',
  89953. bufferViews: 'bufferView',
  89954. images: 'image',
  89955. materials: 'material',
  89956. meshes: 'mesh',
  89957. nodes: 'node',
  89958. samplers: 'sampler',
  89959. scenes: 'scene',
  89960. skins: 'skin',
  89961. textures: 'texture'
  89962. };
  89963. const GLTF_KEYS = {
  89964. accessor: 'accessors',
  89965. animations: 'animation',
  89966. buffer: 'buffers',
  89967. bufferView: 'bufferViews',
  89968. image: 'images',
  89969. material: 'materials',
  89970. mesh: 'meshes',
  89971. node: 'nodes',
  89972. sampler: 'samplers',
  89973. scene: 'scenes',
  89974. skin: 'skins',
  89975. texture: 'textures'
  89976. };
  89977. class GLTFV1Normalizer {
  89978. constructor() {
  89979. _defineProperty(this, "idToIndexMap", {
  89980. animations: {},
  89981. accessors: {},
  89982. buffers: {},
  89983. bufferViews: {},
  89984. images: {},
  89985. materials: {},
  89986. meshes: {},
  89987. nodes: {},
  89988. samplers: {},
  89989. scenes: {},
  89990. skins: {},
  89991. textures: {}
  89992. });
  89993. _defineProperty(this, "json", void 0);
  89994. }
  89995. normalize(gltf, options) {
  89996. this.json = gltf.json;
  89997. const json = gltf.json;
  89998. switch (json.asset && json.asset.version) {
  89999. case '2.0':
  90000. return;
  90001. case undefined:
  90002. case '1.0':
  90003. break;
  90004. default:
  90005. console.warn("glTF: Unknown version ".concat(json.asset.version));
  90006. return;
  90007. }
  90008. if (!options.normalize) {
  90009. throw new Error('glTF v1 is not supported.');
  90010. }
  90011. console.warn('Converting glTF v1 to glTF v2 format. This is experimental and may fail.');
  90012. this._addAsset(json);
  90013. this._convertTopLevelObjectsToArrays(json);
  90014. preprocess(gltf);
  90015. this._convertObjectIdsToArrayIndices(json);
  90016. this._updateObjects(json);
  90017. this._updateMaterial(json);
  90018. }
  90019. _addAsset(json) {
  90020. json.asset = json.asset || {};
  90021. json.asset.version = '2.0';
  90022. json.asset.generator = json.asset.generator || 'Normalized to glTF 2.0 by loaders.gl';
  90023. }
  90024. _convertTopLevelObjectsToArrays(json) {
  90025. for (const arrayName in GLTF_ARRAYS) {
  90026. this._convertTopLevelObjectToArray(json, arrayName);
  90027. }
  90028. }
  90029. _convertTopLevelObjectToArray(json, mapName) {
  90030. const objectMap = json[mapName];
  90031. if (!objectMap || Array.isArray(objectMap)) {
  90032. return;
  90033. }
  90034. json[mapName] = [];
  90035. for (const id in objectMap) {
  90036. const object = objectMap[id];
  90037. object.id = object.id || id;
  90038. const index = json[mapName].length;
  90039. json[mapName].push(object);
  90040. this.idToIndexMap[mapName][id] = index;
  90041. }
  90042. }
  90043. _convertObjectIdsToArrayIndices(json) {
  90044. for (const arrayName in GLTF_ARRAYS) {
  90045. this._convertIdsToIndices(json, arrayName);
  90046. }
  90047. if ('scene' in json) {
  90048. json.scene = this._convertIdToIndex(json.scene, 'scene');
  90049. }
  90050. for (const texture of json.textures) {
  90051. this._convertTextureIds(texture);
  90052. }
  90053. for (const mesh of json.meshes) {
  90054. this._convertMeshIds(mesh);
  90055. }
  90056. for (const node of json.nodes) {
  90057. this._convertNodeIds(node);
  90058. }
  90059. for (const node of json.scenes) {
  90060. this._convertSceneIds(node);
  90061. }
  90062. }
  90063. _convertTextureIds(texture) {
  90064. if (texture.source) {
  90065. texture.source = this._convertIdToIndex(texture.source, 'image');
  90066. }
  90067. }
  90068. _convertMeshIds(mesh) {
  90069. for (const primitive of mesh.primitives) {
  90070. const {
  90071. attributes,
  90072. indices,
  90073. material
  90074. } = primitive;
  90075. for (const attributeName in attributes) {
  90076. attributes[attributeName] = this._convertIdToIndex(attributes[attributeName], 'accessor');
  90077. }
  90078. if (indices) {
  90079. primitive.indices = this._convertIdToIndex(indices, 'accessor');
  90080. }
  90081. if (material) {
  90082. primitive.material = this._convertIdToIndex(material, 'material');
  90083. }
  90084. }
  90085. }
  90086. _convertNodeIds(node) {
  90087. if (node.children) {
  90088. node.children = node.children.map(child => this._convertIdToIndex(child, 'node'));
  90089. }
  90090. if (node.meshes) {
  90091. node.meshes = node.meshes.map(mesh => this._convertIdToIndex(mesh, 'mesh'));
  90092. }
  90093. }
  90094. _convertSceneIds(scene) {
  90095. if (scene.nodes) {
  90096. scene.nodes = scene.nodes.map(node => this._convertIdToIndex(node, 'node'));
  90097. }
  90098. }
  90099. _convertIdsToIndices(json, topLevelArrayName) {
  90100. if (!json[topLevelArrayName]) {
  90101. console.warn("gltf v1: json doesn't contain attribute ".concat(topLevelArrayName));
  90102. json[topLevelArrayName] = [];
  90103. }
  90104. for (const object of json[topLevelArrayName]) {
  90105. for (const key in object) {
  90106. const id = object[key];
  90107. const index = this._convertIdToIndex(id, key);
  90108. object[key] = index;
  90109. }
  90110. }
  90111. }
  90112. _convertIdToIndex(id, key) {
  90113. const arrayName = GLTF_KEYS[key];
  90114. if (arrayName in this.idToIndexMap) {
  90115. const index = this.idToIndexMap[arrayName][id];
  90116. if (!Number.isFinite(index)) {
  90117. throw new Error("gltf v1: failed to resolve ".concat(key, " with id ").concat(id));
  90118. }
  90119. return index;
  90120. }
  90121. return id;
  90122. }
  90123. _updateObjects(json) {
  90124. for (const buffer of this.json.buffers) {
  90125. delete buffer.type;
  90126. }
  90127. }
  90128. _updateMaterial(json) {
  90129. for (const material of json.materials) {
  90130. material.pbrMetallicRoughness = {
  90131. baseColorFactor: [1, 1, 1, 1],
  90132. metallicFactor: 1,
  90133. roughnessFactor: 1
  90134. };
  90135. const textureId = material.values && material.values.tex;
  90136. const textureIndex = json.textures.findIndex(texture => texture.id === textureId);
  90137. if (textureIndex !== -1) {
  90138. material.pbrMetallicRoughness.baseColorTexture = {
  90139. index: textureIndex
  90140. };
  90141. }
  90142. }
  90143. }
  90144. }
  90145. function normalizeGLTFV1(gltf, options = {}) {
  90146. return new GLTFV1Normalizer().normalize(gltf, options);
  90147. }
  90148. const COMPONENTS = {
  90149. SCALAR: 1,
  90150. VEC2: 2,
  90151. VEC3: 3,
  90152. VEC4: 4,
  90153. MAT2: 4,
  90154. MAT3: 9,
  90155. MAT4: 16
  90156. };
  90157. const BYTES = {
  90158. 5120: 1,
  90159. 5121: 1,
  90160. 5122: 2,
  90161. 5123: 2,
  90162. 5125: 4,
  90163. 5126: 4
  90164. };
  90165. const GL_SAMPLER = {
  90166. TEXTURE_MAG_FILTER: 0x2800,
  90167. TEXTURE_MIN_FILTER: 0x2801,
  90168. TEXTURE_WRAP_S: 0x2802,
  90169. TEXTURE_WRAP_T: 0x2803,
  90170. REPEAT: 0x2901,
  90171. LINEAR: 0x2601,
  90172. NEAREST_MIPMAP_LINEAR: 0x2702
  90173. };
  90174. const SAMPLER_PARAMETER_GLTF_TO_GL = {
  90175. magFilter: GL_SAMPLER.TEXTURE_MAG_FILTER,
  90176. minFilter: GL_SAMPLER.TEXTURE_MIN_FILTER,
  90177. wrapS: GL_SAMPLER.TEXTURE_WRAP_S,
  90178. wrapT: GL_SAMPLER.TEXTURE_WRAP_T
  90179. };
  90180. const DEFAULT_SAMPLER = {
  90181. [GL_SAMPLER.TEXTURE_MAG_FILTER]: GL_SAMPLER.LINEAR,
  90182. [GL_SAMPLER.TEXTURE_MIN_FILTER]: GL_SAMPLER.NEAREST_MIPMAP_LINEAR,
  90183. [GL_SAMPLER.TEXTURE_WRAP_S]: GL_SAMPLER.REPEAT,
  90184. [GL_SAMPLER.TEXTURE_WRAP_T]: GL_SAMPLER.REPEAT
  90185. };
  90186. function getBytesFromComponentType(componentType) {
  90187. return BYTES[componentType];
  90188. }
  90189. function getSizeFromAccessorType(type) {
  90190. return COMPONENTS[type];
  90191. }
  90192. class GLTFPostProcessor {
  90193. constructor() {
  90194. _defineProperty(this, "baseUri", '');
  90195. _defineProperty(this, "json", {});
  90196. _defineProperty(this, "buffers", []);
  90197. _defineProperty(this, "images", []);
  90198. }
  90199. postProcess(gltf, options = {}) {
  90200. const {
  90201. json,
  90202. buffers = [],
  90203. images = [],
  90204. baseUri = ''
  90205. } = gltf;
  90206. assert$1(json);
  90207. this.baseUri = baseUri;
  90208. this.json = json;
  90209. this.buffers = buffers;
  90210. this.images = images;
  90211. this._resolveTree(this.json, options);
  90212. return this.json;
  90213. }
  90214. _resolveTree(json, options = {}) {
  90215. if (json.bufferViews) {
  90216. json.bufferViews = json.bufferViews.map((bufView, i) => this._resolveBufferView(bufView, i));
  90217. }
  90218. if (json.images) {
  90219. json.images = json.images.map((image, i) => this._resolveImage(image, i));
  90220. }
  90221. if (json.samplers) {
  90222. json.samplers = json.samplers.map((sampler, i) => this._resolveSampler(sampler, i));
  90223. }
  90224. if (json.textures) {
  90225. json.textures = json.textures.map((texture, i) => this._resolveTexture(texture, i));
  90226. }
  90227. if (json.accessors) {
  90228. json.accessors = json.accessors.map((accessor, i) => this._resolveAccessor(accessor, i));
  90229. }
  90230. if (json.materials) {
  90231. json.materials = json.materials.map((material, i) => this._resolveMaterial(material, i));
  90232. }
  90233. if (json.meshes) {
  90234. json.meshes = json.meshes.map((mesh, i) => this._resolveMesh(mesh, i));
  90235. }
  90236. if (json.nodes) {
  90237. json.nodes = json.nodes.map((node, i) => this._resolveNode(node, i));
  90238. }
  90239. if (json.skins) {
  90240. json.skins = json.skins.map((skin, i) => this._resolveSkin(skin, i));
  90241. }
  90242. if (json.scenes) {
  90243. json.scenes = json.scenes.map((scene, i) => this._resolveScene(scene, i));
  90244. }
  90245. if (json.scene !== undefined) {
  90246. json.scene = json.scenes[this.json.scene];
  90247. }
  90248. }
  90249. getScene(index) {
  90250. return this._get('scenes', index);
  90251. }
  90252. getNode(index) {
  90253. return this._get('nodes', index);
  90254. }
  90255. getSkin(index) {
  90256. return this._get('skins', index);
  90257. }
  90258. getMesh(index) {
  90259. return this._get('meshes', index);
  90260. }
  90261. getMaterial(index) {
  90262. return this._get('materials', index);
  90263. }
  90264. getAccessor(index) {
  90265. return this._get('accessors', index);
  90266. }
  90267. getCamera(index) {
  90268. return null;
  90269. }
  90270. getTexture(index) {
  90271. return this._get('textures', index);
  90272. }
  90273. getSampler(index) {
  90274. return this._get('samplers', index);
  90275. }
  90276. getImage(index) {
  90277. return this._get('images', index);
  90278. }
  90279. getBufferView(index) {
  90280. return this._get('bufferViews', index);
  90281. }
  90282. getBuffer(index) {
  90283. return this._get('buffers', index);
  90284. }
  90285. _get(array, index) {
  90286. if (typeof index === 'object') {
  90287. return index;
  90288. }
  90289. const object = this.json[array] && this.json[array][index];
  90290. if (!object) {
  90291. console.warn("glTF file error: Could not find ".concat(array, "[").concat(index, "]"));
  90292. }
  90293. return object;
  90294. }
  90295. _resolveScene(scene, index) {
  90296. scene.id = scene.id || "scene-".concat(index);
  90297. scene.nodes = (scene.nodes || []).map(node => this.getNode(node));
  90298. return scene;
  90299. }
  90300. _resolveNode(node, index) {
  90301. node.id = node.id || "node-".concat(index);
  90302. if (node.children) {
  90303. node.children = node.children.map(child => this.getNode(child));
  90304. }
  90305. if (node.mesh !== undefined) {
  90306. node.mesh = this.getMesh(node.mesh);
  90307. } else if (node.meshes !== undefined && node.meshes.length) {
  90308. node.mesh = node.meshes.reduce((accum, meshIndex) => {
  90309. const mesh = this.getMesh(meshIndex);
  90310. accum.id = mesh.id;
  90311. accum.primitives = accum.primitives.concat(mesh.primitives);
  90312. return accum;
  90313. }, {
  90314. primitives: []
  90315. });
  90316. }
  90317. if (node.camera !== undefined) {
  90318. node.camera = this.getCamera(node.camera);
  90319. }
  90320. if (node.skin !== undefined) {
  90321. node.skin = this.getSkin(node.skin);
  90322. }
  90323. return node;
  90324. }
  90325. _resolveSkin(skin, index) {
  90326. skin.id = skin.id || "skin-".concat(index);
  90327. skin.inverseBindMatrices = this.getAccessor(skin.inverseBindMatrices);
  90328. return skin;
  90329. }
  90330. _resolveMesh(mesh, index) {
  90331. mesh.id = mesh.id || "mesh-".concat(index);
  90332. if (mesh.primitives) {
  90333. mesh.primitives = mesh.primitives.map(primitive => {
  90334. primitive = { ...primitive
  90335. };
  90336. const attributes = primitive.attributes;
  90337. primitive.attributes = {};
  90338. for (const attribute in attributes) {
  90339. primitive.attributes[attribute] = this.getAccessor(attributes[attribute]);
  90340. }
  90341. if (primitive.indices !== undefined) {
  90342. primitive.indices = this.getAccessor(primitive.indices);
  90343. }
  90344. if (primitive.material !== undefined) {
  90345. primitive.material = this.getMaterial(primitive.material);
  90346. }
  90347. return primitive;
  90348. });
  90349. }
  90350. return mesh;
  90351. }
  90352. _resolveMaterial(material, index) {
  90353. material.id = material.id || "material-".concat(index);
  90354. if (material.normalTexture) {
  90355. material.normalTexture = { ...material.normalTexture
  90356. };
  90357. material.normalTexture.texture = this.getTexture(material.normalTexture.index);
  90358. }
  90359. if (material.occlusionTexture) {
  90360. material.occlustionTexture = { ...material.occlustionTexture
  90361. };
  90362. material.occlusionTexture.texture = this.getTexture(material.occlusionTexture.index);
  90363. }
  90364. if (material.emissiveTexture) {
  90365. material.emmisiveTexture = { ...material.emmisiveTexture
  90366. };
  90367. material.emissiveTexture.texture = this.getTexture(material.emissiveTexture.index);
  90368. }
  90369. if (!material.emissiveFactor) {
  90370. material.emissiveFactor = material.emmisiveTexture ? [1, 1, 1] : [0, 0, 0];
  90371. }
  90372. if (material.pbrMetallicRoughness) {
  90373. material.pbrMetallicRoughness = { ...material.pbrMetallicRoughness
  90374. };
  90375. const mr = material.pbrMetallicRoughness;
  90376. if (mr.baseColorTexture) {
  90377. mr.baseColorTexture = { ...mr.baseColorTexture
  90378. };
  90379. mr.baseColorTexture.texture = this.getTexture(mr.baseColorTexture.index);
  90380. }
  90381. if (mr.metallicRoughnessTexture) {
  90382. mr.metallicRoughnessTexture = { ...mr.metallicRoughnessTexture
  90383. };
  90384. mr.metallicRoughnessTexture.texture = this.getTexture(mr.metallicRoughnessTexture.index);
  90385. }
  90386. }
  90387. return material;
  90388. }
  90389. _resolveAccessor(accessor, index) {
  90390. accessor.id = accessor.id || "accessor-".concat(index);
  90391. if (accessor.bufferView !== undefined) {
  90392. accessor.bufferView = this.getBufferView(accessor.bufferView);
  90393. }
  90394. accessor.bytesPerComponent = getBytesFromComponentType(accessor.componentType);
  90395. accessor.components = getSizeFromAccessorType(accessor.type);
  90396. accessor.bytesPerElement = accessor.bytesPerComponent * accessor.components;
  90397. if (accessor.bufferView) {
  90398. const buffer = accessor.bufferView.buffer;
  90399. const {
  90400. ArrayType,
  90401. byteLength
  90402. } = getAccessorArrayTypeAndLength(accessor, accessor.bufferView);
  90403. const byteOffset = (accessor.bufferView.byteOffset || 0) + (accessor.byteOffset || 0) + buffer.byteOffset;
  90404. let cutBuffer = buffer.arrayBuffer.slice(byteOffset, byteOffset + byteLength);
  90405. if (accessor.bufferView.byteStride) {
  90406. cutBuffer = this._getValueFromInterleavedBuffer(buffer, byteOffset, accessor.bufferView.byteStride, accessor.bytesPerElement, accessor.count);
  90407. }
  90408. accessor.value = new ArrayType(cutBuffer);
  90409. }
  90410. return accessor;
  90411. }
  90412. _getValueFromInterleavedBuffer(buffer, byteOffset, byteStride, bytesPerElement, count) {
  90413. const result = new Uint8Array(count * bytesPerElement);
  90414. for (let i = 0; i < count; i++) {
  90415. const elementOffset = byteOffset + i * byteStride;
  90416. result.set(new Uint8Array(buffer.arrayBuffer.slice(elementOffset, elementOffset + bytesPerElement)), i * bytesPerElement);
  90417. }
  90418. return result.buffer;
  90419. }
  90420. _resolveTexture(texture, index) {
  90421. texture.id = texture.id || "texture-".concat(index);
  90422. texture.sampler = 'sampler' in texture ? this.getSampler(texture.sampler) : DEFAULT_SAMPLER;
  90423. texture.source = this.getImage(texture.source);
  90424. return texture;
  90425. }
  90426. _resolveSampler(sampler, index) {
  90427. sampler.id = sampler.id || "sampler-".concat(index);
  90428. sampler.parameters = {};
  90429. for (const key in sampler) {
  90430. const glEnum = this._enumSamplerParameter(key);
  90431. if (glEnum !== undefined) {
  90432. sampler.parameters[glEnum] = sampler[key];
  90433. }
  90434. }
  90435. return sampler;
  90436. }
  90437. _enumSamplerParameter(key) {
  90438. return SAMPLER_PARAMETER_GLTF_TO_GL[key];
  90439. }
  90440. _resolveImage(image, index) {
  90441. image.id = image.id || "image-".concat(index);
  90442. if (image.bufferView !== undefined) {
  90443. image.bufferView = this.getBufferView(image.bufferView);
  90444. }
  90445. const preloadedImage = this.images[index];
  90446. if (preloadedImage) {
  90447. image.image = preloadedImage;
  90448. }
  90449. return image;
  90450. }
  90451. _resolveBufferView(bufferView, index) {
  90452. const bufferIndex = bufferView.buffer;
  90453. const result = {
  90454. id: "bufferView-".concat(index),
  90455. ...bufferView,
  90456. buffer: this.buffers[bufferIndex]
  90457. };
  90458. const arrayBuffer = this.buffers[bufferIndex].arrayBuffer;
  90459. let byteOffset = this.buffers[bufferIndex].byteOffset || 0;
  90460. if ('byteOffset' in bufferView) {
  90461. byteOffset += bufferView.byteOffset;
  90462. }
  90463. result.data = new Uint8Array(arrayBuffer, byteOffset, bufferView.byteLength);
  90464. return result;
  90465. }
  90466. _resolveCamera(camera, index) {
  90467. camera.id = camera.id || "camera-".concat(index);
  90468. if (camera.perspective) ;
  90469. if (camera.orthographic) ;
  90470. return camera;
  90471. }
  90472. }
  90473. function postProcessGLTF(gltf, options) {
  90474. return new GLTFPostProcessor().postProcess(gltf, options);
  90475. }
  90476. const MAGIC_glTF = 0x676c5446;
  90477. const GLB_FILE_HEADER_SIZE = 12;
  90478. const GLB_CHUNK_HEADER_SIZE = 8;
  90479. const GLB_CHUNK_TYPE_JSON = 0x4e4f534a;
  90480. const GLB_CHUNK_TYPE_BIN = 0x004e4942;
  90481. const GLB_CHUNK_TYPE_JSON_XVIZ_DEPRECATED = 0;
  90482. const GLB_CHUNK_TYPE_BIX_XVIZ_DEPRECATED = 1;
  90483. const GLB_V1_CONTENT_FORMAT_JSON = 0x0;
  90484. const LE = true;
  90485. function getMagicString(dataView, byteOffset = 0) {
  90486. return "".concat(String.fromCharCode(dataView.getUint8(byteOffset + 0))).concat(String.fromCharCode(dataView.getUint8(byteOffset + 1))).concat(String.fromCharCode(dataView.getUint8(byteOffset + 2))).concat(String.fromCharCode(dataView.getUint8(byteOffset + 3)));
  90487. }
  90488. function isGLB(arrayBuffer, byteOffset = 0, options = {}) {
  90489. const dataView = new DataView(arrayBuffer);
  90490. const {
  90491. magic = MAGIC_glTF
  90492. } = options;
  90493. const magic1 = dataView.getUint32(byteOffset, false);
  90494. return magic1 === magic || magic1 === MAGIC_glTF;
  90495. }
  90496. function parseGLBSync(glb, arrayBuffer, byteOffset = 0, options = {}) {
  90497. const dataView = new DataView(arrayBuffer);
  90498. const type = getMagicString(dataView, byteOffset + 0);
  90499. const version = dataView.getUint32(byteOffset + 4, LE);
  90500. const byteLength = dataView.getUint32(byteOffset + 8, LE);
  90501. Object.assign(glb, {
  90502. header: {
  90503. byteOffset,
  90504. byteLength,
  90505. hasBinChunk: false
  90506. },
  90507. type,
  90508. version,
  90509. json: {},
  90510. binChunks: []
  90511. });
  90512. byteOffset += GLB_FILE_HEADER_SIZE;
  90513. switch (glb.version) {
  90514. case 1:
  90515. return parseGLBV1(glb, dataView, byteOffset);
  90516. case 2:
  90517. return parseGLBV2(glb, dataView, byteOffset, options = {});
  90518. default:
  90519. throw new Error("Invalid GLB version ".concat(glb.version, ". Only supports v1 and v2."));
  90520. }
  90521. }
  90522. function parseGLBV1(glb, dataView, byteOffset) {
  90523. assert$7(glb.header.byteLength > GLB_FILE_HEADER_SIZE + GLB_CHUNK_HEADER_SIZE);
  90524. const contentLength = dataView.getUint32(byteOffset + 0, LE);
  90525. const contentFormat = dataView.getUint32(byteOffset + 4, LE);
  90526. byteOffset += GLB_CHUNK_HEADER_SIZE;
  90527. assert$7(contentFormat === GLB_V1_CONTENT_FORMAT_JSON);
  90528. parseJSONChunk(glb, dataView, byteOffset, contentLength);
  90529. byteOffset += contentLength;
  90530. byteOffset += parseBINChunk(glb, dataView, byteOffset, glb.header.byteLength);
  90531. return byteOffset;
  90532. }
  90533. function parseGLBV2(glb, dataView, byteOffset, options) {
  90534. assert$7(glb.header.byteLength > GLB_FILE_HEADER_SIZE + GLB_CHUNK_HEADER_SIZE);
  90535. parseGLBChunksSync(glb, dataView, byteOffset, options);
  90536. return byteOffset + glb.header.byteLength;
  90537. }
  90538. function parseGLBChunksSync(glb, dataView, byteOffset, options) {
  90539. while (byteOffset + 8 <= glb.header.byteLength) {
  90540. const chunkLength = dataView.getUint32(byteOffset + 0, LE);
  90541. const chunkFormat = dataView.getUint32(byteOffset + 4, LE);
  90542. byteOffset += GLB_CHUNK_HEADER_SIZE;
  90543. switch (chunkFormat) {
  90544. case GLB_CHUNK_TYPE_JSON:
  90545. parseJSONChunk(glb, dataView, byteOffset, chunkLength);
  90546. break;
  90547. case GLB_CHUNK_TYPE_BIN:
  90548. parseBINChunk(glb, dataView, byteOffset, chunkLength);
  90549. break;
  90550. case GLB_CHUNK_TYPE_JSON_XVIZ_DEPRECATED:
  90551. if (!options.strict) {
  90552. parseJSONChunk(glb, dataView, byteOffset, chunkLength);
  90553. }
  90554. break;
  90555. case GLB_CHUNK_TYPE_BIX_XVIZ_DEPRECATED:
  90556. if (!options.strict) {
  90557. parseBINChunk(glb, dataView, byteOffset, chunkLength);
  90558. }
  90559. break;
  90560. }
  90561. byteOffset += padToNBytes(chunkLength, 4);
  90562. }
  90563. return byteOffset;
  90564. }
  90565. function parseJSONChunk(glb, dataView, byteOffset, chunkLength) {
  90566. const jsonChunk = new Uint8Array(dataView.buffer, byteOffset, chunkLength);
  90567. const textDecoder = new TextDecoder('utf8');
  90568. const jsonText = textDecoder.decode(jsonChunk);
  90569. glb.json = JSON.parse(jsonText);
  90570. return padToNBytes(chunkLength, 4);
  90571. }
  90572. function parseBINChunk(glb, dataView, byteOffset, chunkLength) {
  90573. glb.header.hasBinChunk = true;
  90574. glb.binChunks.push({
  90575. byteOffset,
  90576. byteLength: chunkLength,
  90577. arrayBuffer: dataView.buffer
  90578. });
  90579. return padToNBytes(chunkLength, 4);
  90580. }
  90581. async function parseGLTF(gltf, arrayBufferOrString, byteOffset = 0, options, context) {
  90582. var _options$gltf, _options$gltf2, _options$gltf3, _options$gltf4;
  90583. parseGLTFContainerSync(gltf, arrayBufferOrString, byteOffset, options);
  90584. normalizeGLTFV1(gltf, {
  90585. normalize: options === null || options === void 0 ? void 0 : (_options$gltf = options.gltf) === null || _options$gltf === void 0 ? void 0 : _options$gltf.normalize
  90586. });
  90587. preprocessExtensions(gltf, options, context);
  90588. const promises = [];
  90589. if (options !== null && options !== void 0 && (_options$gltf2 = options.gltf) !== null && _options$gltf2 !== void 0 && _options$gltf2.loadBuffers && gltf.json.buffers) {
  90590. await loadBuffers(gltf, options, context);
  90591. }
  90592. if (options !== null && options !== void 0 && (_options$gltf3 = options.gltf) !== null && _options$gltf3 !== void 0 && _options$gltf3.loadImages) {
  90593. const promise = loadImages(gltf, options, context);
  90594. promises.push(promise);
  90595. }
  90596. const promise = decodeExtensions(gltf, options, context);
  90597. promises.push(promise);
  90598. await Promise.all(promises);
  90599. return options !== null && options !== void 0 && (_options$gltf4 = options.gltf) !== null && _options$gltf4 !== void 0 && _options$gltf4.postProcess ? postProcessGLTF(gltf, options) : gltf;
  90600. }
  90601. function parseGLTFContainerSync(gltf, data, byteOffset, options) {
  90602. if (options.uri) {
  90603. gltf.baseUri = options.uri;
  90604. }
  90605. if (data instanceof ArrayBuffer && !isGLB(data, byteOffset, options)) {
  90606. const textDecoder = new TextDecoder();
  90607. data = textDecoder.decode(data);
  90608. }
  90609. if (typeof data === 'string') {
  90610. gltf.json = parseJSON(data);
  90611. } else if (data instanceof ArrayBuffer) {
  90612. const glb = {};
  90613. byteOffset = parseGLBSync(glb, data, byteOffset, options.glb);
  90614. assert$1(glb.type === 'glTF', "Invalid GLB magic string ".concat(glb.type));
  90615. gltf._glb = glb;
  90616. gltf.json = glb.json;
  90617. } else {
  90618. assert$1(false, 'GLTF: must be ArrayBuffer or string');
  90619. }
  90620. const buffers = gltf.json.buffers || [];
  90621. gltf.buffers = new Array(buffers.length).fill(null);
  90622. if (gltf._glb && gltf._glb.header.hasBinChunk) {
  90623. const {
  90624. binChunks
  90625. } = gltf._glb;
  90626. gltf.buffers[0] = {
  90627. arrayBuffer: binChunks[0].arrayBuffer,
  90628. byteOffset: binChunks[0].byteOffset,
  90629. byteLength: binChunks[0].byteLength
  90630. };
  90631. }
  90632. const images = gltf.json.images || [];
  90633. gltf.images = new Array(images.length).fill({});
  90634. }
  90635. async function loadBuffers(gltf, options, context) {
  90636. const buffers = gltf.json.buffers || [];
  90637. for (let i = 0; i < buffers.length; ++i) {
  90638. const buffer = buffers[i];
  90639. if (buffer.uri) {
  90640. var _context$fetch, _response$arrayBuffer;
  90641. const {
  90642. fetch
  90643. } = context;
  90644. assert$1(fetch);
  90645. const uri = resolveUrl(buffer.uri, options);
  90646. const response = await (context === null || context === void 0 ? void 0 : (_context$fetch = context.fetch) === null || _context$fetch === void 0 ? void 0 : _context$fetch.call(context, uri));
  90647. const arrayBuffer = await (response === null || response === void 0 ? void 0 : (_response$arrayBuffer = response.arrayBuffer) === null || _response$arrayBuffer === void 0 ? void 0 : _response$arrayBuffer.call(response));
  90648. gltf.buffers[i] = {
  90649. arrayBuffer,
  90650. byteOffset: 0,
  90651. byteLength: arrayBuffer.byteLength
  90652. };
  90653. delete buffer.uri;
  90654. }
  90655. }
  90656. }
  90657. async function loadImages(gltf, options, context) {
  90658. const imageIndices = getReferencesImageIndices(gltf);
  90659. const images = gltf.json.images || [];
  90660. const promises = [];
  90661. for (const imageIndex of imageIndices) {
  90662. promises.push(loadImage(gltf, images[imageIndex], imageIndex, options, context));
  90663. }
  90664. return await Promise.all(promises);
  90665. }
  90666. function getReferencesImageIndices(gltf) {
  90667. const imageIndices = new Set();
  90668. const textures = gltf.json.textures || [];
  90669. for (const texture of textures) {
  90670. if (texture.source !== undefined) {
  90671. imageIndices.add(texture.source);
  90672. }
  90673. }
  90674. return Array.from(imageIndices).sort();
  90675. }
  90676. async function loadImage(gltf, image, index, options, context) {
  90677. const {
  90678. fetch,
  90679. parse
  90680. } = context;
  90681. let arrayBuffer;
  90682. if (image.uri) {
  90683. const uri = resolveUrl(image.uri, options);
  90684. const response = await fetch(uri);
  90685. arrayBuffer = await response.arrayBuffer();
  90686. }
  90687. if (Number.isFinite(image.bufferView)) {
  90688. const array = getTypedArrayForBufferView(gltf.json, gltf.buffers, image.bufferView);
  90689. arrayBuffer = sliceArrayBuffer(array.buffer, array.byteOffset, array.byteLength);
  90690. }
  90691. assert$1(arrayBuffer, 'glTF image has no data');
  90692. let parsedImage = await parse(arrayBuffer, [ImageLoader$1, BasisLoader], {
  90693. mimeType: image.mimeType,
  90694. basis: options.basis || {
  90695. format: selectSupportedBasisFormat()
  90696. }
  90697. }, context);
  90698. if (parsedImage && parsedImage[0]) {
  90699. parsedImage = {
  90700. compressed: true,
  90701. mipmaps: false,
  90702. width: parsedImage[0].width,
  90703. height: parsedImage[0].height,
  90704. data: parsedImage
  90705. };
  90706. }
  90707. gltf.images = gltf.images || [];
  90708. gltf.images[index] = parsedImage;
  90709. }
  90710. const GLTFLoader$1 = {
  90711. name: 'glTF',
  90712. id: 'gltf',
  90713. module: 'gltf',
  90714. version: VERSION$3,
  90715. extensions: ['gltf', 'glb'],
  90716. mimeTypes: ['model/gltf+json', 'model/gltf-binary'],
  90717. text: true,
  90718. binary: true,
  90719. tests: ['glTF'],
  90720. parse: parse$1,
  90721. options: {
  90722. gltf: {
  90723. normalize: true,
  90724. loadBuffers: true,
  90725. loadImages: true,
  90726. decompressMeshes: true,
  90727. postProcess: true
  90728. },
  90729. log: console
  90730. },
  90731. deprecatedOptions: {
  90732. fetchImages: 'gltf.loadImages',
  90733. createImages: 'gltf.loadImages',
  90734. decompress: 'gltf.decompressMeshes',
  90735. postProcess: 'gltf.postProcess',
  90736. gltf: {
  90737. decompress: 'gltf.decompressMeshes'
  90738. }
  90739. }
  90740. };
  90741. async function parse$1(arrayBuffer, options = {}, context) {
  90742. options = { ...GLTFLoader$1.options,
  90743. ...options
  90744. };
  90745. options.gltf = { ...GLTFLoader$1.options.gltf,
  90746. ...options.gltf
  90747. };
  90748. const {
  90749. byteOffset = 0
  90750. } = options;
  90751. const gltf = {};
  90752. return await parseGLTF(gltf, arrayBuffer, byteOffset, options, context);
  90753. }
  90754. const GLTF_FORMAT = {
  90755. URI: 0,
  90756. EMBEDDED: 1
  90757. };
  90758. function parse3DTileGLTFViewSync(tile, arrayBuffer, byteOffset, options) {
  90759. tile.rotateYtoZ = true;
  90760. const gltfByteLength = tile.byteOffset + tile.byteLength - byteOffset;
  90761. if (gltfByteLength === 0) {
  90762. throw new Error('glTF byte length must be greater than 0.');
  90763. }
  90764. tile.gltfUpAxis = options['3d-tiles'] && options['3d-tiles'].assetGltfUpAxis ? options['3d-tiles'].assetGltfUpAxis : 'Y';
  90765. tile.gltfArrayBuffer = sliceArrayBuffer(arrayBuffer, byteOffset, gltfByteLength);
  90766. tile.gltfByteOffset = 0;
  90767. tile.gltfByteLength = gltfByteLength;
  90768. if (byteOffset % 4 === 0) ; else {
  90769. console.warn("".concat(tile.type, ": embedded glb is not aligned to a 4-byte boundary."));
  90770. }
  90771. return tile.byteOffset + tile.byteLength;
  90772. }
  90773. async function extractGLTF(tile, gltfFormat, options, context) {
  90774. const tile3DOptions = options['3d-tiles'] || {};
  90775. extractGLTFBufferOrURL(tile, gltfFormat);
  90776. if (tile3DOptions.loadGLTF) {
  90777. const {
  90778. parse,
  90779. fetch
  90780. } = context;
  90781. if (tile.gltfUrl) {
  90782. tile.gltfArrayBuffer = await fetch(tile.gltfUrl, options);
  90783. tile.gltfByteOffset = 0;
  90784. }
  90785. if (tile.gltfArrayBuffer) {
  90786. tile.gltf = await parse(tile.gltfArrayBuffer, GLTFLoader$1, options, context);
  90787. delete tile.gltfArrayBuffer;
  90788. delete tile.gltfByteOffset;
  90789. delete tile.gltfByteLength;
  90790. }
  90791. }
  90792. }
  90793. function extractGLTFBufferOrURL(tile, gltfFormat, options) {
  90794. switch (gltfFormat) {
  90795. case GLTF_FORMAT.URI:
  90796. const gltfUrlBytes = new Uint8Array(tile.gltfArrayBuffer, tile.gltfByteOffset);
  90797. const textDecoder = new TextDecoder();
  90798. const gltfUrl = textDecoder.decode(gltfUrlBytes);
  90799. tile.gltfUrl = gltfUrl.replace(/[\s\0]+$/, '');
  90800. delete tile.gltfArrayBuffer;
  90801. delete tile.gltfByteOffset;
  90802. delete tile.gltfByteLength;
  90803. break;
  90804. case GLTF_FORMAT.EMBEDDED:
  90805. break;
  90806. default:
  90807. throw new Error('b3dm: Illegal glTF format field');
  90808. }
  90809. }
  90810. async function parseBatchedModel3DTile(tile, arrayBuffer, byteOffset, options, context) {
  90811. var _tile$gltf;
  90812. byteOffset = parseBatchedModel(tile, arrayBuffer, byteOffset, options);
  90813. await extractGLTF(tile, GLTF_FORMAT.EMBEDDED, options, context);
  90814. const extensions = tile === null || tile === void 0 ? void 0 : (_tile$gltf = tile.gltf) === null || _tile$gltf === void 0 ? void 0 : _tile$gltf.extensions;
  90815. if (extensions && extensions.CESIUM_RTC) {
  90816. tile.rtcCenter = extensions.CESIUM_RTC.center;
  90817. }
  90818. return byteOffset;
  90819. }
  90820. function parseBatchedModel(tile, arrayBuffer, byteOffset, options, context) {
  90821. byteOffset = parse3DTileHeaderSync(tile, arrayBuffer, byteOffset);
  90822. byteOffset = parse3DTileTablesHeaderSync(tile, arrayBuffer, byteOffset);
  90823. byteOffset = parse3DTileTablesSync(tile, arrayBuffer, byteOffset);
  90824. byteOffset = parse3DTileGLTFViewSync(tile, arrayBuffer, byteOffset, options);
  90825. const featureTable = new Tile3DFeatureTable(tile.featureTableJson, tile.featureTableBinary);
  90826. tile.rtcCenter = featureTable.getGlobalProperty('RTC_CENTER', GL$1.FLOAT, 3);
  90827. return byteOffset;
  90828. }
  90829. async function parseInstancedModel3DTile(tile, arrayBuffer, byteOffset, options, context) {
  90830. byteOffset = parseInstancedModel(tile, arrayBuffer, byteOffset, options);
  90831. await extractGLTF(tile, tile.gltfFormat, options, context);
  90832. return byteOffset;
  90833. }
  90834. function parseInstancedModel(tile, arrayBuffer, byteOffset, options, context) {
  90835. byteOffset = parse3DTileHeaderSync(tile, arrayBuffer, byteOffset);
  90836. if (tile.version !== 1) {
  90837. throw new Error("Instanced 3D Model version ".concat(tile.version, " is not supported"));
  90838. }
  90839. byteOffset = parse3DTileTablesHeaderSync(tile, arrayBuffer, byteOffset);
  90840. const view = new DataView(arrayBuffer);
  90841. tile.gltfFormat = view.getUint32(byteOffset, true);
  90842. byteOffset += 4;
  90843. byteOffset = parse3DTileTablesSync(tile, arrayBuffer, byteOffset);
  90844. byteOffset = parse3DTileGLTFViewSync(tile, arrayBuffer, byteOffset, options);
  90845. if (tile.featureTableJsonByteLength === 0) {
  90846. throw new Error('i3dm parser: featureTableJsonByteLength is zero.');
  90847. }
  90848. const featureTable = new Tile3DFeatureTable(tile.featureTableJson, tile.featureTableBinary);
  90849. const instancesLength = featureTable.getGlobalProperty('INSTANCES_LENGTH');
  90850. featureTable.featuresLength = instancesLength;
  90851. if (!Number.isFinite(instancesLength)) {
  90852. throw new Error('i3dm parser: INSTANCES_LENGTH must be defined');
  90853. }
  90854. tile.eastNorthUp = featureTable.getGlobalProperty('EAST_NORTH_UP');
  90855. tile.rtcCenter = featureTable.getGlobalProperty('RTC_CENTER', GL$1.FLOAT, 3);
  90856. const batchTable = new Tile3DBatchTableParser(tile.batchTableJson, tile.batchTableBinary, instancesLength);
  90857. extractInstancedAttributes(tile, featureTable, batchTable, instancesLength);
  90858. return byteOffset;
  90859. }
  90860. function extractInstancedAttributes(tile, featureTable, batchTable, instancesLength) {
  90861. const collectionOptions = {
  90862. instances: new Array(instancesLength),
  90863. batchTable: tile._batchTable,
  90864. cull: false,
  90865. url: undefined,
  90866. gltf: undefined,
  90867. basePath: undefined,
  90868. incrementallyLoadTextures: false,
  90869. forwardAxis: [1, 0, 0]
  90870. };
  90871. const instances = collectionOptions.instances;
  90872. const instancePosition = new Vector3$1();
  90873. new Vector3$1();
  90874. new Vector3$1();
  90875. new Vector3$1();
  90876. const instanceRotation = new Matrix3$1();
  90877. const instanceQuaternion = new Quaternion$1();
  90878. const instanceScale = new Vector3$1();
  90879. const instanceTranslationRotationScale = {};
  90880. const instanceTransform = new Matrix4$1();
  90881. const scratch1 = [];
  90882. const scratch2 = [];
  90883. const scratchVector1 = new Vector3$1();
  90884. const scratchVector2 = new Vector3$1();
  90885. for (let i = 0; i < instancesLength; i++) {
  90886. let position;
  90887. if (featureTable.hasProperty('POSITION')) {
  90888. position = featureTable.getProperty('POSITION', GL$1.FLOAT, 3, i, instancePosition);
  90889. } else if (featureTable.hasProperty('POSITION_QUANTIZED')) {
  90890. position = featureTable.getProperty('POSITION_QUANTIZED', GL$1.UNSIGNED_SHORT, 3, i, instancePosition);
  90891. const quantizedVolumeOffset = featureTable.getGlobalProperty('QUANTIZED_VOLUME_OFFSET', GL$1.FLOAT, 3, scratchVector1);
  90892. if (!quantizedVolumeOffset) {
  90893. throw new Error('i3dm parser: QUANTIZED_VOLUME_OFFSET must be defined for quantized positions.');
  90894. }
  90895. const quantizedVolumeScale = featureTable.getGlobalProperty('QUANTIZED_VOLUME_SCALE', GL$1.FLOAT, 3, scratchVector2);
  90896. if (!quantizedVolumeScale) {
  90897. throw new Error('i3dm parser: QUANTIZED_VOLUME_SCALE must be defined for quantized positions.');
  90898. }
  90899. const MAX_UNSIGNED_SHORT = 65535.0;
  90900. for (let j = 0; j < 3; j++) {
  90901. position[j] = position[j] / MAX_UNSIGNED_SHORT * quantizedVolumeScale[j] + quantizedVolumeOffset[j];
  90902. }
  90903. }
  90904. if (!position) {
  90905. throw new Error('i3dm: POSITION or POSITION_QUANTIZED must be defined for each instance.');
  90906. }
  90907. instancePosition.copy(position);
  90908. instanceTranslationRotationScale.translation = instancePosition;
  90909. tile.normalUp = featureTable.getProperty('NORMAL_UP', GL$1.FLOAT, 3, i, scratch1);
  90910. tile.normalRight = featureTable.getProperty('NORMAL_RIGHT', GL$1.FLOAT, 3, i, scratch2);
  90911. if (tile.normalUp) {
  90912. if (!tile.normalRight) {
  90913. throw new Error('i3dm: Custom orientation requires both NORMAL_UP and NORMAL_RIGHT.');
  90914. }
  90915. tile.hasCustomOrientation = true;
  90916. } else {
  90917. tile.octNormalUp = featureTable.getProperty('NORMAL_UP_OCT32P', GL$1.UNSIGNED_SHORT, 2, scratch1);
  90918. tile.octNormalRight = featureTable.getProperty('NORMAL_RIGHT_OCT32P', GL$1.UNSIGNED_SHORT, 2, scratch2);
  90919. if (tile.octNormalUp) {
  90920. if (!tile.octNormalRight) {
  90921. throw new Error('i3dm: oct-encoded orientation requires NORMAL_UP_OCT32P and NORMAL_RIGHT_OCT32P');
  90922. }
  90923. throw new Error('i3dm: oct-encoded orientation not implemented');
  90924. } else if (tile.eastNorthUp) {
  90925. Ellipsoid.WGS84.eastNorthUpToFixedFrame(instancePosition, instanceTransform);
  90926. instanceTransform.getRotationMatrix3(instanceRotation);
  90927. } else {
  90928. instanceRotation.identity();
  90929. }
  90930. }
  90931. instanceQuaternion.fromMatrix3(instanceRotation);
  90932. instanceTranslationRotationScale.rotation = instanceQuaternion;
  90933. instanceScale.set(1.0, 1.0, 1.0);
  90934. const scale = featureTable.getProperty('SCALE', GL$1.FLOAT, 1, i);
  90935. if (Number.isFinite(scale)) {
  90936. instanceScale.multiplyByScalar(scale);
  90937. }
  90938. const nonUniformScale = featureTable.getProperty('SCALE_NON_UNIFORM', GL$1.FLOAT, 3, i, scratch1);
  90939. if (nonUniformScale) {
  90940. instanceScale.scale(nonUniformScale);
  90941. }
  90942. instanceTranslationRotationScale.scale = instanceScale;
  90943. let batchId = featureTable.getProperty('BATCH_ID', GL$1.UNSIGNED_SHORT, 1, i);
  90944. if (batchId === undefined) {
  90945. batchId = i;
  90946. }
  90947. const rotationMatrix = new Matrix4$1().fromQuaternion(instanceTranslationRotationScale.rotation);
  90948. instanceTransform.identity();
  90949. instanceTransform.translate(instanceTranslationRotationScale.translation);
  90950. instanceTransform.multiplyRight(rotationMatrix);
  90951. instanceTransform.scale(instanceTranslationRotationScale.scale);
  90952. const modelMatrix = instanceTransform.clone();
  90953. instances[i] = {
  90954. modelMatrix,
  90955. batchId
  90956. };
  90957. }
  90958. tile.instances = instances;
  90959. }
  90960. async function parseComposite3DTile(tile, arrayBuffer, byteOffset, options, context, parse3DTile) {
  90961. byteOffset = parse3DTileHeaderSync(tile, arrayBuffer, byteOffset);
  90962. const view = new DataView(arrayBuffer);
  90963. tile.tilesLength = view.getUint32(byteOffset, true);
  90964. byteOffset += 4;
  90965. tile.tiles = [];
  90966. while (tile.tiles.length < tile.tilesLength && tile.byteLength - byteOffset > 12) {
  90967. const subtile = {};
  90968. tile.tiles.push(subtile);
  90969. byteOffset = await parse3DTile(arrayBuffer, byteOffset, options, context, subtile);
  90970. }
  90971. return byteOffset;
  90972. }
  90973. async function parseGltf3DTile(tile, arrayBuffer, options, context) {
  90974. tile.rotateYtoZ = true;
  90975. tile.gltfUpAxis = options['3d-tiles'] && options['3d-tiles'].assetGltfUpAxis ? options['3d-tiles'].assetGltfUpAxis : 'Y';
  90976. const {
  90977. parse
  90978. } = context;
  90979. tile.gltf = await parse(arrayBuffer, GLTFLoader$1, options, context);
  90980. }
  90981. async function parse3DTile(arrayBuffer, byteOffset = 0, options, context, tile = {}) {
  90982. tile.byteOffset = byteOffset;
  90983. tile.type = getMagicString$1(arrayBuffer, byteOffset);
  90984. switch (tile.type) {
  90985. case TILE3D_TYPE.COMPOSITE:
  90986. return await parseComposite3DTile(tile, arrayBuffer, byteOffset, options, context, parse3DTile);
  90987. case TILE3D_TYPE.BATCHED_3D_MODEL:
  90988. return await parseBatchedModel3DTile(tile, arrayBuffer, byteOffset, options, context);
  90989. case TILE3D_TYPE.GLTF:
  90990. return await parseGltf3DTile(tile, arrayBuffer, options, context);
  90991. case TILE3D_TYPE.INSTANCED_3D_MODEL:
  90992. return await parseInstancedModel3DTile(tile, arrayBuffer, byteOffset, options, context);
  90993. case TILE3D_TYPE.POINT_CLOUD:
  90994. return await parsePointCloud3DTile(tile, arrayBuffer, byteOffset, options, context);
  90995. default:
  90996. throw new Error("3DTileLoader: unknown type ".concat(tile.type));
  90997. }
  90998. }
  90999. const SUBTREE_FILE_MAGIC = 0x74627573;
  91000. const SUBTREE_FILE_VERSION = 1;
  91001. async function parse3DTilesSubtree(data) {
  91002. const magic = new Uint32Array(data.slice(0, 4));
  91003. if (magic[0] !== SUBTREE_FILE_MAGIC) {
  91004. throw new Error('Wrong subtree file magic number');
  91005. }
  91006. const version = new Uint32Array(data.slice(4, 8));
  91007. if (version[0] !== SUBTREE_FILE_VERSION) {
  91008. throw new Error('Wrong subtree file verson, must be 1');
  91009. }
  91010. const jsonByteLength = parseUint64Value(data.slice(8, 16));
  91011. const stringAttribute = new Uint8Array(data, 24, jsonByteLength);
  91012. const textDecoder = new TextDecoder('utf8');
  91013. const string = textDecoder.decode(stringAttribute);
  91014. const subtree = JSON.parse(string);
  91015. const binaryByteLength = parseUint64Value(data.slice(16, 24));
  91016. let internalBinaryBuffer = new ArrayBuffer(0);
  91017. if (binaryByteLength) {
  91018. internalBinaryBuffer = data.slice(24 + jsonByteLength);
  91019. }
  91020. if ('bufferView' in subtree.tileAvailability) {
  91021. subtree.tileAvailability.explicitBitstream = await getExplicitBitstream(subtree, 'tileAvailability', internalBinaryBuffer);
  91022. }
  91023. if ('bufferView' in subtree.contentAvailability) {
  91024. subtree.contentAvailability.explicitBitstream = await getExplicitBitstream(subtree, 'contentAvailability', internalBinaryBuffer);
  91025. }
  91026. if ('bufferView' in subtree.childSubtreeAvailability) {
  91027. subtree.childSubtreeAvailability.explicitBitstream = await getExplicitBitstream(subtree, 'childSubtreeAvailability', internalBinaryBuffer);
  91028. }
  91029. return subtree;
  91030. }
  91031. async function getExplicitBitstream(subtree, name, internalBinaryBuffer) {
  91032. const bufferViewIndex = subtree[name].bufferView;
  91033. const bufferView = subtree.bufferViews[bufferViewIndex];
  91034. const buffer = subtree.buffers[bufferView.buffer];
  91035. if (buffer.uri) {
  91036. const response = await fetchFile(buffer.uri);
  91037. const data = await response.arrayBuffer();
  91038. return new Uint8Array(data, bufferView.byteOffset, bufferView.byteLength);
  91039. }
  91040. return new Uint8Array(internalBinaryBuffer, bufferView.byteOffset, bufferView.byteLength);
  91041. }
  91042. function parseUint64Value(buffer) {
  91043. const dataView = new DataView(buffer);
  91044. const left = dataView.getUint32(0, true);
  91045. const right = dataView.getUint32(4, true);
  91046. return left + 2 ** 32 * right;
  91047. }
  91048. const Tile3DSubtreeLoader = {
  91049. id: '3d-tiles-subtree',
  91050. name: '3D Tiles Subtree',
  91051. module: '3d-tiles',
  91052. version: VERSION$5,
  91053. extensions: ['subtree'],
  91054. mimeTypes: ['application/octet-stream'],
  91055. tests: ['subtree'],
  91056. parse: parse3DTilesSubtree,
  91057. options: {}
  91058. };
  91059. const QUADTREE_DEVISION_COUNT = 4;
  91060. const OCTREE_DEVISION_COUNT = 8;
  91061. const SUBDIVISION_COUNT_MAP = {
  91062. QUADTREE: QUADTREE_DEVISION_COUNT,
  91063. OCTREE: OCTREE_DEVISION_COUNT
  91064. };
  91065. async function parseImplicitTiles(subtree, options, parentData = {
  91066. mortonIndex: 0,
  91067. x: 0,
  91068. y: 0,
  91069. z: 0
  91070. }, childIndex = 0, level = 0, globalData = {
  91071. level: 0,
  91072. mortonIndex: 0,
  91073. x: 0,
  91074. y: 0,
  91075. z: 0
  91076. }) {
  91077. const {
  91078. subdivisionScheme,
  91079. subtreeLevels,
  91080. maximumLevel,
  91081. contentUrlTemplate,
  91082. subtreesUriTemplate,
  91083. basePath
  91084. } = options;
  91085. const tile = {
  91086. children: [],
  91087. lodMetricValue: 0,
  91088. contentUrl: ''
  91089. };
  91090. const childrenPerTile = SUBDIVISION_COUNT_MAP[subdivisionScheme];
  91091. const childX = childIndex & 0b01;
  91092. const childY = childIndex >> 1 & 0b01;
  91093. const childZ = childIndex >> 2 & 0b01;
  91094. const levelOffset = (childrenPerTile ** level - 1) / (childrenPerTile - 1);
  91095. let childTileMortonIndex = concatBits(parentData.mortonIndex, childIndex);
  91096. let tileAvailabilityIndex = levelOffset + childTileMortonIndex;
  91097. let childTileX = concatBits(parentData.x, childX);
  91098. let childTileY = concatBits(parentData.y, childY);
  91099. let childTileZ = concatBits(parentData.z, childZ);
  91100. let isChildSubtreeAvailable = false;
  91101. if (level + 1 > subtreeLevels) {
  91102. isChildSubtreeAvailable = getAvailabilityResult(subtree.childSubtreeAvailability, childTileMortonIndex);
  91103. }
  91104. const x = concatBits(globalData.x, childTileX);
  91105. const y = concatBits(globalData.y, childTileY);
  91106. const z = concatBits(globalData.z, childTileZ);
  91107. const lev = level + globalData.level;
  91108. if (isChildSubtreeAvailable) {
  91109. const subtreePath = "".concat(basePath, "/").concat(subtreesUriTemplate);
  91110. const childSubtreeUrl = replaceContentUrlTemplate(subtreePath, lev, x, y, z);
  91111. const childSubtree = await load(childSubtreeUrl, Tile3DSubtreeLoader);
  91112. subtree = childSubtree;
  91113. globalData.mortonIndex = childTileMortonIndex;
  91114. globalData.x = childTileX;
  91115. globalData.y = childTileY;
  91116. globalData.z = childTileZ;
  91117. globalData.level = level;
  91118. childTileMortonIndex = 0;
  91119. tileAvailabilityIndex = 0;
  91120. childTileX = 0;
  91121. childTileY = 0;
  91122. childTileZ = 0;
  91123. level = 0;
  91124. }
  91125. const isTileAvailable = getAvailabilityResult(subtree.tileAvailability, tileAvailabilityIndex);
  91126. if (!isTileAvailable || level > maximumLevel) {
  91127. return tile;
  91128. }
  91129. const isContentAvailable = getAvailabilityResult(subtree.contentAvailability, tileAvailabilityIndex);
  91130. if (isContentAvailable) {
  91131. tile.contentUrl = replaceContentUrlTemplate(contentUrlTemplate, lev, x, y, z);
  91132. }
  91133. const childTileLevel = level + 1;
  91134. const pData = {
  91135. mortonIndex: childTileMortonIndex,
  91136. x: childTileX,
  91137. y: childTileY,
  91138. z: childTileZ
  91139. };
  91140. for (let index = 0; index < childrenPerTile; index++) {
  91141. const currentTile = await parseImplicitTiles(subtree, options, pData, index, childTileLevel, globalData);
  91142. if (currentTile.contentUrl || currentTile.children.length) {
  91143. const globalLevel = lev + 1;
  91144. const childCoordinates = {
  91145. childTileX,
  91146. childTileY,
  91147. childTileZ
  91148. };
  91149. const formattedTile = formatTileData(currentTile, globalLevel, childCoordinates, options);
  91150. tile.children.push(formattedTile);
  91151. }
  91152. }
  91153. return tile;
  91154. }
  91155. function getAvailabilityResult(availabilityData, index) {
  91156. if ('constant' in availabilityData) {
  91157. return Boolean(availabilityData.constant);
  91158. }
  91159. if (availabilityData.explicitBitstream) {
  91160. return getBooleanValueFromBitstream(index, availabilityData.explicitBitstream);
  91161. }
  91162. return false;
  91163. }
  91164. function formatTileData(tile, level, childCoordinates, options) {
  91165. const {
  91166. basePath,
  91167. refine,
  91168. getRefine,
  91169. lodMetricType,
  91170. getTileType,
  91171. rootLodMetricValue,
  91172. rootBoundingVolume
  91173. } = options;
  91174. const uri = tile.contentUrl && tile.contentUrl.replace("".concat(basePath, "/"), '');
  91175. const lodMetricValue = rootLodMetricValue / 2 ** level;
  91176. const boundingVolume = calculateBoundingVolumeForChildTile(level, rootBoundingVolume, childCoordinates);
  91177. return {
  91178. children: tile.children,
  91179. contentUrl: tile.contentUrl,
  91180. content: {
  91181. uri
  91182. },
  91183. id: tile.contentUrl,
  91184. refine: getRefine(refine),
  91185. type: getTileType(tile),
  91186. lodMetricType,
  91187. lodMetricValue,
  91188. boundingVolume
  91189. };
  91190. }
  91191. function calculateBoundingVolumeForChildTile(level, rootBoundingVolume, childCoordinates) {
  91192. if (rootBoundingVolume.region) {
  91193. const {
  91194. childTileX,
  91195. childTileY,
  91196. childTileZ
  91197. } = childCoordinates;
  91198. const [west, south, east, north, minimumHeight, maximumHeight] = rootBoundingVolume.region;
  91199. const boundingVolumesCount = 2 ** level;
  91200. const sizeX = (east - west) / boundingVolumesCount;
  91201. const sizeY = (north - south) / boundingVolumesCount;
  91202. const sizeZ = (maximumHeight - minimumHeight) / boundingVolumesCount;
  91203. const [childWest, childEast] = [west + sizeX * childTileX, west + sizeX * (childTileX + 1)];
  91204. const [childSouth, childNorth] = [south + sizeY * childTileY, south + sizeY * (childTileY + 1)];
  91205. const [childMinimumHeight, childMaximumHeight] = [minimumHeight + sizeZ * childTileZ, minimumHeight + sizeZ * (childTileZ + 1)];
  91206. return {
  91207. region: [childWest, childSouth, childEast, childNorth, childMinimumHeight, childMaximumHeight]
  91208. };
  91209. }
  91210. console.warn('Unsupported bounding volume type: ', rootBoundingVolume);
  91211. return null;
  91212. }
  91213. function concatBits(first, second) {
  91214. return parseInt(first.toString(2) + second.toString(2), 2);
  91215. }
  91216. function replaceContentUrlTemplate(templateUrl, level, x, y, z) {
  91217. const mapUrl = generateMapUrl({
  91218. level,
  91219. x,
  91220. y,
  91221. z
  91222. });
  91223. return templateUrl.replace(/{level}|{x}|{y}|{z}/gi, matched => mapUrl[matched]);
  91224. }
  91225. function generateMapUrl(items) {
  91226. const mapUrl = {};
  91227. for (const key in items) {
  91228. mapUrl["{".concat(key, "}")] = items[key];
  91229. }
  91230. return mapUrl;
  91231. }
  91232. function getBooleanValueFromBitstream(availabilityIndex, availabilityBuffer) {
  91233. const byteIndex = Math.floor(availabilityIndex / 8);
  91234. const bitIndex = availabilityIndex % 8;
  91235. const bitValue = availabilityBuffer[byteIndex] >> bitIndex & 1;
  91236. return bitValue === 1;
  91237. }
  91238. function getTileType(tile) {
  91239. if (!tile.contentUrl) {
  91240. return TILE_TYPE.EMPTY;
  91241. }
  91242. const contentUrl = tile.contentUrl;
  91243. const fileExtension = contentUrl.split('.').pop();
  91244. switch (fileExtension) {
  91245. case 'pnts':
  91246. return TILE_TYPE.POINTCLOUD;
  91247. case 'i3dm':
  91248. case 'b3dm':
  91249. case 'glb':
  91250. case 'gltf':
  91251. return TILE_TYPE.SCENEGRAPH;
  91252. default:
  91253. return fileExtension;
  91254. }
  91255. }
  91256. function getRefine(refine) {
  91257. switch (refine) {
  91258. case 'REPLACE':
  91259. case 'replace':
  91260. return TILE_REFINEMENT.REPLACE;
  91261. case 'ADD':
  91262. case 'add':
  91263. return TILE_REFINEMENT.ADD;
  91264. default:
  91265. return refine;
  91266. }
  91267. }
  91268. function normalizeTileData(tile, options) {
  91269. if (!tile) {
  91270. return null;
  91271. }
  91272. if (tile.content) {
  91273. const contentUri = tile.content.uri || tile.content.url;
  91274. tile.contentUrl = "".concat(options.basePath, "/").concat(contentUri);
  91275. }
  91276. tile.id = tile.contentUrl;
  91277. tile.lodMetricType = LOD_METRIC_TYPE.GEOMETRIC_ERROR;
  91278. tile.lodMetricValue = tile.geometricError;
  91279. tile.transformMatrix = tile.transform;
  91280. tile.type = getTileType(tile);
  91281. tile.refine = getRefine(tile.refine);
  91282. return tile;
  91283. }
  91284. function normalizeTileHeaders(tileset) {
  91285. const basePath = tileset.basePath;
  91286. const root = normalizeTileData(tileset.root, tileset);
  91287. const stack = [];
  91288. stack.push(root);
  91289. while (stack.length > 0) {
  91290. const tile = stack.pop() || {};
  91291. const children = tile.children || [];
  91292. for (const childHeader of children) {
  91293. normalizeTileData(childHeader, {
  91294. basePath
  91295. });
  91296. stack.push(childHeader);
  91297. }
  91298. }
  91299. return root;
  91300. }
  91301. async function normalizeImplicitTileHeaders(tileset) {
  91302. if (!tileset.root) {
  91303. return null;
  91304. }
  91305. const basePath = tileset.basePath;
  91306. const implicitTilingExtension = tileset.root.extensions['3DTILES_implicit_tiling'];
  91307. const {
  91308. subdivisionScheme,
  91309. maximumLevel,
  91310. subtreeLevels,
  91311. subtrees: {
  91312. uri: subtreesUriTemplate
  91313. }
  91314. } = implicitTilingExtension;
  91315. const subtreeUrl = replaceContentUrlTemplate(subtreesUriTemplate, 0, 0, 0, 0);
  91316. const rootSubtreeUrl = "".concat(basePath, "/").concat(subtreeUrl);
  91317. const rootSubtree = await load(rootSubtreeUrl, Tile3DSubtreeLoader);
  91318. const contentUrlTemplate = "".concat(basePath, "/").concat(tileset.root.content.uri);
  91319. const refine = tileset.root.refine;
  91320. const rootLodMetricValue = tileset.root.geometricError;
  91321. const rootBoundingVolume = tileset.root.boundingVolume;
  91322. const options = {
  91323. contentUrlTemplate,
  91324. subtreesUriTemplate,
  91325. subdivisionScheme,
  91326. subtreeLevels,
  91327. maximumLevel,
  91328. refine,
  91329. basePath,
  91330. lodMetricType: LOD_METRIC_TYPE.GEOMETRIC_ERROR,
  91331. rootLodMetricValue,
  91332. rootBoundingVolume,
  91333. getTileType,
  91334. getRefine
  91335. };
  91336. return await normalizeImplicitTileData(tileset.root, rootSubtree, options);
  91337. }
  91338. async function normalizeImplicitTileData(tile, rootSubtree, options) {
  91339. if (!tile) {
  91340. return null;
  91341. }
  91342. tile.lodMetricType = LOD_METRIC_TYPE.GEOMETRIC_ERROR;
  91343. tile.lodMetricValue = tile.geometricError;
  91344. tile.transformMatrix = tile.transform;
  91345. const {
  91346. children,
  91347. contentUrl
  91348. } = await parseImplicitTiles(rootSubtree, options);
  91349. if (contentUrl) {
  91350. tile.contentUrl = contentUrl;
  91351. tile.content = {
  91352. uri: contentUrl.replace("".concat(options.basePath, "/"), '')
  91353. };
  91354. }
  91355. tile.refine = getRefine(tile.refine);
  91356. tile.type = getTileType(tile);
  91357. tile.children = children;
  91358. tile.id = tile.contentUrl;
  91359. return tile;
  91360. }
  91361. const IMPLICIT_TILING_EXTENSION_NAME = '3DTILES_implicit_tiling';
  91362. const Tiles3DLoader = {
  91363. id: '3d-tiles',
  91364. name: '3D Tiles',
  91365. module: '3d-tiles',
  91366. version: VERSION$5,
  91367. extensions: ['cmpt', 'pnts', 'b3dm', 'i3dm'],
  91368. mimeTypes: ['application/octet-stream'],
  91369. tests: ['cmpt', 'pnts', 'b3dm', 'i3dm'],
  91370. parse: parse$4,
  91371. options: {
  91372. '3d-tiles': {
  91373. loadGLTF: true,
  91374. decodeQuantizedPositions: false,
  91375. isTileset: 'auto',
  91376. assetGltfUpAxis: null
  91377. }
  91378. }
  91379. };
  91380. function getBaseUri(tileset) {
  91381. return dirname(tileset.url);
  91382. }
  91383. async function parseTile(arrayBuffer, options, context) {
  91384. const tile = {
  91385. content: {
  91386. featureIds: null
  91387. }
  91388. };
  91389. const byteOffset = 0;
  91390. await parse3DTile(arrayBuffer, byteOffset, options, context, tile.content);
  91391. return tile.content;
  91392. }
  91393. async function parseTileset(data, options, context) {
  91394. var _tilesetJson$root;
  91395. const tilesetJson = JSON.parse(new TextDecoder().decode(data));
  91396. tilesetJson.loader = options.loader || Tiles3DLoader;
  91397. tilesetJson.url = context.url;
  91398. tilesetJson.basePath = getBaseUri(tilesetJson);
  91399. tilesetJson.root = hasImplicitTilingExtension(tilesetJson) ? await normalizeImplicitTileHeaders(tilesetJson) : normalizeTileHeaders(tilesetJson);
  91400. tilesetJson.type = TILESET_TYPE.TILES3D;
  91401. tilesetJson.lodMetricType = LOD_METRIC_TYPE.GEOMETRIC_ERROR;
  91402. tilesetJson.lodMetricValue = ((_tilesetJson$root = tilesetJson.root) === null || _tilesetJson$root === void 0 ? void 0 : _tilesetJson$root.lodMetricValue) || 0;
  91403. return tilesetJson;
  91404. }
  91405. async function parse$4(data, options, context) {
  91406. const loaderOptions = options['3d-tiles'] || {};
  91407. let isTileset;
  91408. if (loaderOptions.isTileset === 'auto') {
  91409. isTileset = context.url && context.url.indexOf('.json') !== -1;
  91410. } else {
  91411. isTileset = loaderOptions.isTileset;
  91412. }
  91413. if (isTileset) {
  91414. data = await parseTileset(data, options, context);
  91415. } else {
  91416. data = await parseTile(data, options, context);
  91417. }
  91418. return data;
  91419. }
  91420. function hasImplicitTilingExtension(tilesetJson) {
  91421. var _tilesetJson$extensio, _tilesetJson$extensio2;
  91422. return (tilesetJson === null || tilesetJson === void 0 ? void 0 : (_tilesetJson$extensio = tilesetJson.extensionsRequired) === null || _tilesetJson$extensio === void 0 ? void 0 : _tilesetJson$extensio.includes(IMPLICIT_TILING_EXTENSION_NAME)) && (tilesetJson === null || tilesetJson === void 0 ? void 0 : (_tilesetJson$extensio2 = tilesetJson.extensionsUsed) === null || _tilesetJson$extensio2 === void 0 ? void 0 : _tilesetJson$extensio2.includes(IMPLICIT_TILING_EXTENSION_NAME));
  91423. }
  91424. const CESIUM_ION_URL = 'https://api.cesium.com/v1/assets';
  91425. async function getIonTilesetMetadata(accessToken, assetId) {
  91426. if (!assetId) {
  91427. const assets = await getIonAssets(accessToken);
  91428. for (const item of assets.items) {
  91429. if (item.type === '3DTILES') {
  91430. assetId = item.id;
  91431. }
  91432. }
  91433. }
  91434. const ionAssetMetadata = await getIonAssetMetadata(accessToken, assetId);
  91435. const {
  91436. type,
  91437. url
  91438. } = ionAssetMetadata;
  91439. assert$7(type === '3DTILES' && url);
  91440. ionAssetMetadata.headers = {
  91441. Authorization: "Bearer ".concat(ionAssetMetadata.accessToken)
  91442. };
  91443. return ionAssetMetadata;
  91444. }
  91445. async function getIonAssets(accessToken) {
  91446. assert$7(accessToken);
  91447. const url = CESIUM_ION_URL;
  91448. const headers = {
  91449. Authorization: "Bearer ".concat(accessToken)
  91450. };
  91451. const response = await fetchFile(url, {
  91452. fetch: {
  91453. headers
  91454. }
  91455. });
  91456. if (!response.ok) {
  91457. throw new Error(response.statusText);
  91458. }
  91459. return await response.json();
  91460. }
  91461. async function getIonAssetMetadata(accessToken, assetId) {
  91462. assert$7(accessToken, assetId);
  91463. const headers = {
  91464. Authorization: "Bearer ".concat(accessToken)
  91465. };
  91466. const url = "".concat(CESIUM_ION_URL, "/").concat(assetId);
  91467. let response = await fetchFile("".concat(url), {
  91468. fetch: {
  91469. headers
  91470. }
  91471. });
  91472. if (!response.ok) {
  91473. throw new Error(response.statusText);
  91474. }
  91475. let metadata = await response.json();
  91476. response = await fetchFile("".concat(url, "/endpoint"), {
  91477. fetch: {
  91478. headers
  91479. }
  91480. });
  91481. if (!response.ok) {
  91482. throw new Error(response.statusText);
  91483. }
  91484. const tilesetInfo = await response.json();
  91485. metadata = { ...metadata,
  91486. ...tilesetInfo
  91487. };
  91488. return metadata;
  91489. }
  91490. async function preload(url, options = {}) {
  91491. options = options['cesium-ion'] || {};
  91492. const {
  91493. accessToken
  91494. } = options;
  91495. let assetId = options.assetId;
  91496. if (!Number.isFinite(assetId)) {
  91497. const matched = url.match(/\/([0-9]+)\/tileset.json/);
  91498. assetId = matched && matched[1];
  91499. }
  91500. return getIonTilesetMetadata(accessToken, assetId);
  91501. }
  91502. const CesiumIonLoader = { ...Tiles3DLoader,
  91503. id: 'cesium-ion',
  91504. name: 'Cesium Ion',
  91505. preload,
  91506. parse: async (data, options, context) => {
  91507. options = { ...options
  91508. };
  91509. options['3d-tiles'] = options['cesium-ion'];
  91510. options.loader = CesiumIonLoader;
  91511. return Tiles3DLoader.parse(data, options, context);
  91512. },
  91513. options: {
  91514. 'cesium-ion': { ...Tiles3DLoader.options['3d-tiles'],
  91515. accessToken: null
  91516. }
  91517. }
  91518. };
  91519. // From https://github.com/potree/potree/blob/master/src/materials/PointCloudMaterial.js
  91520. function generateGradientTexture(gradient) {
  91521. const size = 64;
  91522. // create canvas
  91523. const canvas = document.createElement('canvas');
  91524. canvas.width = size;
  91525. canvas.height = size;
  91526. // get context
  91527. const context = canvas.getContext('2d');
  91528. // draw gradient
  91529. context.rect(0, 0, size, size);
  91530. const ctxGradient = context.createLinearGradient(0, 0, size, size);
  91531. for (let i = 0; i < gradient.length; i++) {
  91532. const step = gradient[i];
  91533. ctxGradient.addColorStop(step[0], '#' + step[1].getHexString());
  91534. }
  91535. context.fillStyle = ctxGradient;
  91536. context.fill();
  91537. //let texture = new THREE.Texture(canvas);
  91538. const texture = new CanvasTexture(canvas);
  91539. texture.needsUpdate = true;
  91540. texture.minFilter = LinearFilter;
  91541. texture.wrapS = RepeatWrapping;
  91542. texture.wrapT = RepeatWrapping;
  91543. texture.repeat.set(2, 2);
  91544. // textureImage = texture.image;
  91545. return texture;
  91546. }
  91547. function getCameraFrustum(camera) {
  91548. camera.updateMatrix(); // make sure camera's local matrix is updated
  91549. camera.updateMatrixWorld(); // make sure camera's world matrix is updated
  91550. camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
  91551. const frustum = new Frustum();
  91552. frustum.setFromProjectionMatrix(new Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse));
  91553. return frustum;
  91554. }
  91555. function loadersPlaneToMesh(plane) {
  91556. const group = new Group();
  91557. // Create a basic rectangle geometry from math.gl plane
  91558. const planeGeometry = new PlaneGeometry(10, 5);
  91559. // Align the geometry to the plane
  91560. const coplanarPoint = new Vector3(...plane.projectPointOntoPlane([0, 0, 0]));
  91561. const normal = new Vector3(plane.normal.x, plane.normal.y, plane.normal.z);
  91562. const focalPoint = new Vector3().copy(coplanarPoint).add(normal);
  91563. planeGeometry.lookAt(focalPoint);
  91564. planeGeometry.translate(coplanarPoint.x, coplanarPoint.y, coplanarPoint.z);
  91565. // Edges
  91566. /*
  91567. const edges = new EdgesGeometry(planeGeometry)
  91568. var dispPlane = new LineSegments(edges, new LineBasicMaterial({ color: 0x00ffff }))*/
  91569. //plane
  91570. const material = new BasicMaterial({ color: 0x00ffff, side: DoubleSide });
  91571. const mesh = new Mesh(planeGeometry, material);
  91572. const arrowHelper = new ArrowHelper(normal, coplanarPoint, 5, 0xffff00);
  91573. group.add(arrowHelper);
  91574. group.add(mesh);
  91575. return group;
  91576. }
  91577. function loadersBoundingBoxToMesh(tile) {
  91578. // Create a basic rectangle geometry from math.gl half-axes
  91579. const { boundingVolume } = tile;
  91580. let redColor = 0;
  91581. if (tile.content) {
  91582. //redColor = Math.min((tile.content.byteLength != void 0 ? tile.content.byteLength : 0) / 500000, 1.0);
  91583. redColor = Math.min( tile.depth / 10 , 1.0); //改
  91584. }
  91585. const boxColor = new Color(redColor, 1.0, 0.0);
  91586. const boxGeometry = new BoxGeometry(1, 1, 1);
  91587. const boxTransform = new Matrix4();
  91588. if (boundingVolume.halfAxes) {
  91589. boxTransform.copy(getMatrix4FromHalfAxes(boundingVolume.halfAxes));
  91590. }
  91591. else if (boundingVolume.radius) {
  91592. boxGeometry.scale(boundingVolume.radius * 2, boundingVolume.radius * 2, boundingVolume.radius * 2);
  91593. }
  91594. boxTransform.premultiply((new Matrix4()).setPosition(...boundingVolume.center)); //add
  91595. boxGeometry.applyMatrix4(boxTransform);
  91596. const edges = new EdgesGeometry(boxGeometry);
  91597. const dispPlane = new LineSegments(edges, new LineBasicMaterial({ color: boxColor, transparent:true }));
  91598. //dispPlane.position.copy(new Vector3$1(...boundingVolume.center));
  91599. dispPlane.matrixAutoUpdate = false; //add
  91600. /* if(tile.content.byteLength == void 0){
  91601. let oldUpdate = dispPlane.updateMatrixWorld.bind(dispPlane)
  91602. dispPlane.updateMatrixWorld = (a,b)=>{
  91603. oldUpdate(a,b)
  91604. }
  91605. let oldU = dispPlane.updateMatrix.bind(dispPlane)
  91606. dispPlane.updateMatrix = (a,b)=>{
  91607. oldU(a,b)
  91608. }
  91609. } */
  91610. return dispPlane;
  91611. }
  91612. function getMatrix4FromHalfAxes(halfAxes) {
  91613. const m = halfAxes;
  91614. const rotateMatrix = new Matrix4().fromArray([
  91615. m[0] * 2,
  91616. m[1] * 2,
  91617. m[2] * 2,
  91618. 0,
  91619. m[3] * 2,
  91620. m[4] * 2,
  91621. m[5] * 2,
  91622. 0,
  91623. m[6] * 2,
  91624. m[7] * 2,
  91625. m[8] * 2,
  91626. 0,
  91627. 0,
  91628. 0,
  91629. 0,
  91630. 1,
  91631. ]);
  91632. return rotateMatrix;
  91633. }
  91634. /*
  91635. * from https://github.com/tentone/geo-three
  91636. * Tree-shaking did not work, probably due to static class methods
  91637. */
  91638. function datumsToSpherical(latitude, longitude) {
  91639. const EARTH_RADIUS = 6378137;
  91640. const EARTH_PERIMETER = 2 * Math.PI * EARTH_RADIUS;
  91641. const EARTH_ORIGIN = EARTH_PERIMETER / 2.0;
  91642. const x = longitude * EARTH_ORIGIN / 180.0;
  91643. let y = Math.log(Math.tan((90 + latitude) * Math.PI / 360.0)) / (Math.PI / 180.0);
  91644. y = y * EARTH_ORIGIN / 180.0;
  91645. return new Vector2(x, y);
  91646. }
  91647. const Gradients$1 = {
  91648. // From chroma spectral http://gka.github.io/chroma.js/
  91649. SPECTRAL: [
  91650. [0, new Color(0.3686, 0.3098, 0.6353)],
  91651. [0.1, new Color(0.1961, 0.5333, 0.7412)],
  91652. [0.2, new Color(0.4, 0.7608, 0.6471)],
  91653. [0.3, new Color(0.6706, 0.8667, 0.6431)],
  91654. [0.4, new Color(0.902, 0.9608, 0.5961)],
  91655. [0.5, new Color(1.0, 1.0, 0.749)],
  91656. [0.6, new Color(0.9961, 0.8784, 0.5451)],
  91657. [0.7, new Color(0.9922, 0.6824, 0.3804)],
  91658. [0.8, new Color(0.9569, 0.4275, 0.2627)],
  91659. [0.9, new Color(0.8353, 0.2431, 0.3098)],
  91660. [1, new Color(0.6196, 0.0039, 0.2588)],
  91661. ],
  91662. PLASMA: [
  91663. [0.0, new Color(0.241, 0.015, 0.61)],
  91664. [0.1, new Color(0.387, 0.001, 0.654)],
  91665. [0.2, new Color(0.524, 0.025, 0.653)],
  91666. [0.3, new Color(0.651, 0.125, 0.596)],
  91667. [0.4, new Color(0.752, 0.227, 0.513)],
  91668. [0.5, new Color(0.837, 0.329, 0.431)],
  91669. [0.6, new Color(0.907, 0.435, 0.353)],
  91670. [0.7, new Color(0.963, 0.554, 0.272)],
  91671. [0.8, new Color(0.992, 0.681, 0.195)],
  91672. [0.9, new Color(0.987, 0.822, 0.144)],
  91673. [1.0, new Color(0.94, 0.975, 0.131)],
  91674. ],
  91675. YELLOW_GREEN: [
  91676. [0, new Color(0.1647, 0.2824, 0.3451)],
  91677. [0.1, new Color(0.1338, 0.3555, 0.4227)],
  91678. [0.2, new Color(0.061, 0.4319, 0.4864)],
  91679. [0.3, new Color(0.0, 0.5099, 0.5319)],
  91680. [0.4, new Color(0.0, 0.5881, 0.5569)],
  91681. [0.5, new Color(0.137, 0.665, 0.5614)],
  91682. [0.6, new Color(0.2906, 0.7395, 0.5477)],
  91683. [0.7, new Color(0.4453, 0.8099, 0.5201)],
  91684. [0.8, new Color(0.6102, 0.8748, 0.485)],
  91685. [0.9, new Color(0.7883, 0.9323, 0.4514)],
  91686. [1, new Color(0.9804, 0.9804, 0.4314)],
  91687. ],
  91688. VIRIDIS: [
  91689. [0.0, new Color(0.267, 0.005, 0.329)],
  91690. [0.1, new Color(0.283, 0.141, 0.458)],
  91691. [0.2, new Color(0.254, 0.265, 0.53)],
  91692. [0.3, new Color(0.207, 0.372, 0.553)],
  91693. [0.4, new Color(0.164, 0.471, 0.558)],
  91694. [0.5, new Color(0.128, 0.567, 0.551)],
  91695. [0.6, new Color(0.135, 0.659, 0.518)],
  91696. [0.7, new Color(0.267, 0.749, 0.441)],
  91697. [0.8, new Color(0.478, 0.821, 0.318)],
  91698. [0.9, new Color(0.741, 0.873, 0.15)],
  91699. [1.0, new Color(0.993, 0.906, 0.144)],
  91700. ],
  91701. INFERNO: [
  91702. [0.0, new Color(0.077, 0.042, 0.206)],
  91703. [0.1, new Color(0.225, 0.036, 0.388)],
  91704. [0.2, new Color(0.373, 0.074, 0.432)],
  91705. [0.3, new Color(0.522, 0.128, 0.42)],
  91706. [0.4, new Color(0.665, 0.182, 0.37)],
  91707. [0.5, new Color(0.797, 0.255, 0.287)],
  91708. [0.6, new Color(0.902, 0.364, 0.184)],
  91709. [0.7, new Color(0.969, 0.516, 0.063)],
  91710. [0.8, new Color(0.988, 0.683, 0.072)],
  91711. [0.9, new Color(0.961, 0.859, 0.298)],
  91712. [1.0, new Color(0.988, 0.998, 0.645)],
  91713. ],
  91714. GRAYSCALE: [
  91715. [0, new Color(0, 0, 0)],
  91716. [1, new Color(1, 1, 1)],
  91717. ],
  91718. // 16 samples of the TURBU color scheme
  91719. // values taken from: https://gist.github.com/mikhailov-work/ee72ba4191942acecc03fe6da94fc73f
  91720. // original file licensed under Apache-2.0
  91721. TURBO: [
  91722. [0.0, new Color(0.18995, 0.07176, 0.23217)],
  91723. [0.07, new Color(0.25107, 0.25237, 0.63374)],
  91724. [0.13, new Color(0.27628, 0.42118, 0.89123)],
  91725. [0.2, new Color(0.25862, 0.57958, 0.99876)],
  91726. [0.27, new Color(0.15844, 0.73551, 0.92305)],
  91727. [0.33, new Color(0.09267, 0.86554, 0.7623)],
  91728. [0.4, new Color(0.19659, 0.94901, 0.59466)],
  91729. [0.47, new Color(0.42778, 0.99419, 0.38575)],
  91730. [0.53, new Color(0.64362, 0.98999, 0.23356)],
  91731. [0.6, new Color(0.80473, 0.92452, 0.20459)],
  91732. [0.67, new Color(0.93301, 0.81236, 0.22667)],
  91733. [0.73, new Color(0.99314, 0.67408, 0.20348)],
  91734. [0.8, new Color(0.9836, 0.49291, 0.12849)],
  91735. [0.87, new Color(0.92105, 0.31489, 0.05475)],
  91736. [0.93, new Color(0.81608, 0.18462, 0.01809)],
  91737. [1.0, new Color(0.66449, 0.08436, 0.00424)],
  91738. ],
  91739. RAINBOW: [
  91740. [0, new Color(0.278, 0, 0.714)],
  91741. [1 / 6, new Color(0, 0, 1)],
  91742. [2 / 6, new Color(0, 1, 1)],
  91743. [3 / 6, new Color(0, 1, 0)],
  91744. [4 / 6, new Color(1, 1, 0)],
  91745. [5 / 6, new Color(1, 0.64, 0)],
  91746. [1, new Color(1, 0, 0)],
  91747. ],
  91748. CONTOUR: [
  91749. [0.0, new Color(0, 0, 0)],
  91750. [0.03, new Color(0, 0, 0)],
  91751. [0.04, new Color(1, 1, 1)],
  91752. [1.0, new Color(1, 1, 1)],
  91753. ],
  91754. };
  91755. const PointCloudFS = `
  91756. varying vec3 vColor;
  91757. uniform float alpha;
  91758. void main() {
  91759. if (vColor == vec3(0.0, 0.0, 0.0)) {
  91760. discard;
  91761. } else {
  91762. gl_FragColor = vec4( vColor, alpha);
  91763. }
  91764. }
  91765. `;
  91766. const PointCloudVS = `
  91767. varying vec3 vColor;
  91768. uniform sampler2D gradient;
  91769. uniform sampler2D grayscale;
  91770. attribute float intensity;
  91771. attribute float classification;
  91772. uniform vec3 rootCenter;
  91773. uniform vec3 rootNormal;
  91774. uniform vec2 elevationRange;
  91775. uniform int coloring;
  91776. uniform bool hideGround;
  91777. uniform float maxIntensity;
  91778. uniform float intensityContrast;
  91779. uniform float pointSize;
  91780. #ifdef USE_COLOR
  91781. vec3 getRGB() {
  91782. vec3 rgb = color;
  91783. return rgb;
  91784. }
  91785. #endif
  91786. vec3 getElevation(){
  91787. vec4 world = modelMatrix * vec4( position, 1.0 );
  91788. float diff = abs(dot(rootNormal, (vec3(world) - rootCenter)));
  91789. float w = max(diff - elevationRange.x,0.0) / max(elevationRange.y - elevationRange.x,1.0);
  91790. vec3 cElevation = texture2D(gradient, vec2(w,1.0-w)).rgb;
  91791. return cElevation;
  91792. }
  91793. vec3 getIntensity(){
  91794. // TODO: real contrast enhancement. Check https://github.com/yuki-koyama/enhancer/blob/master/shaders/enhancer.fs
  91795. float intmod = pow(intensity, intensityContrast);
  91796. vec3 cIntensity = texture2D(grayscale, vec2(intmod / maxIntensity ,1.0-(intmod / maxIntensity))).rgb;
  91797. return cIntensity;
  91798. }
  91799. vec3 getClassification(){
  91800. float classNormalized = classification / 255.0;
  91801. vec3 cClassification = texture2D(gradient, vec2(classNormalized * 5.0,1.0-classNormalized * 5.0)).rgb;
  91802. return cClassification;
  91803. }
  91804. vec3 getColor(){
  91805. vec3 color;
  91806. if (hideGround && classification == 2.0) {
  91807. return vec3(0.0, 0.0, 0.0);
  91808. }
  91809. if (coloring == 1) {
  91810. color = getIntensity();
  91811. }
  91812. else if (coloring == 2) {
  91813. color = getClassification();
  91814. } else if (coloring == 3) {
  91815. color = getElevation();
  91816. }
  91817. #ifdef USE_COLOR
  91818. else if (coloring == 4) {
  91819. color = getRGB();
  91820. }
  91821. #endif
  91822. else {
  91823. color = vec3(1.0, 1.0, 1.0);
  91824. }
  91825. return color;
  91826. }
  91827. void main() {
  91828. vColor = getColor();
  91829. gl_PointSize = pointSize;
  91830. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  91831. }
  91832. `;
  91833. /** Types of coloring used when viewing point cloud tiles */
  91834. var PointCloudColoring;
  91835. (function (PointCloudColoring) {
  91836. PointCloudColoring[PointCloudColoring["Intensity"] = 1] = "Intensity";
  91837. PointCloudColoring[PointCloudColoring["Classification"] = 2] = "Classification";
  91838. PointCloudColoring[PointCloudColoring["Elevation"] = 3] = "Elevation";
  91839. PointCloudColoring[PointCloudColoring["RGB"] = 4] = "RGB";
  91840. PointCloudColoring[PointCloudColoring["White"] = 5] = "White";
  91841. })(PointCloudColoring || (PointCloudColoring = {}));
  91842. /** Types of shading used when viewing b3dm (mesh) tiles */
  91843. var Shading;
  91844. (function (Shading) {
  91845. Shading[Shading["FlatTexture"] = 1] = "FlatTexture";
  91846. Shading[Shading["ShadedTexture"] = 2] = "ShadedTexture";
  91847. Shading[Shading["ShadedNoTexture"] = 3] = "ShadedNoTexture";
  91848. })(Shading || (Shading = {}));
  91849. var GeoTransform;
  91850. (function (GeoTransform) {
  91851. GeoTransform[GeoTransform["Reset"] = 1] = "Reset";
  91852. GeoTransform[GeoTransform["Mercator"] = 2] = "Mercator";
  91853. GeoTransform[GeoTransform["WGS84Cartesian"] = 3] = "WGS84Cartesian";
  91854. })(GeoTransform || (GeoTransform = {}));
  91855. const gradient = Gradients$1.RAINBOW;
  91856. const gradientTexture = typeof document != 'undefined' ? generateGradientTexture(gradient) : null;
  91857. const grayscale = Gradients$1.GRAYSCALE;
  91858. const grayscaleTexture = typeof document != 'undefined' ? generateGradientTexture(grayscale) : null;
  91859. const defaultOptions = {
  91860. throttleRequests: true,
  91861. maxRequests: 64,
  91862. updateInterval: 0.1,
  91863. maxConcurrency: 1,
  91864. maximumScreenSpaceError: 16,
  91865. maximumMemoryUsage: 32,
  91866. viewDistanceScale: 1.0,
  91867. skipLevelOfDetail: false,
  91868. updateTransforms: true,
  91869. shading: Shading.FlatTexture,
  91870. transparent: false,
  91871. pointCloudColoring: PointCloudColoring.White,
  91872. pointSize: 1.0,
  91873. worker: true,
  91874. wireframe: false,
  91875. debug: false,
  91876. basisTranscoderPath: null,
  91877. dracoDecoderPath: null,
  91878. material: null,
  91879. computeNormals: false,
  91880. shaderCallback: null,
  91881. geoTransform: GeoTransform.Reset,
  91882. preloadTilesCount: null
  91883. };
  91884. /** 3D Tiles Loader */
  91885. class Loader3DTiles {
  91886. /**
  91887. * Loads a tileset of 3D Tiles according to the given {@link LoaderProps}
  91888. * @public
  91889. *
  91890. * @param props - Properties for this load call {@link LoaderProps}.
  91891. * @returns An object containing the 3D Model to be added to the scene
  91892. * and a runtime engine to be updated every frame.
  91893. */
  91894. static load(props) {
  91895. return __awaiter(this, void 0, void 0, function* () {
  91896. const options = Object.assign(Object.assign({}, defaultOptions), props.options);
  91897. const { url } = props;
  91898. const UPDATE_INTERVAL = options.updateInterval;
  91899. const MAX_DEPTH_FOR_ORIENTATION = 5;
  91900. const loadersGLOptions = {};
  91901. if (options.cesiumIONToken) {
  91902. loadersGLOptions['cesium-ion'] = {
  91903. accessToken: options.cesiumIONToken,
  91904. };
  91905. const metadata = yield CesiumIonLoader.preload(url, loadersGLOptions);
  91906. loadersGLOptions['fetch'] = { headers: metadata.headers };
  91907. }
  91908. if (props.loadingManager) {
  91909. props.loadingManager.itemStart(url);
  91910. }
  91911. const tilesetJson = yield load(url, Tiles3DLoader, Object.assign({}, loadersGLOptions));
  91912. const renderMap = {};
  91913. const boxMap = {};
  91914. const unloadQueue = [];
  91915. const root = new Group();
  91916. const tileBoxes = new Group();
  91917. tileBoxes.matrixAutoUpdate = false;//add
  91918. if (!options.debug) {
  91919. tileBoxes.visible = false;
  91920. }else {
  91921. options.parent.add(tileBoxes); //add
  91922. }
  91923. const pointcloudUniforms = {
  91924. pointSize: { type: 'f', value: options.pointSize },
  91925. gradient: { type: 't', value: gradientTexture },
  91926. grayscale: { type: 't', value: grayscaleTexture },
  91927. rootCenter: { type: 'vec3', value: new Vector3() },
  91928. rootNormal: { type: 'vec3', value: new Vector3() },
  91929. coloring: { type: 'i', value: options.pointCloudColoring },
  91930. hideGround: { type: 'b', value: true },
  91931. elevationRange: { type: 'vec2', value: new Vector2(0, 400) },
  91932. maxIntensity: { type: 'f', value: 1.0 },
  91933. intensityContrast: { type: 'f', value: 1.0 },
  91934. alpha: { type: 'f', value: 1.0 },
  91935. };
  91936. const pointcloudMaterial = new ShaderMaterial({
  91937. uniforms: pointcloudUniforms,
  91938. vertexShader: PointCloudVS,
  91939. fragmentShader: PointCloudFS,
  91940. transparent: options.transparent,
  91941. vertexColors: true
  91942. });
  91943. let cameraReference = null;
  91944. let rendererReference = null;
  91945. const gltfLoader = props.gltfLoader || new GLTFLoader(); //xzw改
  91946. let ktx2Loader = undefined;
  91947. let dracoLoader = undefined;
  91948. if (options.basisTranscoderPath) {
  91949. ktx2Loader = new KTX2Loader();
  91950. ktx2Loader.detectSupport(props.renderer);
  91951. ktx2Loader.setTranscoderPath(options.basisTranscoderPath + '/');
  91952. ktx2Loader.setWorkerLimit(1);
  91953. gltfLoader.setKTX2Loader(ktx2Loader);
  91954. }
  91955. if (options.dracoDecoderPath) {
  91956. dracoLoader = new DRACOLoader();
  91957. dracoLoader.setDecoderPath(options.dracoDecoderPath + '/');
  91958. dracoLoader.setWorkerLimit(options.maxConcurrency);
  91959. gltfLoader.setDRACOLoader(dracoLoader);
  91960. }
  91961. const unlitMaterial = new BasicMaterial({ transparent: options.transparent });
  91962. const tileOptions = {
  91963. maximumMemoryUsage: options.maximumMemoryUsage,
  91964. maximumScreenSpaceError: options.maximumScreenSpaceError,
  91965. viewDistanceScale: options.viewDistanceScale,
  91966. skipLevelOfDetail: options.skipLevelOfDetail,
  91967. updateTransforms: options.updateTransforms,
  91968. throttleRequests: options.throttleRequests,
  91969. maxRequests: options.maxRequests,
  91970. maxDepth: options.maxDepth || 50, // !zeg改
  91971. contentLoader: (tile) => __awaiter(this, void 0, void 0, function* () {
  91972. let tileContent = null;
  91973. switch (tile.type) {
  91974. case TILE_TYPE.POINTCLOUD: {
  91975. tileContent = createPointNodes(tile, pointcloudMaterial, options, rootTransformInverse);
  91976. break;
  91977. }
  91978. case TILE_TYPE.SCENEGRAPH:
  91979. case TILE_TYPE.MESH: {
  91980. tileContent = yield createGLTFNodes(gltfLoader, tile, unlitMaterial, options, rootTransformInverse);
  91981. break;
  91982. }
  91983. }
  91984. if (tileContent) {
  91985. tileContent.visible = false;
  91986. renderMap[tile.id] = tileContent;
  91987. root.add(renderMap[tile.id]);
  91988. if (options.debug) {
  91989. const box = loadersBoundingBoxToMesh(tile);
  91990. tileBoxes.add(box);
  91991. boxMap[tile.id] = box;
  91992. }
  91993. //xzw :
  91994. tileset.dispatchEvent({type:'tileLoaded',tileContent}); //每一个tile加载完要更改透明度等
  91995. }
  91996. }),
  91997. onTileLoad: (tile) => __awaiter(this, void 0, void 0, function* () {
  91998. if (tileset) {
  91999. if (!orientationDetected && (tile === null || tile === void 0 ? void 0 : tile.depth) <= MAX_DEPTH_FOR_ORIENTATION) {
  92000. detectOrientation(tile);
  92001. }
  92002. tileset._frameNumber++;
  92003. tilesetUpdate(tileset, renderMap, rendererReference, cameraReference);
  92004. }
  92005. }),
  92006. onTileUnload: (tile) => {
  92007. unloadQueue.push(tile);
  92008. },
  92009. onTileError: (tile, message) => {
  92010. console.error('Tile error', tile.id, message);
  92011. },
  92012. };
  92013. const tileset = new Tileset3D(tilesetJson, Object.assign(Object.assign({}, tileOptions), { loadOptions: Object.assign(Object.assign({}, loadersGLOptions), { maxConcurrency: options.maxConcurrency, worker: options.worker, gltf: {
  92014. loadImages: false,
  92015. }, '3d-tiles': {
  92016. loadGLTF: false
  92017. } }) }));
  92018. //
  92019. // transformations
  92020. const threeMat = new Matrix4();
  92021. const tileTrasnform = new Matrix4();
  92022. const rootCenter = new Vector3();
  92023. let orientationDetected = false;
  92024. if (tileset.root.boundingVolume) {
  92025. if (tileset.root.header.boundingVolume.region) {
  92026. // TODO: Handle region type bounding volumes
  92027. // https://github.com/visgl/loaders.gl/issues/1994
  92028. console.warn("Cannot apply a model matrix to bounding volumes of type region. Tileset stays in original geo-coordinates.");
  92029. options.geoTransform = GeoTransform.WGS84Cartesian;
  92030. }
  92031. tileTrasnform.setPosition(tileset.root.boundingVolume.center[0], tileset.root.boundingVolume.center[1], tileset.root.boundingVolume.center[2]);
  92032. }
  92033. else {
  92034. console.warn("Bounding volume not found, no transformations applied");
  92035. }
  92036. if (options.debug) {
  92037. const box = loadersBoundingBoxToMesh(tileset.root);
  92038. tileBoxes.add(box);
  92039. boxMap[tileset.root.id] = box;
  92040. }
  92041. let disposeFlag = false;
  92042. let loadingEnded = false;
  92043. pointcloudUniforms.rootCenter.value.copy(rootCenter);
  92044. pointcloudUniforms.rootNormal.value.copy(new Vector3(0, 0, 1).normalize());
  92045. // Extra stats
  92046. tileset.stats.get('Loader concurrency').count = options.maxConcurrency;
  92047. tileset.stats.get('Maximum SSE').count = options.maximumScreenSpaceError;
  92048. tileset.stats.get('Maximum mem usage').count = options.maximumMemoryUsage;
  92049. let timer = 0;
  92050. let lastCameraTransform = null;
  92051. let lastCameraAspect = null;
  92052. const lastCameraPosition = new Vector3(Infinity, Infinity, Infinity);
  92053. let sseDenominator = null;
  92054. root.updateMatrixWorld(true);
  92055. const lastRootTransform = new Matrix4().copy(root.matrixWorld);
  92056. const rootTransformInverse = new Matrix4().copy(lastRootTransform).invert();
  92057. detectOrientation(tileset.root);
  92058. updateResetTransform();
  92059. if (options.debug) {
  92060. boxMap[tileset.root.id].applyMatrix4(threeMat);
  92061. tileBoxes.matrixWorld.copy(root.matrixWorld);
  92062. }
  92063. if (options.geoTransform == GeoTransform.Mercator) {
  92064. const coords = datumsToSpherical(tileset.cartographicCenter[1], tileset.cartographicCenter[0]);
  92065. rootCenter.set(coords.x, 0, -coords.y);
  92066. root.position.copy(rootCenter);
  92067. root.rotation.set(-Math.PI / 2, 0, 0);
  92068. root.updateMatrixWorld(true);
  92069. }
  92070. else if (options.geoTransform == GeoTransform.WGS84Cartesian) {
  92071. root.applyMatrix4(tileTrasnform);
  92072. root.updateMatrixWorld(true);
  92073. rootCenter.copy(root.position);
  92074. }
  92075. function detectOrientation(tile) {
  92076. if (!tile.boundingVolume.halfAxes) {
  92077. return;
  92078. }
  92079. const halfAxes = tile.boundingVolume.halfAxes;
  92080. const orientationMatrix = new Matrix4()
  92081. .extractRotation(getMatrix4FromHalfAxes(halfAxes))
  92082. .premultiply(new Matrix4().extractRotation(rootTransformInverse));
  92083. const rotation = new Euler().setFromRotationMatrix(orientationMatrix);
  92084. if (!rotation.equals(new Euler())) {
  92085. orientationDetected = true;
  92086. const pos = new Vector3(tileTrasnform.elements[12], tileTrasnform.elements[13], tileTrasnform.elements[14]);
  92087. tileTrasnform.extractRotation(orientationMatrix);
  92088. tileTrasnform.setPosition(pos);
  92089. updateResetTransform();
  92090. }
  92091. }
  92092. function updateResetTransform() {
  92093. if (options.geoTransform != GeoTransform.WGS84Cartesian) {
  92094. // Reset the current model matrix and apply our own transformation
  92095. threeMat.copy(tileTrasnform).invert();
  92096. threeMat.premultiply(lastRootTransform);
  92097. threeMat.copy(lastRootTransform).multiply(new Matrix4().copy(tileTrasnform).invert());
  92098. tileset.modelMatrix = new Matrix4$1(threeMat.toArray());
  92099. }
  92100. }
  92101. // 更新瓦片显隐和瓦片迭代更新
  92102. function tilesetUpdate(tileset, renderMap, renderer, camera) {
  92103. if (disposeFlag || options.pauseTilesetUpdate) {// !zeg改 pauseTilesetUpdate
  92104. return
  92105. }
  92106. // Assumes camera fov, near and far are not changing
  92107. if (!sseDenominator || camera.aspect != lastCameraAspect) {
  92108. const loadersFrustum = new PerspectiveFrustum({
  92109. fov: (camera.fov / 180) * Math.PI,
  92110. aspectRatio: camera.aspect,
  92111. near: camera.near,
  92112. far: camera.far,
  92113. });
  92114. sseDenominator = loadersFrustum.sseDenominator;
  92115. lastCameraAspect = camera.aspect;
  92116. if (options.debug) {
  92117. console.log('Updated sse denonimator:', sseDenominator);
  92118. }
  92119. }
  92120. const frustum = getCameraFrustum(camera);
  92121. const planes = frustum.planes.map((plane) => new Plane$1(plane.normal.toArray(), plane.constant));
  92122. const cullingVolume = new CullingVolume(planes);
  92123. const rendererSize = new Vector2();
  92124. renderer.getSize(rendererSize);
  92125. const frameState = {
  92126. camera: {
  92127. position: lastCameraPosition.toArray(),
  92128. },
  92129. height: rendererSize.y,
  92130. frameNumber: tileset._frameNumber,
  92131. sseDenominator: sseDenominator,
  92132. cullingVolume: cullingVolume,
  92133. viewport: {
  92134. id: 0,
  92135. },
  92136. };
  92137. tileset._cache.reset();
  92138. tileset._traverser.traverse(tileset.root, frameState, tileset.options);
  92139. for (const tile of tileset.tiles) {
  92140. if (tile.selected) {
  92141. if (!renderMap[tile.id]) {
  92142. console.error('TILE SELECTED BUT NOT LOADED!!', tile.id);
  92143. }
  92144. else {
  92145. // Make sure it's visible
  92146. if(!renderMap[tile.id].visible){
  92147. if(visiVertexCount<maxVertexVisi){
  92148. renderMap[tile.id].visible = true;
  92149. visiVertexCount += renderMap[tile.id].vertexCount; //xzw add
  92150. options.debug && (boxMap[tile.id].material.opacity = 1);
  92151. }else {
  92152. console.log('超出', visiVertexCount);
  92153. }
  92154. }
  92155. /* if(!renderMap[tile.id].realVisible()){
  92156. console.error('!realVisible')
  92157. } */
  92158. }
  92159. }
  92160. else {
  92161. if (renderMap[tile.id]) {
  92162. if(renderMap[tile.id].visible){
  92163. renderMap[tile.id].visible = false;
  92164. options.debug && (boxMap[tile.id].material.opacity = 0.1);
  92165. visiVertexCount -= renderMap[tile.id].vertexCount; //xzw add
  92166. }
  92167. }
  92168. }
  92169. }
  92170. while (unloadQueue.length > 0) {
  92171. const tile = unloadQueue.pop();
  92172. if (renderMap[tile.id] && tile.contentState == TILE_CONTENT_STATE.UNLOADED) {
  92173. //console.log('removevisi', renderMap[tile.id].visible) 如果是true,visiVertexCount要减
  92174. root.remove(renderMap[tile.id]);
  92175. disposeNode(renderMap[tile.id]);
  92176. delete renderMap[tile.id];
  92177. }
  92178. if (boxMap[tile.id]) {
  92179. disposeNode(boxMap[tile.id]);
  92180. tileBoxes.remove(boxMap[tile.id]);
  92181. delete boxMap[tile.id];
  92182. }
  92183. }
  92184. const tilesLoaded = tileset.stats.get('Tiles Loaded').count;
  92185. const tilesLoading = tileset.stats.get('Tiles Loading').count;
  92186. if (props.onProgress) {
  92187. props.onProgress(tilesLoaded, tilesLoaded + tilesLoading);
  92188. }
  92189. if (props.loadingManager && !loadingEnded) {
  92190. if (tilesLoading == 0 &&
  92191. (options.preloadTilesCount == null ||
  92192. tilesLoaded >= options.preloadTilesCount)) {
  92193. loadingEnded = true;
  92194. props.loadingManager.itemEnd(props.url);
  92195. }
  92196. }
  92197. return frameState;
  92198. }
  92199. return {
  92200. model: root,
  92201. runtime: {
  92202. getTileset: () => {
  92203. return tileset;
  92204. },
  92205. getStats: () => {
  92206. return tileset.stats;
  92207. },
  92208. showTiles: (visible) => {
  92209. tileBoxes.visible = visible;
  92210. },
  92211. setWireframe: (wireframe) => {
  92212. options.wireframe = wireframe;
  92213. root.traverse((object) => {
  92214. if (object instanceof Mesh) {
  92215. object.material.wireframe = wireframe;
  92216. }
  92217. });
  92218. },
  92219. setDebug: (debug) => {
  92220. options.debug = debug;
  92221. tileBoxes.visible = debug;
  92222. },
  92223. setShading: (shading) => {
  92224. options.shading = shading;
  92225. },
  92226. getTileBoxes: () => {
  92227. return tileBoxes;
  92228. },
  92229. setViewDistanceScale: (scale) => {
  92230. tileset.options.viewDistanceScale = scale;
  92231. tileset._frameNumber++;
  92232. tilesetUpdate(tileset, renderMap, rendererReference, cameraReference);
  92233. },
  92234. setHideGround: (enabled) => {
  92235. pointcloudUniforms.hideGround.value = enabled;
  92236. },
  92237. setPointCloudColoring: (selection) => {
  92238. pointcloudUniforms.coloring.value = selection;
  92239. },
  92240. setElevationRange: (range) => {
  92241. pointcloudUniforms.elevationRange.value.set(range[0], range[1]);
  92242. },
  92243. setMaxIntensity: (intensity) => {
  92244. pointcloudUniforms.maxIntensity.value = intensity;
  92245. },
  92246. setIntensityContrast: (contrast) => {
  92247. pointcloudUniforms.intensityContrast.value = contrast;
  92248. },
  92249. setPointAlpha: (alpha) => {
  92250. pointcloudUniforms.alpha.value = alpha;
  92251. },
  92252. getLatLongHeightFromPosition: (position) => {
  92253. const cartographicPosition = tileset.ellipsoid.cartesianToCartographic(new Vector3().copy(position).applyMatrix4(new Matrix4().copy(threeMat).invert()).toArray());
  92254. return {
  92255. lat: cartographicPosition[1],
  92256. long: cartographicPosition[0],
  92257. height: cartographicPosition[2],
  92258. };
  92259. },
  92260. getPositionFromLatLongHeight: (coord) => {
  92261. const cartesianPosition = tileset.ellipsoid.cartographicToCartesian([coord.long, coord.lat, coord.height]);
  92262. return new Vector3(...cartesianPosition).applyMatrix4(threeMat);
  92263. },
  92264. getCameraFrustum: (camera) => {
  92265. const frustum = getCameraFrustum(camera);
  92266. const meshes = frustum.planes
  92267. .map((plane) => new Plane$1(plane.normal.toArray(), plane.constant))
  92268. .map((loadersPlane) => loadersPlaneToMesh(loadersPlane));
  92269. const model = new Group();
  92270. for (const mesh of meshes)
  92271. model.add(mesh);
  92272. return model;
  92273. },
  92274. update: function (dt, renderer, camera) {
  92275. cameraReference = camera;
  92276. rendererReference = renderer;
  92277. timer += dt;
  92278. if (tileset && timer >= UPDATE_INTERVAL) {
  92279. if (!lastRootTransform.equals(root.matrixWorld)) {
  92280. timer = 0;
  92281. lastRootTransform.copy(root.matrixWorld);
  92282. updateResetTransform();
  92283. const rootCenter = new Vector3().setFromMatrixPosition(lastRootTransform);
  92284. pointcloudUniforms.rootCenter.value.copy(rootCenter);
  92285. pointcloudUniforms.rootNormal.value.copy(new Vector3(0, 0, 1).applyMatrix4(lastRootTransform).normalize());
  92286. rootTransformInverse.copy(lastRootTransform).invert();
  92287. if (options.debug) {
  92288. /* console.log('move', tileset.root.id, boxMap[tileset.root.id].matrix.elements, boxMap[tileset.root.id].matrixWorld.elements)
  92289. boxMap[tileset.root.id].matrix.copy(root.matrixWorld);
  92290. boxMap[tileset.root.id].matrixWorld.copy(root.matrixWorld); */
  92291. //boxMap[tileset.root.id].applyMatrix4(threeMat);
  92292. tileBoxes.matrix.copy(root.matrixWorld);
  92293. //boxMap[tileset.root.id].matrixWorld.copy(threeMat);
  92294. //boxMap[tileset.root.id].applyMatrix4(lastRootTransform);//boxMap[tileset.root.id].applyMatrix4(lastRootTransform);
  92295. //boxMap[tileset.root.id].updateWorldMatrix()
  92296. }
  92297. }
  92298. if (this.lastCameraTransform == null) {
  92299. this.lastCameraTransform = new Matrix4().copy(camera.matrixWorld);
  92300. }
  92301. else {
  92302. const cameraChanged = !camera.matrixWorld.equals(this.lastCameraTransform) ||
  92303. !(camera.aspect == lastCameraAspect);
  92304. if (cameraChanged) {
  92305. timer = 0;
  92306. tileset._frameNumber++;
  92307. camera.getWorldPosition(lastCameraPosition);
  92308. this.lastCameraTransform.copy(camera.matrixWorld);
  92309. tilesetUpdate(tileset, renderMap, renderer, camera);
  92310. }
  92311. }
  92312. }/* else{
  92313. console.log('11')
  92314. } */
  92315. },
  92316. dispose: function () {
  92317. disposeFlag = true;
  92318. tileset._destroy();
  92319. while (root.children.length > 0) {
  92320. const obj = root.children[0];
  92321. disposeNode(obj);
  92322. root.remove(obj);
  92323. }
  92324. while (tileBoxes.children.length > 0) {
  92325. const obj = tileBoxes.children[0];
  92326. tileBoxes.remove(obj);
  92327. obj.geometry.dispose();
  92328. obj.material.dispose();
  92329. }
  92330. if (ktx2Loader) {
  92331. ktx2Loader.dispose();
  92332. }
  92333. if (dracoLoader) {
  92334. dracoLoader.dispose();
  92335. }
  92336. },
  92337. },
  92338. };
  92339. });
  92340. }
  92341. }
  92342. function createGLTFNodes(gltfLoader, tile, unlitMaterial, options, rootTransformInverse) {
  92343. return __awaiter(this, void 0, void 0, function* () {
  92344. return new Promise((resolve, reject) => {
  92345. var _a;
  92346. const rotateX = new Matrix4().makeRotationAxis(new Vector3(1, 0, 0), Math.PI / 2);
  92347. const shouldRotate = ((_a = tile.tileset.asset) === null || _a === void 0 ? void 0 : _a.gltfUpAxis) !== "Z";
  92348. // The computed trasnform already contains the root's transform, so we have to invert it
  92349. const contentTransform = new Matrix4().fromArray(tile.computedTransform).premultiply(rootTransformInverse); //xzw 删。原先的会造成移动后tiles错乱
  92350. //不知为何在刚开始加载时迅速移动模型,tiles位置会参差不齐。应该和contentTransform有关,也就是tile.computedTransform 和rootTransformInverse的问题。但即使每次_updateTransform后重新计算也不对
  92351. if (shouldRotate) {
  92352. contentTransform.multiply(rotateX); // convert from GLTF Y-up to Z-up
  92353. }
  92354. gltfLoader.parse(
  92355. tile.content.type == 'glTF' ? tile.content.gltf.gltfArrayBuffer : tile.content.gltfArrayBuffer,//tile.content.gltfArrayBuffer,
  92356. tile.contentUrl ? tile.contentUrl.substr(0, tile.contentUrl.lastIndexOf('/') + 1) : '',
  92357. (gltf) => {
  92358. const tileContent = gltf.scenes[0];
  92359. //tileContent.applyMatrix4(contentTransform);
  92360. tileContent.vertexCount = 0; //xzw add
  92361. tileContent.traverse((object) => {
  92362. if (object.type == "Mesh") {
  92363. const mesh = object;
  92364. //mesh.tileId = tile.id//add
  92365. const originalMaterial = mesh.material;
  92366. const originalMap = originalMaterial.map;
  92367. if (options.material) {
  92368. mesh.material = options.material.clone();
  92369. originalMaterial.dispose();
  92370. }
  92371. else if (options.shading == Shading.FlatTexture) {
  92372. mesh.material = unlitMaterial.clone();
  92373. originalMaterial.dispose();
  92374. }
  92375. if (options.shading != Shading.ShadedNoTexture) {
  92376. if (mesh.material.type == "ShaderMaterial" && !(mesh.material instanceof BasicMaterial)) {//改
  92377. mesh.material.uniforms.map = { value: originalMap };
  92378. }
  92379. else {
  92380. mesh.material.map = originalMap;
  92381. }
  92382. }
  92383. else {
  92384. if (originalMap) {
  92385. originalMap.dispose();
  92386. }
  92387. mesh.material.map = null;
  92388. }
  92389. if (options.shaderCallback) {
  92390. mesh.onBeforeRender = options.shaderCallback;
  92391. }
  92392. mesh.material.wireframe = options.wireframe;
  92393. if (options.computeNormals) {
  92394. mesh.geometry.computeVertexNormals();
  92395. }
  92396. //xzw add:
  92397. tileContent.vertexCount += mesh.geometry.attributes.position.count;
  92398. //------------------add on 2023.1.16----zeg
  92399. mesh.geometry.applyMatrix4(contentTransform);
  92400. if (tile.content.rtcCenter) {
  92401. // 有些b3dm模型会将坐标写在源码的rtcCenter里 如https://testgis.4dage.com/LVBADUI_qp/tileset.json
  92402. mesh.geometry.translate(tile.content.rtcCenter[0], tile.content.rtcCenter[1], tile.content.rtcCenter[2]);
  92403. } else {
  92404. mesh.geometry.scale(1, 1, -1); // 调整缩放,对应box也要进行变换(scaleZ对应box[2])
  92405. }
  92406. //---------------------
  92407. }
  92408. });
  92409. resolve(tileContent);
  92410. },
  92411. (e) => {
  92412. reject(new Error(`error parsing gltf in tile ${tile.id}: ${e}`));
  92413. }
  92414. );
  92415. });
  92416. });
  92417. }
  92418. function createPointNodes(tile, pointcloudMaterial, options, rootTransformInverse) {
  92419. const d = {
  92420. rtc_center: tile.content.rtcCenter,
  92421. points: tile.content.attributes.positions,
  92422. intensities: tile.content.attributes.intensity,
  92423. classifications: tile.content.attributes.classification,
  92424. rgb: null,
  92425. rgba: null,
  92426. };
  92427. const { colors } = tile.content.attributes;
  92428. if (colors && colors.size === 3) {
  92429. d.rgb = colors.value;
  92430. }
  92431. if (colors && colors.size === 4) {
  92432. d.rgba = colors.value;
  92433. }
  92434. const geometry = new BufferGeometry();
  92435. geometry.setAttribute('position', new Float32BufferAttribute(d.points, 3));
  92436. const contentTransform = new Matrix4().fromArray(tile.computedTransform).premultiply(rootTransformInverse);
  92437. if (d.rgba) {
  92438. geometry.setAttribute('color', new Float32BufferAttribute(d.rgba, 4));
  92439. }
  92440. else if (d.rgb) {
  92441. geometry.setAttribute('color', new Uint8BufferAttribute(d.rgb, 3, true));
  92442. }
  92443. if (d.intensities) {
  92444. geometry.setAttribute('intensity',
  92445. // Handles both 16bit or 8bit intensity values
  92446. new BufferAttribute(d.intensities, 1, true));
  92447. }
  92448. if (d.classifications) {
  92449. geometry.setAttribute('classification', new Uint8BufferAttribute(d.classifications, 1, false));
  92450. }
  92451. const tileContent = new Points(geometry, options.material || pointcloudMaterial);
  92452. if (d.rtc_center) {
  92453. const c = d.rtc_center;
  92454. contentTransform.multiply(new Matrix4().makeTranslation(c[0], c[1], c[2]));
  92455. }
  92456. tileContent.applyMatrix4(contentTransform);
  92457. return tileContent;
  92458. }
  92459. function disposeMaterial(material) {
  92460. var _a, _b, _c, _d;
  92461. if ((_a = material === null || material === void 0 ? void 0 : material.uniforms) === null || _a === void 0 ? void 0 : _a.map) {
  92462. (_c = (_b = material === null || material === void 0 ? void 0 : material.uniforms) === null || _b === void 0 ? void 0 : _b.map.value) === null || _c === void 0 ? void 0 : _c.dispose();
  92463. }
  92464. else if (material.map) {
  92465. (_d = material.map) === null || _d === void 0 ? void 0 : _d.dispose();
  92466. }
  92467. material.dispose();
  92468. }
  92469. function disposeNode(node) {
  92470. node.traverse((object) => {
  92471. if (object.isMesh) {
  92472. object.geometry.dispose();
  92473. if (object.material.isMaterial) {
  92474. disposeMaterial(object.material);
  92475. }
  92476. else {
  92477. // an array of materials
  92478. for (const material of object.material) {
  92479. disposeMaterial(material);
  92480. }
  92481. }
  92482. }
  92483. });
  92484. for (let i = node.children.length - 1; i >= 0; i--) {
  92485. const obj = node.children[i];
  92486. node.remove(obj);
  92487. }
  92488. }
  92489. /*
  92490. 关键搜寻:
  92491. Loader3DTiles : const tileset = new Tileset3D
  92492. tileset.dispatchEvent({type:'tileLoaded',tileContent})
  92493. createGLTFNodes : gltfLoader.parse
  92494. */
  92495. /**
  92496. * Description: A THREE loader for PLY ASCII files (known as the Polygon
  92497. * File Format or the Stanford Triangle Format).
  92498. *
  92499. * Limitations: ASCII decoding assumes file is UTF-8.
  92500. *
  92501. * Usage:
  92502. * var loader = new PLYLoader();
  92503. * loader.load('./models/ply/ascii/dolphins.ply', function (geometry) {
  92504. *
  92505. * scene.add( new THREE.Mesh( geometry ) );
  92506. *
  92507. * } );
  92508. *
  92509. * If the PLY file uses non standard property names, they can be mapped while
  92510. * loading. For example, the following maps the properties
  92511. * “diffuse_(red|green|blue)” in the file to standard color names.
  92512. *
  92513. * loader.setPropertyNameMapping( {
  92514. * diffuse_red: 'red',
  92515. * diffuse_green: 'green',
  92516. * diffuse_blue: 'blue'
  92517. * } );
  92518. *
  92519. */
  92520. var PLYLoader = function ( manager ) {
  92521. Loader.call( this, manager );
  92522. this.propertyNameMapping = {};
  92523. };
  92524. PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  92525. constructor: PLYLoader,
  92526. load: function ( url, onLoad, onProgress, onError ) {
  92527. var scope = this;
  92528. var loader = new FileLoader( this.manager );
  92529. loader.setPath( this.path );
  92530. loader.setResponseType( 'arraybuffer' );
  92531. loader.setRequestHeader( this.requestHeader );
  92532. loader.setWithCredentials( this.withCredentials );
  92533. loader.load( url, function ( text ) {
  92534. try {
  92535. onLoad( scope.parse( text ) );
  92536. } catch ( e ) {
  92537. if ( onError ) {
  92538. onError( e );
  92539. } else {
  92540. console.error( e );
  92541. }
  92542. scope.manager.itemError( url );
  92543. }
  92544. }, onProgress, onError );
  92545. },
  92546. setPropertyNameMapping: function ( mapping ) {
  92547. this.propertyNameMapping = mapping;
  92548. },
  92549. parse: function ( data ) {
  92550. function parseHeader( data ) {
  92551. var patternHeader = /ply([\s\S]*)end_header\r?\n/;
  92552. var headerText = '';
  92553. var headerLength = 0;
  92554. var result = patternHeader.exec( data );
  92555. if ( result !== null ) {
  92556. headerText = result[ 1 ];
  92557. headerLength = new Blob( [ result[ 0 ] ] ).size;
  92558. }
  92559. var header = {
  92560. comments: [],
  92561. elements: [],
  92562. headerLength: headerLength,
  92563. objInfo: ''
  92564. };
  92565. var lines = headerText.split( '\n' );
  92566. var currentElement;
  92567. var lineType, lineValues;
  92568. function make_ply_element_property( propertValues, propertyNameMapping ) {
  92569. var property = { type: propertValues[ 0 ] };
  92570. if ( property.type === 'list' ) {
  92571. property.name = propertValues[ 3 ];
  92572. property.countType = propertValues[ 1 ];
  92573. property.itemType = propertValues[ 2 ];
  92574. } else {
  92575. property.name = propertValues[ 1 ];
  92576. }
  92577. if ( property.name in propertyNameMapping ) {
  92578. property.name = propertyNameMapping[ property.name ];
  92579. }
  92580. return property;
  92581. }
  92582. for ( var i = 0; i < lines.length; i ++ ) {
  92583. var line = lines[ i ];
  92584. line = line.trim();
  92585. if ( line === '' ) continue;
  92586. lineValues = line.split( /\s+/ );
  92587. lineType = lineValues.shift();
  92588. line = lineValues.join( ' ' );
  92589. switch ( lineType ) {
  92590. case 'format':
  92591. header.format = lineValues[ 0 ];
  92592. header.version = lineValues[ 1 ];
  92593. break;
  92594. case 'comment':
  92595. header.comments.push( line );
  92596. break;
  92597. case 'element':
  92598. if ( currentElement !== undefined ) {
  92599. header.elements.push( currentElement );
  92600. }
  92601. currentElement = {};
  92602. currentElement.name = lineValues[ 0 ];
  92603. currentElement.count = parseInt( lineValues[ 1 ] );
  92604. currentElement.properties = [];
  92605. break;
  92606. case 'property':
  92607. currentElement.properties.push( make_ply_element_property( lineValues, scope.propertyNameMapping ) );
  92608. break;
  92609. case 'obj_info':
  92610. header.objInfo = line;
  92611. break;
  92612. default:
  92613. console.log( 'unhandled', lineType, lineValues );
  92614. }
  92615. }
  92616. if ( currentElement !== undefined ) {
  92617. header.elements.push( currentElement );
  92618. }
  92619. return header;
  92620. }
  92621. function parseASCIINumber( n, type ) {
  92622. switch ( type ) {
  92623. case 'char': case 'uchar': case 'short': case 'ushort': case 'int': case 'uint':
  92624. case 'int8': case 'uint8': case 'int16': case 'uint16': case 'int32': case 'uint32':
  92625. return parseInt( n );
  92626. case 'float': case 'double': case 'float32': case 'float64':
  92627. return parseFloat( n );
  92628. }
  92629. }
  92630. function parseASCIIElement( properties, line ) {
  92631. var values = line.split( /\s+/ );
  92632. var element = {};
  92633. for ( var i = 0; i < properties.length; i ++ ) {
  92634. if ( properties[ i ].type === 'list' ) {
  92635. var list = [];
  92636. var n = parseASCIINumber( values.shift(), properties[ i ].countType );
  92637. for ( var j = 0; j < n; j ++ ) {
  92638. list.push( parseASCIINumber( values.shift(), properties[ i ].itemType ) );
  92639. }
  92640. element[ properties[ i ].name ] = list;
  92641. } else {
  92642. element[ properties[ i ].name ] = parseASCIINumber( values.shift(), properties[ i ].type );
  92643. }
  92644. }
  92645. return element;
  92646. }
  92647. function parseASCII( data, header ) {
  92648. // PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
  92649. var buffer = {
  92650. indices: [],
  92651. vertices: [],
  92652. normals: [],
  92653. uvs: [],
  92654. faceVertexUvs: [],
  92655. colors: []
  92656. };
  92657. var result;
  92658. var patternBody = /end_header\s([\s\S]*)$/;
  92659. var body = '';
  92660. if ( ( result = patternBody.exec( data ) ) !== null ) {
  92661. body = result[ 1 ];
  92662. }
  92663. var lines = body.split( '\n' );
  92664. var currentElement = 0;
  92665. var currentElementCount = 0;
  92666. for ( var i = 0; i < lines.length; i ++ ) {
  92667. var line = lines[ i ];
  92668. line = line.trim();
  92669. if ( line === '' ) {
  92670. continue;
  92671. }
  92672. if ( currentElementCount >= header.elements[ currentElement ].count ) {
  92673. currentElement ++;
  92674. currentElementCount = 0;
  92675. }
  92676. var element = parseASCIIElement( header.elements[ currentElement ].properties, line );
  92677. handleElement( buffer, header.elements[ currentElement ].name, element );
  92678. currentElementCount ++;
  92679. }
  92680. return postProcess( buffer );
  92681. }
  92682. function postProcess( buffer ) {
  92683. var geometry = new BufferGeometry();
  92684. // mandatory buffer data
  92685. if ( buffer.indices.length > 0 ) {
  92686. geometry.setIndex( buffer.indices );
  92687. }
  92688. geometry.setAttribute( 'position', new Float32BufferAttribute( buffer.vertices, 3 ) );
  92689. // optional buffer data
  92690. if ( buffer.normals.length > 0 ) {
  92691. geometry.setAttribute( 'normal', new Float32BufferAttribute( buffer.normals, 3 ) );
  92692. }
  92693. if ( buffer.uvs.length > 0 ) {
  92694. geometry.setAttribute( 'uv', new Float32BufferAttribute( buffer.uvs, 2 ) );
  92695. }
  92696. if ( buffer.colors.length > 0 ) {
  92697. geometry.setAttribute( 'color', new Float32BufferAttribute( buffer.colors, 3 ) );
  92698. }
  92699. if ( buffer.faceVertexUvs.length > 0 ) {
  92700. geometry = geometry.toNonIndexed();
  92701. geometry.setAttribute( 'uv', new Float32BufferAttribute( buffer.faceVertexUvs, 2 ) );
  92702. }
  92703. geometry.computeBoundingSphere();
  92704. return geometry;
  92705. }
  92706. function handleElement( buffer, elementName, element ) {
  92707. if ( elementName === 'vertex' ) {
  92708. buffer.vertices.push( element.x, element.y, element.z );
  92709. if ( 'nx' in element && 'ny' in element && 'nz' in element ) {
  92710. buffer.normals.push( element.nx, element.ny, element.nz );
  92711. }
  92712. if ( 's' in element && 't' in element ) {
  92713. buffer.uvs.push( element.s, element.t );
  92714. }
  92715. if ( 'red' in element && 'green' in element && 'blue' in element ) {
  92716. buffer.colors.push( element.red / 255.0, element.green / 255.0, element.blue / 255.0 );
  92717. }
  92718. } else if ( elementName === 'face' ) {
  92719. var vertex_indices = element.vertex_indices || element.vertex_index; // issue #9338
  92720. var texcoord = element.texcoord;
  92721. if ( vertex_indices.length === 3 ) {
  92722. buffer.indices.push( vertex_indices[ 0 ], vertex_indices[ 1 ], vertex_indices[ 2 ] );
  92723. if ( texcoord && texcoord.length === 6 ) {
  92724. buffer.faceVertexUvs.push( texcoord[ 0 ], texcoord[ 1 ] );
  92725. buffer.faceVertexUvs.push( texcoord[ 2 ], texcoord[ 3 ] );
  92726. buffer.faceVertexUvs.push( texcoord[ 4 ], texcoord[ 5 ] );
  92727. }
  92728. } else if ( vertex_indices.length === 4 ) {
  92729. buffer.indices.push( vertex_indices[ 0 ], vertex_indices[ 1 ], vertex_indices[ 3 ] );
  92730. buffer.indices.push( vertex_indices[ 1 ], vertex_indices[ 2 ], vertex_indices[ 3 ] );
  92731. }
  92732. }
  92733. }
  92734. function binaryRead( dataview, at, type, little_endian ) {
  92735. switch ( type ) {
  92736. // corespondences for non-specific length types here match rply:
  92737. case 'int8': case 'char': return [ dataview.getInt8( at ), 1 ];
  92738. case 'uint8': case 'uchar': return [ dataview.getUint8( at ), 1 ];
  92739. case 'int16': case 'short': return [ dataview.getInt16( at, little_endian ), 2 ];
  92740. case 'uint16': case 'ushort': return [ dataview.getUint16( at, little_endian ), 2 ];
  92741. case 'int32': case 'int': return [ dataview.getInt32( at, little_endian ), 4 ];
  92742. case 'uint32': case 'uint': return [ dataview.getUint32( at, little_endian ), 4 ];
  92743. case 'float32': case 'float': return [ dataview.getFloat32( at, little_endian ), 4 ];
  92744. case 'float64': case 'double': return [ dataview.getFloat64( at, little_endian ), 8 ];
  92745. }
  92746. }
  92747. function binaryReadElement( dataview, at, properties, little_endian ) {
  92748. var element = {};
  92749. var result, read = 0;
  92750. for ( var i = 0; i < properties.length; i ++ ) {
  92751. if ( properties[ i ].type === 'list' ) {
  92752. var list = [];
  92753. result = binaryRead( dataview, at + read, properties[ i ].countType, little_endian );
  92754. var n = result[ 0 ];
  92755. read += result[ 1 ];
  92756. for ( var j = 0; j < n; j ++ ) {
  92757. result = binaryRead( dataview, at + read, properties[ i ].itemType, little_endian );
  92758. list.push( result[ 0 ] );
  92759. read += result[ 1 ];
  92760. }
  92761. element[ properties[ i ].name ] = list;
  92762. } else {
  92763. result = binaryRead( dataview, at + read, properties[ i ].type, little_endian );
  92764. element[ properties[ i ].name ] = result[ 0 ];
  92765. read += result[ 1 ];
  92766. }
  92767. }
  92768. return [ element, read ];
  92769. }
  92770. function parseBinary( data, header ) {
  92771. var buffer = {
  92772. indices: [],
  92773. vertices: [],
  92774. normals: [],
  92775. uvs: [],
  92776. faceVertexUvs: [],
  92777. colors: []
  92778. };
  92779. var little_endian = ( header.format === 'binary_little_endian' );
  92780. var body = new DataView( data, header.headerLength );
  92781. var result, loc = 0;
  92782. for ( var currentElement = 0; currentElement < header.elements.length; currentElement ++ ) {
  92783. for ( var currentElementCount = 0; currentElementCount < header.elements[ currentElement ].count; currentElementCount ++ ) {
  92784. result = binaryReadElement( body, loc, header.elements[ currentElement ].properties, little_endian );
  92785. loc += result[ 1 ];
  92786. var element = result[ 0 ];
  92787. handleElement( buffer, header.elements[ currentElement ].name, element );
  92788. }
  92789. }
  92790. return postProcess( buffer );
  92791. }
  92792. //
  92793. var geometry;
  92794. var scope = this;
  92795. if ( data instanceof ArrayBuffer ) {
  92796. var text = LoaderUtils.decodeText( new Uint8Array( data ) );
  92797. var header = parseHeader( text );
  92798. geometry = header.format === 'ascii' ? parseASCII( text, header ) : parseBinary( data, header );
  92799. } else {
  92800. geometry = parseASCII( data, parseHeader( data ) );
  92801. }
  92802. return geometry;
  92803. }
  92804. } );
  92805. /**
  92806. * @author alteredq / http://alteredqualia.com/
  92807. */
  92808. let Pass = function () {
  92809. // if set to true, the pass is processed by the composer
  92810. this.enabled = true;
  92811. // if set to true, the pass indicates to swap read and write buffer after rendering
  92812. this.needsSwap = true;
  92813. // if set to true, the pass clears its buffer before rendering
  92814. this.clear = false;
  92815. // if set to true, the result of the pass is rendered to screen
  92816. this.renderToScreen = false;
  92817. };
  92818. Object.assign( Pass.prototype, {
  92819. setSize: function ( width, height ) {},
  92820. render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
  92821. console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );
  92822. }
  92823. } );
  92824. let ShaderPass = function ( shader, textureID ) {
  92825. Pass.call( this );
  92826. this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse";
  92827. if ( shader instanceof ShaderMaterial ) {
  92828. this.uniforms = shader.uniforms;
  92829. this.material = shader;
  92830. } else if ( shader ) {
  92831. this.uniforms = UniformsUtils.clone( shader.uniforms );
  92832. this.material = new ShaderMaterial( {
  92833. defines: Object.assign( {}, shader.defines ),
  92834. uniforms: this.uniforms,
  92835. vertexShader: shader.vertexShader,
  92836. fragmentShader: shader.fragmentShader,
  92837. transparent:true,//add
  92838. } );
  92839. }
  92840. this.camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
  92841. this.scene = new Scene();
  92842. this.quad = new Mesh( new PlaneBufferGeometry( 2, 2 ), null );
  92843. this.quad.frustumCulled = false; // Avoid getting clipped
  92844. this.scene.add( this.quad );
  92845. };
  92846. ShaderPass.prototype = Object.assign( Object.create( Pass.prototype ), {
  92847. constructor: ShaderPass,
  92848. render: function(scene,camera, viewports, renderer, writeBuffer, readBuffer, delta, maskActive ) {
  92849. let oldTarget = renderer.getRenderTarget();
  92850. /* if(this.readTarget){ //add
  92851. readBuffer = oldTarget
  92852. } */
  92853. if ( this.uniforms[ this.textureID ] ) {
  92854. this.uniforms[ this.textureID ].value = readBuffer.texture;
  92855. }
  92856. this.quad.material = this.material;
  92857. if ( this.renderToScreen ) {
  92858. renderer.render( this.scene, this.camera );
  92859. } else {
  92860. renderer.setRenderTarget(writeBuffer);
  92861. if(this.clear) renderer.clear();
  92862. renderer.render( this.scene, this.camera );
  92863. renderer.setRenderTarget(oldTarget);
  92864. }
  92865. }
  92866. } );
  92867. /**
  92868. * @author alteredq / http://alteredqualia.com/
  92869. *
  92870. * Full-screen textured quad shader
  92871. */
  92872. let CopyShader = {
  92873. uniforms: {
  92874. "tDiffuse": { value: null },
  92875. "opacity": { value: 1.0 }
  92876. },
  92877. vertexShader: [
  92878. "varying vec2 vUv;",
  92879. "void main() {",
  92880. "vUv = uv;",
  92881. "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
  92882. "}"
  92883. ].join( "\n" ),
  92884. fragmentShader: [
  92885. "uniform float opacity;",
  92886. "uniform sampler2D tDiffuse;",
  92887. "varying vec2 vUv;",
  92888. "void main() {",
  92889. "vec4 texel = texture2D( tDiffuse, vUv );", //如果开启premultipliedAlpha用这个,否则用注释的
  92890. "gl_FragColor = opacity * texel;",
  92891. //"gl_FragColor = texture2D( tDiffuse, vUv );",
  92892. //"gl_FragColor.a *= opacity;",
  92893. "}"
  92894. ].join( "\n" )
  92895. };
  92896. /**
  92897. *
  92898. * Supersample Anti-Aliasing Render Pass
  92899. *
  92900. * @author bhouston / http://clara.io/
  92901. *
  92902. * This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results.
  92903. *
  92904. * References: https://en.wikipedia.org/wiki/Supersampling
  92905. *
  92906. */
  92907. //较为原始的一种抗锯齿 (超级采样抗锯齿)
  92908. let SSAARenderPass = function ( clearColor, clearAlpha ) {
  92909. Pass.call( this );
  92910. //this.scene //= scene;
  92911. //this.camera = camera;
  92912. this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.
  92913. this.unbiased = true;
  92914. // as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black.
  92915. this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000;
  92916. this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
  92917. this.renderUniforms = {
  92918. bgTex : {value:null},
  92919. outlineTex : {value:null},
  92920. opacity : {value:1},
  92921. };
  92922. this.renderMat = new ShaderMaterial({
  92923. uniforms: this.renderUniforms,
  92924. vertexShader: CopyShader.vertexShader,
  92925. /* fragmentShader: CopyShader.fragmentShader, */
  92926. fragmentShader: `
  92927. uniform sampler2D bgTex;
  92928. uniform sampler2D outlineTex;
  92929. uniform float opacity;
  92930. varying vec2 vUv;
  92931. void main() {
  92932. vec4 color1 = texture2D( bgTex, vUv );
  92933. vec4 color2 = texture2D( outlineTex, vUv );
  92934. gl_FragColor = opacity * mix(color1, color2, color2.a) ;
  92935. }
  92936. `,
  92937. premultipliedAlpha: true,
  92938. blending: AdditiveBlending,
  92939. depthTest: false,
  92940. depthWrite: false,
  92941. transparent: true
  92942. });
  92943. this.renderMat2 = new ShaderMaterial({
  92944. uniforms: UniformsUtils.clone(CopyShader.uniforms) ,
  92945. vertexShader: CopyShader.vertexShader,
  92946. fragmentShader:`uniform float opacity;
  92947. uniform sampler2D tDiffuse;
  92948. varying vec2 vUv;
  92949. void main() {
  92950. vec4 texel = texture2D( tDiffuse, vUv );
  92951. if(texel.r == 0.0 && texel.g == 0.0 && texel.b == 0.0){
  92952. discard;
  92953. }else{
  92954. gl_FragColor = opacity * texel;
  92955. }
  92956. }
  92957. ` ,
  92958. depthTest: false,
  92959. depthWrite: false,
  92960. transparent: true
  92961. });
  92962. ////////////////////
  92963. /* this.renderMat.blendSrc = THREE.OneFactor //即将写入缓冲区的颜色。
  92964. this.renderMat.blendDst = THREE.OneFactor //缓冲区已经存在的颜色
  92965. this.renderMat.blendEquation = THREE.AddEquation;
  92966. this.renderMat.blendEquationAlpha = THREE.AddEquation;
  92967. this.renderMat.blendDstAlpha = THREE.SrcAlphaFactor
  92968. this.renderMat.blendSrcAlpha = THREE.SrcAlphaFactor */
  92969. this.camera2 = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
  92970. this.scene2 = new Scene();
  92971. this.quad2 = new Mesh( new PlaneBufferGeometry( 2, 2 ), this.renderMat/* this.copyMaterial */ );
  92972. this.quad2.frustumCulled = false; // Avoid getting clipped
  92973. this.scene2.add( this.quad2 );
  92974. this.copyPass = new ShaderPass( CopyShader );
  92975. this.copyPass.renderToScreen = true;
  92976. };
  92977. SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), {
  92978. constructor: SSAARenderPass,
  92979. dispose: function () {
  92980. if ( this.sampleRenderTarget ) {
  92981. this.sampleRenderTarget.dispose();
  92982. this.sampleRenderTarget = null;
  92983. }
  92984. },
  92985. setSize: function ( width, height ) {
  92986. if ( this.sampleRenderTarget ) this.sampleRenderTarget.setSize( width, height );
  92987. this.childPass && this.childPass.setSize(width, height);
  92988. },
  92989. addPass: function (pass){
  92990. this.childPass = pass;
  92991. },
  92992. render: function (scene, camera, viewports, renderer, writeBuffer, readBuffer, maskActive, renderFun ) {
  92993. if(this.useCopy ){
  92994. scene = this.copyPass.scene; camera = this.copyPass.camera;
  92995. }
  92996. if ( ! this.sampleRenderTarget ) {
  92997. this.sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat } );
  92998. this.sampleRenderTarget.texture.name = "SSAARenderPass.sample";
  92999. }
  93000. var jitterOffsets = SSAARenderPass.JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ];
  93001. var autoClear = renderer.autoClear;
  93002. renderer.autoClear = false;
  93003. var oldClearColor = renderer.getClearColor(new Color).getHex();
  93004. var oldClearAlpha = renderer.getClearAlpha();
  93005. renderer.setClearColor( this.clearColor, this.clearAlpha );
  93006. var baseSampleWeight = 1.0 / jitterOffsets.length;
  93007. var roundingRange = 1 / 32;
  93008. //this.copyUniforms[ "tDiffuse" ].value = this.sampleRenderTarget.texture;
  93009. let oldTarget = renderer.getRenderTarget();
  93010. if(oldTarget){
  93011. if(oldTarget.scissorTest){
  93012. var width = oldTarget.scissor.w, height = oldTarget.scissor.z;
  93013. }else {
  93014. var width = oldTarget.width, height = oldTarget.height;
  93015. }
  93016. }else {
  93017. var width = readBuffer.width, height = readBuffer.height;
  93018. }
  93019. // render the scene multiple times, each slightly jitter offset from the last and accumulate the results.
  93020. let opa = 0;
  93021. for ( var i = 0; i < jitterOffsets.length; i ++ ) {
  93022. var jitterOffset = jitterOffsets[ i ];
  93023. if ( camera.setViewOffset ) {
  93024. camera.setViewOffset( width, height,
  93025. jitterOffset[ 0 ] * 0.0625 , jitterOffset[ 1 ] * 0.0625 , // 0.0625 = 1 / 16
  93026. width, height );
  93027. }
  93028. var sampleWeight = baseSampleWeight;
  93029. if ( this.unbiased ) {//更柔和
  93030. var uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length );
  93031. sampleWeight += roundingRange * uniformCenteredDistribution;
  93032. }
  93033. renderer.setRenderTarget(this.sampleRenderTarget);
  93034. renderer.clear();
  93035. if(this.useCopy){
  93036. this.copyPass.render(scene,camera, null,renderer, writeBuffer, readBuffer );
  93037. }else {
  93038. if(renderFun){
  93039. renderFun({target : this.sampleRenderTarget});
  93040. }else {
  93041. renderer.render( scene, camera );
  93042. }
  93043. }
  93044. renderer.setRenderTarget(oldTarget);
  93045. //---------------------
  93046. //获取outline tex
  93047. let hasOutline = this.childPass && this.childPass.render(scene, camera, renderer, writeBuffer, readBuffer, null, renderFun );
  93048. //合成到该材质
  93049. this.renderUniforms[ "bgTex" ].value = this.sampleRenderTarget.texture;
  93050. this.renderUniforms[ "outlineTex" ].value = hasOutline ? readBuffer.texture : null;
  93051. this.renderUniforms[ "opacity" ].value = sampleWeight;
  93052. /* console.log('sampleWeight', sampleWeight)
  93053. opa += sampleWeight */
  93054. if(!this.renderToScreen){
  93055. renderer.setRenderTarget(writeBuffer);
  93056. }
  93057. if(i === 0 ){
  93058. renderer.setClearColor( 0x000000, 0 ); //叠加前颜色必须0
  93059. renderer.clear();
  93060. }
  93061. renderer.render( this.scene2, this.camera2); // , this.renderToScreen ? null : writeBuffer, ( i === 0 )
  93062. if(!this.renderToScreen){
  93063. renderer.setRenderTarget(oldTarget);
  93064. }
  93065. //if(i==2)break;
  93066. }
  93067. //console.log('sum:',opa)
  93068. if ( camera.clearViewOffset )camera.clearViewOffset();
  93069. //renderer.setRenderTarget(readBuffer)
  93070. //renderer.setClearColor( 0x000000, 0 );
  93071. //renderer.clear()
  93072. /* this.quad2.material = this.renderMat2
  93073. this.renderMat2.uniforms.tDiffuse.value = writeBuffer.texture;
  93074. renderer.render( this.scene2, this.camera2);
  93075. this.quad2.material = this.renderMat */
  93076. //renderer.setRenderTarget(oldTarget)
  93077. renderer.autoClear = autoClear;
  93078. renderer.setClearColor( oldClearColor, oldClearAlpha );
  93079. /* 试了好几次,测量线的透明度还是还原不了。 clearAlpha十分影响结果。
  93080. 因为绘制测量线需要背景透明。 或许可以先全部绘制完后,再 copyshader中 抗锯齿?
  93081. 另外会有黑边。
  93082. */
  93083. }
  93084. } );
  93085. // These jitter vectors are specified in integers because it is easier.
  93086. // I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5)
  93087. // before being used, thus these integers need to be scaled by 1/16.
  93088. //
  93089. // Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
  93090. SSAARenderPass.JitterVectors = [
  93091. [
  93092. [ 0, 0 ]
  93093. ],
  93094. [
  93095. [ 4, 4 ], [ - 4, - 4 ]
  93096. ],
  93097. [
  93098. [ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ]
  93099. ],
  93100. [
  93101. [ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ],
  93102. [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ]
  93103. ],
  93104. [
  93105. [ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ],
  93106. [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ],
  93107. [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ],
  93108. [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ]
  93109. ],
  93110. [
  93111. [ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ],
  93112. [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ],
  93113. [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ],
  93114. [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ],
  93115. [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ],
  93116. [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ],
  93117. [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ],
  93118. [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]
  93119. ]
  93120. ];
  93121. class MaskPass extends Pass {
  93122. constructor( scene, camera ) {
  93123. super();
  93124. this.scene = scene;
  93125. this.camera = camera;
  93126. this.clear = true;
  93127. this.needsSwap = false;
  93128. this.inverse = false;
  93129. }
  93130. render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {
  93131. const context = renderer.getContext();
  93132. const state = renderer.state;
  93133. // don't update color or depth
  93134. state.buffers.color.setMask( false );
  93135. state.buffers.depth.setMask( false );
  93136. // lock buffers
  93137. state.buffers.color.setLocked( true );
  93138. state.buffers.depth.setLocked( true );
  93139. // set up stencil
  93140. let writeValue, clearValue;
  93141. if ( this.inverse ) {
  93142. writeValue = 0;
  93143. clearValue = 1;
  93144. } else {
  93145. writeValue = 1;
  93146. clearValue = 0;
  93147. }
  93148. state.buffers.stencil.setTest( true );
  93149. state.buffers.stencil.setOp( context.REPLACE, context.REPLACE, context.REPLACE );
  93150. state.buffers.stencil.setFunc( context.ALWAYS, writeValue, 0xffffffff );
  93151. state.buffers.stencil.setClear( clearValue );
  93152. state.buffers.stencil.setLocked( true );
  93153. // draw into the stencil buffer
  93154. renderer.setRenderTarget( readBuffer );
  93155. if ( this.clear ) renderer.clear();
  93156. renderer.render( this.scene, this.camera );
  93157. renderer.setRenderTarget( writeBuffer );
  93158. if ( this.clear ) renderer.clear();
  93159. renderer.render( this.scene, this.camera );
  93160. // unlock color and depth buffer for subsequent rendering
  93161. state.buffers.color.setLocked( false );
  93162. state.buffers.depth.setLocked( false );
  93163. // only render where stencil is set to 1
  93164. state.buffers.stencil.setLocked( false );
  93165. state.buffers.stencil.setFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1
  93166. state.buffers.stencil.setOp( context.KEEP, context.KEEP, context.KEEP );
  93167. state.buffers.stencil.setLocked( true );
  93168. }
  93169. }
  93170. class ClearMaskPass extends Pass {
  93171. constructor() {
  93172. super();
  93173. this.needsSwap = false;
  93174. }
  93175. render( renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */ ) {
  93176. renderer.state.buffers.stencil.setLocked( false );
  93177. renderer.state.buffers.stencil.setTest( false );
  93178. }
  93179. }
  93180. /**
  93181. * @author alteredq / http://alteredqualia.com/
  93182. */
  93183. var EffectComposer = function ( renderer, renderTarget ) {
  93184. this.renderer = renderer;
  93185. if ( renderTarget === undefined ) {
  93186. var parameters = {
  93187. minFilter: LinearFilter,
  93188. magFilter: LinearFilter,
  93189. format: RGBAFormat,
  93190. stencilBuffer: false,
  93191. };
  93192. var size = renderer.getDrawingBufferSize(new Vector2);
  93193. renderTarget = new WebGLRenderTarget( size.width, size.height , parameters );
  93194. renderTarget.texture.name = 'EffectComposer.rt1';
  93195. }
  93196. this.renderTarget1 = renderTarget;
  93197. this.renderTarget2 = renderTarget.clone();
  93198. this.renderTarget2.texture.name = 'EffectComposer.rt2';
  93199. this.writeBuffer = this.renderTarget1;
  93200. this.readBuffer = this.renderTarget2;
  93201. this.passes = [];
  93202. // dependencies
  93203. /* if ( THREE.CopyShader === undefined ) {
  93204. console.error( 'THREE.EffectComposer relies on THREE.CopyShader' );
  93205. }
  93206. if ( THREE.ShaderPass === undefined ) {
  93207. console.error( 'THREE.EffectComposer relies on THREE.ShaderPass' );
  93208. } */
  93209. this.copyPass = new ShaderPass( CopyShader );
  93210. viewer.addEventListener('resize',(e)=>{
  93211. this.setSize(e.viewport.resolution.x,e.viewport.resolution.y); //暂时假设composer渲染的viewer的viewports.length == 1
  93212. });
  93213. };
  93214. Object.assign( EffectComposer.prototype, {
  93215. swapBuffers: function () {
  93216. var tmp = this.readBuffer;
  93217. this.readBuffer = this.writeBuffer;
  93218. this.writeBuffer = tmp;
  93219. },
  93220. addPass: function ( pass ) {
  93221. this.passes.push( pass );
  93222. var size = this.renderer.getDrawingBufferSize(new Vector2);
  93223. pass.setSize( size.width, size.height );
  93224. },
  93225. removePass: function(pass){ //add
  93226. let index = this.passes.indexOf(pass);
  93227. index > -1 && this.passes.splice(index,1);
  93228. },
  93229. insertPass: function ( pass, index ) {
  93230. this.passes.splice( index, 0, pass );
  93231. },
  93232. render: function ( scene, camera, viewports, renderFun ) {
  93233. var maskActive = false;
  93234. let passes = this.passes.filter(e=>e.enabled);
  93235. var pass, i, il = passes.length;
  93236. if(this.readTarget){ //add 使用当前renderTarget中的像素
  93237. this.copyPass.render( scene, camera,viewports, this.renderer, this.readBuffer, this.renderer.getRenderTarget() );
  93238. }
  93239. for ( i = 0; i < il; i ++ ) {
  93240. pass = passes[ i ];
  93241. //if(i == il-1)pass.renderToScreen = true//
  93242. pass.render( scene, camera, viewports, this.renderer, this.writeBuffer, this.readBuffer, maskActive, renderFun );
  93243. if ( pass.needsSwap ) {
  93244. if ( maskActive ) {
  93245. var context = this.renderer.context;
  93246. context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
  93247. this.copyPass.render(null,null, viewports, this.renderer, this.writeBuffer, this.readBuffer );// delta
  93248. context.stencilFunc( context.EQUAL, 1, 0xffffffff );
  93249. }
  93250. this.swapBuffers();
  93251. }
  93252. if ( MaskPass !== undefined ) {
  93253. if ( pass instanceof MaskPass ) {
  93254. maskActive = true;
  93255. } else if ( pass instanceof ClearMaskPass ) {
  93256. maskActive = false;
  93257. }
  93258. }
  93259. }
  93260. //add
  93261. if(!pass.renderToScreen){ //最后一个如果没有绘制到屏幕or target上
  93262. this.copyPass.renderToScreen = true;
  93263. this.copyPass.render(null,null, viewports,this.renderer, this.writeBuffer, this.readBuffer);
  93264. }
  93265. },
  93266. reset: function ( renderTarget ) {
  93267. if ( renderTarget === undefined ) {
  93268. var size = this.renderer.getDrawingBufferSize(new Vector2);
  93269. renderTarget = this.renderTarget1.clone();
  93270. renderTarget.setSize( size.width, size.height );
  93271. }
  93272. this.renderTarget1.dispose();
  93273. this.renderTarget2.dispose();
  93274. this.renderTarget1 = renderTarget;
  93275. this.renderTarget2 = renderTarget.clone();
  93276. this.writeBuffer = this.renderTarget1;
  93277. this.readBuffer = this.renderTarget2;
  93278. },
  93279. setSize: function ( width, height, scaleRatio ) {
  93280. scaleRatio = scaleRatio || 1;
  93281. this.renderTarget1.setSize( width * scaleRatio , height * scaleRatio );
  93282. this.renderTarget2.setSize( width * scaleRatio, height * scaleRatio );
  93283. for ( var i = 0; i < this.passes.length; i ++ ) {
  93284. this.passes[ i ].setSize( width * scaleRatio, height * scaleRatio );
  93285. }
  93286. }
  93287. } );
  93288. /**
  93289. * @author alteredq / http://alteredqualia.com/
  93290. */
  93291. class RenderPass extends Pass {
  93292. constructor( overrideMaterial, clearColor, clearAlpha ) {
  93293. super();
  93294. /* this.scene = scene;
  93295. this.camera = camera; */
  93296. this.overrideMaterial = overrideMaterial;
  93297. this.clearColor = clearColor;
  93298. this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
  93299. this.clear = true;
  93300. this.clearDepth = false;
  93301. this.needsSwap = false;
  93302. this._oldClearColor = new Color();
  93303. }
  93304. render(scene, camera, viewports,renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {
  93305. const oldAutoClear = renderer.autoClear;
  93306. renderer.autoClear = false;
  93307. let oldClearAlpha, oldOverrideMaterial;
  93308. if ( this.overrideMaterial !== undefined ) {
  93309. oldOverrideMaterial = this.scene.overrideMaterial;
  93310. scene.overrideMaterial = this.overrideMaterial;
  93311. }
  93312. if ( this.clearColor ) {
  93313. renderer.getClearColor( this._oldClearColor );
  93314. oldClearAlpha = renderer.getClearAlpha();
  93315. renderer.setClearColor( this.clearColor, this.clearAlpha );
  93316. }
  93317. if ( this.clearDepth ) {
  93318. renderer.clearDepth();
  93319. }
  93320. let oldTarget = renderer.getRenderTarget();
  93321. if(!this.renderToScreen)renderer.setRenderTarget( readBuffer );
  93322. // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
  93323. if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
  93324. renderer.render( scene, camera );
  93325. if(!this.renderToScreen)renderer.setRenderTarget( oldTarget );
  93326. if ( this.clearColor ) {
  93327. renderer.setClearColor( this._oldClearColor, oldClearAlpha );
  93328. }
  93329. if ( this.overrideMaterial !== undefined ) {
  93330. scene.overrideMaterial = oldOverrideMaterial;
  93331. }
  93332. renderer.autoClear = oldAutoClear;
  93333. }
  93334. }
  93335. /**
  93336. * NVIDIA FXAA by Timothy Lottes
  93337. * https://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf
  93338. * - WebGL port by @supereggbert
  93339. * http://www.glge.org/demos/fxaa/
  93340. * Further improved by Daniel Sturk
  93341. */
  93342. const FXAAShader = {
  93343. uniforms: {
  93344. 'tDiffuse': { value: null },
  93345. 'resolution': { value: new Vector2( 1 / 1024, 1 / 512 ) }
  93346. },
  93347. vertexShader: /* glsl */`
  93348. varying vec2 vUv;
  93349. void main() {
  93350. vUv = uv;
  93351. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  93352. }`,
  93353. fragmentShader: `
  93354. precision highp float;
  93355. uniform sampler2D tDiffuse;
  93356. uniform vec2 resolution;
  93357. varying vec2 vUv;
  93358. // FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com)
  93359. //----------------------------------------------------------------------------------
  93360. // File: es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag
  93361. // SDK Version: v3.00
  93362. // Email: gameworks@nvidia.com
  93363. // Site: http://developer.nvidia.com/
  93364. //
  93365. // Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
  93366. //
  93367. // Redistribution and use in source and binary forms, with or without
  93368. // modification, are permitted provided that the following conditions
  93369. // are met:
  93370. // * Redistributions of source code must retain the above copyright
  93371. // notice, this list of conditions and the following disclaimer.
  93372. // * Redistributions in binary form must reproduce the above copyright
  93373. // notice, this list of conditions and the following disclaimer in the
  93374. // documentation and/or other materials provided with the distribution.
  93375. // * Neither the name of NVIDIA CORPORATION nor the names of its
  93376. // contributors may be used to endorse or promote products derived
  93377. // from this software without specific prior written permission.
  93378. //
  93379. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
  93380. // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  93381. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  93382. // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  93383. // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  93384. // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  93385. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  93386. // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  93387. // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  93388. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  93389. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  93390. //
  93391. //----------------------------------------------------------------------------------
  93392. #ifndef FXAA_DISCARD
  93393. //
  93394. // Only valid for PC OpenGL currently.
  93395. // Probably will not work when FXAA_GREEN_AS_LUMA = 1.
  93396. //
  93397. // 1 = Use discard on pixels which don't need AA.
  93398. // For APIs which enable concurrent TEX+ROP from same surface.
  93399. // 0 = Return unchanged color on pixels which don't need AA.
  93400. //
  93401. #define FXAA_DISCARD 0
  93402. #endif
  93403. /*--------------------------------------------------------------------------*/
  93404. //第三个参数加入后只能在片元着色器中调用,且只对采样器为mipmap类型纹理时有效。不明白作用??? 但警告说范围在16之内
  93405. #define FxaaTexTop(t, p) texture2D(t, p, -15.0); //-100.0);
  93406. #define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), -15.0); //-100.0)
  93407. /*--------------------------------------------------------------------------*/
  93408. #define NUM_SAMPLES 5
  93409. // assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha
  93410. float contrast( vec4 a, vec4 b ) {
  93411. vec4 diff = abs( a - b );
  93412. return max( max( max( diff.r, diff.g ), diff.b ), diff.a );
  93413. }
  93414. /*============================================================================
  93415. FXAA3 QUALITY - PC
  93416. ============================================================================*/
  93417. /*--------------------------------------------------------------------------*/
  93418. vec4 FxaaPixelShader(
  93419. vec2 posM,
  93420. sampler2D tex,
  93421. vec2 fxaaQualityRcpFrame,
  93422. float fxaaQualityEdgeThreshold,
  93423. float fxaaQualityinvEdgeThreshold
  93424. ) {
  93425. vec4 rgbaM = FxaaTexTop(tex, posM);
  93426. vec4 rgbaS = FxaaTexOff(tex, posM, vec2( 0.0, 1.0), fxaaQualityRcpFrame.xy);
  93427. vec4 rgbaE = FxaaTexOff(tex, posM, vec2( 1.0, 0.0), fxaaQualityRcpFrame.xy);
  93428. vec4 rgbaN = FxaaTexOff(tex, posM, vec2( 0.0,-1.0), fxaaQualityRcpFrame.xy);
  93429. vec4 rgbaW = FxaaTexOff(tex, posM, vec2(-1.0, 0.0), fxaaQualityRcpFrame.xy);
  93430. // . S .
  93431. // W M E
  93432. // . N .
  93433. bool earlyExit = max( max( max(
  93434. contrast( rgbaM, rgbaN ),
  93435. contrast( rgbaM, rgbaS ) ),
  93436. contrast( rgbaM, rgbaE ) ),
  93437. contrast( rgbaM, rgbaW ) )
  93438. < fxaaQualityEdgeThreshold;
  93439. // . 0 .
  93440. // 0 0 0
  93441. // . 0 .
  93442. #if (FXAA_DISCARD == 1)
  93443. if(earlyExit) FxaaDiscard;
  93444. #else
  93445. if(earlyExit) return rgbaM;
  93446. #endif
  93447. float contrastN = contrast( rgbaM, rgbaN );
  93448. float contrastS = contrast( rgbaM, rgbaS );
  93449. float contrastE = contrast( rgbaM, rgbaE );
  93450. float contrastW = contrast( rgbaM, rgbaW );
  93451. float relativeVContrast = ( contrastN + contrastS ) - ( contrastE + contrastW );
  93452. relativeVContrast *= fxaaQualityinvEdgeThreshold;
  93453. bool horzSpan = relativeVContrast > 0.;
  93454. // . 1 .
  93455. // 0 0 0
  93456. // . 1 .
  93457. // 45 deg edge detection and corners of objects, aka V/H contrast is too similar
  93458. if( abs( relativeVContrast ) < .3 ) {
  93459. // locate the edge
  93460. vec2 dirToEdge;
  93461. dirToEdge.x = contrastE > contrastW ? 1. : -1.;
  93462. dirToEdge.y = contrastS > contrastN ? 1. : -1.;
  93463. // . 2 . . 1 .
  93464. // 1 0 2 ~= 0 0 1
  93465. // . 1 . . 0 .
  93466. // tap 2 pixels and see which ones are "outside" the edge, to
  93467. // determine if the edge is vertical or horizontal
  93468. vec4 rgbaAlongH = FxaaTexOff(tex, posM, vec2( dirToEdge.x, -dirToEdge.y ), fxaaQualityRcpFrame.xy);
  93469. float matchAlongH = contrast( rgbaM, rgbaAlongH );
  93470. // . 1 .
  93471. // 0 0 1
  93472. // . 0 H
  93473. vec4 rgbaAlongV = FxaaTexOff(tex, posM, vec2( -dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy);
  93474. float matchAlongV = contrast( rgbaM, rgbaAlongV );
  93475. // V 1 .
  93476. // 0 0 1
  93477. // . 0 .
  93478. relativeVContrast = matchAlongV - matchAlongH;
  93479. relativeVContrast *= fxaaQualityinvEdgeThreshold;
  93480. if( abs( relativeVContrast ) < .3 ) { // 45 deg edge
  93481. // 1 1 .
  93482. // 0 0 1
  93483. // . 0 1
  93484. // do a simple blur
  93485. return mix(
  93486. rgbaM,
  93487. (rgbaN + rgbaS + rgbaE + rgbaW) * .25,
  93488. .4
  93489. );
  93490. }
  93491. horzSpan = relativeVContrast > 0.;
  93492. }
  93493. if(!horzSpan) rgbaN = rgbaW;
  93494. if(!horzSpan) rgbaS = rgbaE;
  93495. // . 0 . 1
  93496. // 1 0 1 -> 0
  93497. // . 0 . 1
  93498. bool pairN = contrast( rgbaM, rgbaN ) > contrast( rgbaM, rgbaS );
  93499. if(!pairN) rgbaN = rgbaS;
  93500. vec2 offNP;
  93501. offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
  93502. offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
  93503. bool doneN = false;
  93504. bool doneP = false;
  93505. float nDist = 0.;
  93506. float pDist = 0.;
  93507. vec2 posN = posM;
  93508. vec2 posP = posM;
  93509. int iterationsUsed = 0;
  93510. int iterationsUsedN = 0;
  93511. int iterationsUsedP = 0;
  93512. for( int i = 0; i < NUM_SAMPLES; i++ ) {
  93513. iterationsUsed = i;
  93514. float increment = float(i + 1);
  93515. if(!doneN) {
  93516. nDist += increment;
  93517. posN = posM + offNP * nDist;
  93518. vec4 rgbaEndN = FxaaTexTop(tex, posN.xy);
  93519. doneN = contrast( rgbaEndN, rgbaM ) > contrast( rgbaEndN, rgbaN );
  93520. iterationsUsedN = i;
  93521. }
  93522. if(!doneP) {
  93523. pDist += increment;
  93524. posP = posM - offNP * pDist;
  93525. vec4 rgbaEndP = FxaaTexTop(tex, posP.xy);
  93526. doneP = contrast( rgbaEndP, rgbaM ) > contrast( rgbaEndP, rgbaN );
  93527. iterationsUsedP = i;
  93528. }
  93529. if(doneN || doneP) break;
  93530. }
  93531. if ( !doneP && !doneN ) return rgbaM; // failed to find end of edge
  93532. float dist = min(
  93533. doneN ? float( iterationsUsedN ) / float( NUM_SAMPLES - 1 ) : 1.,
  93534. doneP ? float( iterationsUsedP ) / float( NUM_SAMPLES - 1 ) : 1.
  93535. );
  93536. // hacky way of reduces blurriness of mostly diagonal edges
  93537. // but reduces AA quality
  93538. dist = pow(dist, .5);
  93539. dist = 1. - dist;
  93540. return mix(
  93541. rgbaM,
  93542. rgbaN,
  93543. dist * .5
  93544. );
  93545. }
  93546. void main() {
  93547. const float edgeDetectionQuality = 0.2;//.05 ; //越高,越保留细节;越低,越平滑 但模糊
  93548. const float invEdgeDetectionQuality = 1. / edgeDetectionQuality;
  93549. gl_FragColor = FxaaPixelShader(
  93550. vUv,
  93551. tDiffuse,
  93552. resolution,
  93553. edgeDetectionQuality, // [0,1] contrast needed, otherwise early discard
  93554. invEdgeDetectionQuality
  93555. );
  93556. }
  93557. `
  93558. };
  93559. /**
  93560. * @author spidersharma / http://eduperiment.com/
  93561. */
  93562. let OutlinePass = function ( selectedObjects ) {
  93563. /* scene = scene;
  93564. camera = camera; */
  93565. this.selectedObjects = selectedObjects !== undefined ? selectedObjects : [];
  93566. this.visibleEdgeColor = new Color( 1, 1, 1 );
  93567. this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 );
  93568. this.edgeGlow = 0.0;
  93569. this.usePatternTexture = false;
  93570. //this.edgeThickness = 1.0;
  93571. this.edgeStrength = 50;
  93572. this.downSampleRatio = 1;//2; // 抗锯齿 值越低renderTarget size越大,抗锯齿越强,线条可越细(或许可以把模糊化去掉?)
  93573. this.pulsePeriod = 0;
  93574. this.showHiddenPart = false; //是否判断被遮住的部分,以设置hiddenEdgeColor。一般不需要
  93575. Pass.call( this );
  93576. this.resolution = new Vector2( 256, 256 );
  93577. var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
  93578. var resx = Math.round( this.resolution.x / this.downSampleRatio );
  93579. var resy = Math.round( this.resolution.y / this.downSampleRatio );
  93580. this.renderTargetMaskBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
  93581. this.renderTargetMaskBuffer.texture.name = "OutlinePass.mask";
  93582. this.renderTargetMaskBuffer.texture.generateMipmaps = false;
  93583. this.depthMaterial = new MeshDepthMaterial();
  93584. this.depthMaterial.side = DoubleSide;
  93585. this.depthMaterial.depthPacking = RGBADepthPacking;
  93586. this.depthMaterial.blending = NoBlending;
  93587. this.prepareMaskMaterial = this.getPrepareMaskMaterial();
  93588. this.prepareMaskMaterial.side = DoubleSide;
  93589. this.renderTargetDepthBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
  93590. this.renderTargetDepthBuffer.texture.name = "OutlinePass.depth";
  93591. this.renderTargetDepthBuffer.texture.generateMipmaps = false;
  93592. this.edgeDetectionMaterial = this.getEdgeDetectionMaterial(this.edgeStrength);
  93593. this.renderTargetEdgeBuffer1 = new WebGLRenderTarget( resx, resy, pars );
  93594. this.renderTargetEdgeBuffer1.texture.name = "OutlinePass.edge1";
  93595. this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
  93596. // Overlay material
  93597. this.overlayMaterial = this.getOverlayMaterial();
  93598. // copy material
  93599. this.copyUniforms = UniformsUtils.clone( CopyShader.uniforms );
  93600. this.copyUniforms[ "opacity" ].value = 1.0;
  93601. this.materialCopy = new ShaderMaterial( {
  93602. uniforms: this.copyUniforms,
  93603. vertexShader: CopyShader.vertexShader,
  93604. fragmentShader: CopyShader.fragmentShader,
  93605. blending: NoBlending,
  93606. depthTest: false,
  93607. depthWrite: false,
  93608. transparent: true
  93609. } );
  93610. this.enabled = true;
  93611. this.needsSwap = false;
  93612. this.oldClearColor = new Color();
  93613. this.oldClearAlpha = 1;
  93614. this.camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
  93615. this.scene = new Scene();
  93616. this.quad = new Mesh( new PlaneBufferGeometry( 2, 2 ), null );
  93617. this.quad.frustumCulled = false; // Avoid getting clipped
  93618. this.scene.add( this.quad );
  93619. this.textureMatrix = new Matrix4();
  93620. };
  93621. OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
  93622. constructor: OutlinePass,
  93623. dispose: function () {
  93624. this.renderTargetMaskBuffer.dispose();
  93625. this.renderTargetEdgeBuffer1.dispose();
  93626. this.renderTargetDepthBuffer.dispose();
  93627. },
  93628. replaceDepthToViewZ( camera ) {
  93629. var type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic';
  93630. if(type == this.lastCameraType )return
  93631. this.lastCameraType = type;
  93632. this.prepareMaskMaterial.fragmentShader = this.prepareMaskMaterial.fragmentShader.replace( /DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ' );
  93633. this.prepareMaskMaterial.needsUpdate = true;
  93634. },
  93635. setSize: function ( width, height ) {
  93636. this.renderTargetEdgeBuffer1.setSize( width, height );
  93637. this.renderTargetMaskBuffer.setSize( width, height );
  93638. this.resolution.set(width,height);
  93639. },
  93640. changeVisibilityOfSelectedObjects: function ( bVisible ) {
  93641. function gatherSelectedMeshesCallBack( object ) {
  93642. /* if ( object.isMesh ) { */
  93643. if ( object.isPointcloud || object.isMesh || object.isLine || object.isSprite ) {
  93644. /* if ( bVisible ) {
  93645. object.visible = object.userData.oldVisible;
  93646. delete object.userData.oldVisible;
  93647. } else {
  93648. object.userData.oldVisible = object.visible;
  93649. object.visible = bVisible;
  93650. } */
  93651. Potree.Utils.updateVisible(object, 'overlinePass', bVisible);
  93652. }
  93653. }
  93654. for ( var i = 0; i < this.selectedObjects.length; i ++ ) {
  93655. var selectedObject = this.selectedObjects[ i ];
  93656. selectedObject.traverse( gatherSelectedMeshesCallBack );
  93657. }
  93658. },
  93659. changeVisibilityOfNonSelectedObjects: function ( bVisible , scenes) {
  93660. var selectedMeshes = [];
  93661. function gatherSelectedMeshesCallBack( object ) {
  93662. //if ( object.isMesh ) selectedMeshes.push( object );
  93663. if ( object.isPointcloud || object.isMesh || object.isLine || object.isSprite ) {
  93664. selectedMeshes.push( object );
  93665. }
  93666. }
  93667. for ( var i = 0; i < this.selectedObjects.length; i ++ ) {
  93668. var selectedObject = this.selectedObjects[ i ];
  93669. selectedObject.traverse( gatherSelectedMeshesCallBack );
  93670. }
  93671. function VisibilityChangeCallBack( object ) {
  93672. if ( object.isPointcloud || object.isMesh || object.isLine || object.isSprite ) {
  93673. var bFound = false;
  93674. for ( var i = 0; i < selectedMeshes.length; i ++ ) {
  93675. var selectedObjectId = selectedMeshes[ i ].id;
  93676. if ( selectedObjectId === object.id ) {
  93677. bFound = true;
  93678. break;
  93679. }
  93680. }
  93681. if ( ! bFound ) {
  93682. var visibility = object.visible;
  93683. Potree.Utils.updateVisible(object, 'overlinePass', bVisible); //add
  93684. //但保不齐在设置为false后,渲染时又true了,所以在其他地方update时设置visible 得用updateVisible
  93685. if(!bVisible){
  93686. object.visible = false;
  93687. }else {
  93688. object.visible = !!object.bVisible;
  93689. }
  93690. object.bVisible = visibility;
  93691. //这两种updateVisible 和 visible 设置都不能去掉, 第一块是为了防止有的visible不是通过updateVisible设置的; 第二块是为了防止渲染时updateVisible又修改了visible为true, 另外渲染时
  93692. return {stopContinue:true} //for pointcloud
  93693. }
  93694. }
  93695. }
  93696. scenes.forEach(scene=>scene.traverse( VisibilityChangeCallBack ));
  93697. },
  93698. updateTextureMatrix: function (camera) {
  93699. this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
  93700. 0.0, 0.5, 0.0, 0.5,
  93701. 0.0, 0.0, 0.5, 0.5,
  93702. 0.0, 0.0, 0.0, 1.0 );
  93703. this.textureMatrix.multiply( camera.projectionMatrix );
  93704. this.textureMatrix.multiply( camera.matrixWorldInverse );
  93705. },
  93706. render: function (scenes, camera, viewports, renderer, writeBuffer, readBuffer, maskActive, renderFun ) {
  93707. if(!(scenes instanceof Array))scenes = [scenes];
  93708. if ( this.selectedObjects.length > 0 && this.edgeStrength > 0) {
  93709. let render2 = (target, dontRenderRtEDL=true)=>{
  93710. if(renderFun){
  93711. renderFun({target , dontRenderRtEDL });
  93712. }else {
  93713. renderer.setRenderTarget(target);
  93714. renderer.clear();
  93715. scenes.forEach(scene=>renderer.render( scene, camera));
  93716. }
  93717. };
  93718. this.oldClearColor.copy( renderer.getClearColor(new Color) );
  93719. this.oldClearAlpha = renderer.getClearAlpha();
  93720. let oldAutoClear = renderer.autoClear;
  93721. let oldTarget = renderer.getRenderTarget();
  93722. renderer.autoClear = false;
  93723. if ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST );
  93724. renderer.setClearColor( 0xffffff, 1 );
  93725. let oldBG = viewer.background, oldBgOpacity = viewer.backgroundOpacity;
  93726. viewer.background = new Color(1,1,1);
  93727. viewer.backgroundOpacity = 1;
  93728. if(this.showHiddenPart){ //几乎不会使用
  93729. viewports.forEach(e=>{
  93730. e.oldBeforeRender = e.beforeRender;
  93731. e.beforeRender = ()=>{
  93732. e.oldBeforeRender && e.oldBeforeRender();
  93733. this.replaceDepthToViewZ( e.camera );
  93734. };
  93735. });
  93736. // Make selected objects invisible
  93737. this.changeVisibilityOfSelectedObjects( false );
  93738. scenes.forEach(scene=>{
  93739. scene.currentBackground = scene.background;
  93740. scene.background = null;
  93741. // 1. Draw Non Selected objects in the depth buffer
  93742. scene.overrideMaterial = this.depthMaterial;
  93743. });
  93744. render2(this.renderTargetDepthBuffer);
  93745. // Make selected objects visible
  93746. this.changeVisibilityOfSelectedObjects( true );
  93747. viewports.forEach(e=>{
  93748. e.beforeRender = ()=>{
  93749. e.oldBeforeRender && e.oldBeforeRender();
  93750. // Update Texture Matrix for Depth compare
  93751. this.updateTextureMatrix(e.camera);
  93752. this.prepareMaskMaterial.uniforms[ "cameraNearFar" ].value = new Vector2( e.camera.near, e.camera.far );
  93753. };
  93754. });
  93755. }else {
  93756. //不渲染背景
  93757. scenes.forEach(scene=>{
  93758. scene.currentBackground = scene.background;
  93759. scene.background = null;
  93760. });
  93761. }
  93762. let colorType, colors = new Map() , opas = new Map();
  93763. {//绘制选中部分
  93764. // Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects
  93765. this.changeVisibilityOfNonSelectedObjects( false , scenes);
  93766. scenes.forEach(scene=>{
  93767. scene.overrideMaterial = this.prepareMaskMaterial;
  93768. });
  93769. if(this.showHiddenPart){
  93770. this.prepareMaskMaterial.uniforms[ "depthTexture" ].value = this.renderTargetDepthBuffer.texture;
  93771. this.prepareMaskMaterial.uniforms[ "textureMatrix" ].value = this.textureMatrix;
  93772. }
  93773. //因为点云不受prepareMaskMaterial作用,所以手动将他们变为黑色不透明
  93774. viewer.scene.pointclouds.forEach(e=>{ //先将点云透明度变为1,因为点云透明度莫名其妙会影响其r值//
  93775. colorType = e.material.activeAttributeName;
  93776. e.material.activeAttributeName = 'color';
  93777. colors.set(e, e.material.color);
  93778. e.material.color = '#000000';
  93779. opas.set(e, e.material.opacity);
  93780. e.material.opacity = 1;
  93781. });
  93782. }
  93783. render2(this.renderTargetMaskBuffer);
  93784. {//恢复
  93785. viewer.scene.pointclouds.forEach(e=>{
  93786. e.material.activeAttributeName = colorType;
  93787. e.material.color = colors.get(e);
  93788. e.material.opacity = opas.get(e);
  93789. });
  93790. if(this.showHiddenPart){
  93791. viewports.forEach((e)=>{e.beforeRender = e.oldBeforeRender;});
  93792. }
  93793. scenes.forEach(scene=>{
  93794. scene.overrideMaterial = null;
  93795. scene.background = scene.currentBackground;
  93796. });
  93797. viewer.background = oldBG;
  93798. viewer.backgroundOpacity = oldBgOpacity;
  93799. this.changeVisibilityOfNonSelectedObjects( true , scenes);
  93800. }
  93801. //检测边缘并绘制
  93802. // 3. Apply Edge Detection Pass
  93803. this.quad.material = this.edgeDetectionMaterial;
  93804. this.edgeDetectionMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskBuffer.texture;//this.renderTargetMaskDownSampleBuffer.texture;
  93805. this.edgeDetectionMaterial.uniforms[ "texSize" ].value = new Vector2(this.resolution.x, this.resolution.y );//new THREE.Vector2( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height );
  93806. //this.edgeDetectionMaterial.uniforms[ "texSize" ].value = new THREE.Vector2(this.renderTargetMaskBuffer.width, this.renderTargetMaskBuffer.height)//new THREE.Vector2( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height );
  93807. this.edgeDetectionMaterial.uniforms[ "edgeStrength" ].value = this.edgeStrength;
  93808. this.edgeDetectionMaterial.uniforms[ "visibleEdgeColor" ].value = this.visibleEdgeColor;//this.tempPulseColor1;
  93809. this.edgeDetectionMaterial.uniforms[ "hiddenEdgeColor" ].value = this.hiddenEdgeColor; //this.tempPulseColor2;
  93810. let buffer;
  93811. if ( this.renderToScreen ) {
  93812. this.quad.material.transparent = true;
  93813. buffer = null;
  93814. renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );
  93815. render2(null,false); //普通绘制原场景
  93816. //绘制到全屏
  93817. let renderSize = renderer.getSize(new Vector2()); //是client大小
  93818. renderer.setViewport(0, 0, renderSize.x, renderSize.y); //规定视口,影响图形变换(画布的使用范围)
  93819. renderer.setScissorTest( false );
  93820. }else {
  93821. buffer = readBuffer;
  93822. renderer.setClearColor( 0x000000, 0 );
  93823. renderer.clear();
  93824. }
  93825. renderer.setRenderTarget( buffer );
  93826. renderer.render( this.scene, this.camera ); //将边缘覆盖上去
  93827. renderer.setRenderTarget(oldTarget);
  93828. renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );
  93829. renderer.autoClear = oldAutoClear;
  93830. return true
  93831. }
  93832. },
  93833. getPrepareMaskMaterial: function () {
  93834. if(this.showHiddenPart){
  93835. return new ShaderMaterial( {
  93836. uniforms: {
  93837. "depthTexture": { value: null },
  93838. "cameraNearFar": { value: new Vector2( 0.5, 0.5 ) },
  93839. "textureMatrix": { value: new Matrix4() }
  93840. },
  93841. vertexShader: [
  93842. 'varying vec4 projTexCoord;',
  93843. 'varying vec4 vPosition;',
  93844. 'uniform mat4 textureMatrix;',
  93845. 'void main() {',
  93846. ' vPosition = modelViewMatrix * vec4( position, 1.0 );',
  93847. ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
  93848. ' projTexCoord = textureMatrix * worldPosition;',
  93849. ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
  93850. '}'
  93851. ].join( '\n' ),
  93852. fragmentShader: [
  93853. '#include <packing>',
  93854. 'varying vec4 vPosition;',
  93855. 'varying vec4 projTexCoord;',
  93856. 'uniform sampler2D depthTexture;',
  93857. 'uniform vec2 cameraNearFar;',
  93858. 'void main() {',
  93859. ' float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));',
  93860. ' float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );',
  93861. ' float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;', //决定是否为hiddenPart
  93862. ' gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);',
  93863. '}'
  93864. ].join( '\n' )
  93865. } );//没有绘制部分的颜色是clearColor,255
  93866. }else {
  93867. return new MeshBasicMaterial({color:'#000000'}) //不检测深度,不判断遮挡
  93868. }
  93869. },
  93870. getEdgeDetectionMaterial: function (edgeStrength) {
  93871. return new ShaderMaterial( {
  93872. uniforms: {
  93873. "edgeStrength": { value: edgeStrength },
  93874. "maskTexture": { value: null },
  93875. "texSize": { value: new Vector2( 10, 10 ) },
  93876. "visibleEdgeColor": { value: new Vector3( 1.0, 1.0, 1.0 ) },
  93877. "hiddenEdgeColor": { value: new Vector3( 1.0, 1.0, 1.0 ) },
  93878. },
  93879. vertexShader:
  93880. "varying vec2 vUv;\n\
  93881. void main() {\n\
  93882. vUv = uv;\n\
  93883. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
  93884. }",
  93885. /* fragmentShader:
  93886. "varying vec2 vUv;\
  93887. uniform sampler2D maskTexture;\
  93888. uniform vec2 texSize;\
  93889. uniform vec3 visibleEdgeColor;\
  93890. uniform vec3 hiddenEdgeColor;\
  93891. \
  93892. void main() {\n\
  93893. vec2 invSize = 1.0 / texSize;\
  93894. vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\
  93895. vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);\
  93896. vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);\
  93897. vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);\
  93898. vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);\
  93899. float diff1 = (c1.r - c2.r)*0.5;\
  93900. float diff2 = (c3.r - c4.r)*0.5;\
  93901. float d = length( vec2(diff1, diff2) );\
  93902. float a1 = min(c1.g, c2.g);\
  93903. float a2 = min(c3.g, c4.g);\
  93904. float visibilityFactor = min(a1, a2);\
  93905. vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\
  93906. gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\
  93907. }" */
  93908. fragmentShader:
  93909. `varying vec2 vUv;
  93910. uniform sampler2D maskTexture;
  93911. uniform float edgeStrength;
  93912. uniform vec2 texSize;
  93913. uniform vec3 visibleEdgeColor;
  93914. uniform vec3 hiddenEdgeColor;
  93915. void main() {
  93916. const float thickness = 1.0;
  93917. vec2 invSize = thickness / texSize;
  93918. vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);
  93919. vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);
  93920. vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);
  93921. vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);
  93922. vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);
  93923. float diff1 = (c1.r - c2.r)*0.5; //检测边缘,
  93924. float diff2 = (c3.r - c4.r)*0.5;
  93925. float d = length( vec2(diff1, diff2) ) * edgeStrength;
  93926. float a1 = min(c1.g, c2.g);
  93927. float a2 = min(c3.g, c4.g);
  93928. float visibilityFactor = min(a1, a2); //检测深度值,是否被遮挡
  93929. vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;
  93930. //gl_FragColor = vec4(0.0,1.0,0.0,1.0);
  93931. gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);
  93932. }`
  93933. } );
  93934. //为什么vec4(0.0,1.0,1.0,1.0); 显示出来的是rgb(109,255,255) ? 几乎只有绿色通道会影响红色通道
  93935. },
  93936. getSeperableBlurMaterial: function ( maxRadius ) {
  93937. return new ShaderMaterial( {
  93938. defines: {
  93939. "MAX_RADIUS": maxRadius,
  93940. },
  93941. uniforms: {
  93942. "colorTexture": { value: null },
  93943. "texSize": { value: new Vector2( 0.5, 0.5 ) },
  93944. "direction": { value: new Vector2( 0.5, 0.5 ) },
  93945. "kernelRadius": { value: 1.0 }
  93946. },
  93947. vertexShader:
  93948. "varying vec2 vUv;\n\
  93949. void main() {\n\
  93950. vUv = uv;\n\
  93951. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
  93952. }",
  93953. fragmentShader:
  93954. "#include <common>\
  93955. varying vec2 vUv;\
  93956. uniform sampler2D colorTexture;\
  93957. uniform vec2 texSize;\
  93958. uniform vec2 direction;\
  93959. uniform float kernelRadius;\
  93960. \
  93961. float gaussianPdf(in float x, in float sigma) {\
  93962. return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\
  93963. }\
  93964. void main() {\
  93965. vec2 invSize = 1.0 / texSize;\
  93966. float weightSum = gaussianPdf(0.0, kernelRadius);\
  93967. vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\
  93968. vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\
  93969. vec2 uvOffset = delta;\
  93970. for( int i = 1; i <= MAX_RADIUS; i ++ ) {\
  93971. float w = gaussianPdf(uvOffset.x, kernelRadius);\
  93972. vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb;\
  93973. vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb;\
  93974. diffuseSum += ((sample1 + sample2) * w);\
  93975. weightSum += (2.0 * w);\
  93976. uvOffset += delta;\
  93977. }\
  93978. gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\
  93979. }"
  93980. } );
  93981. },
  93982. getOverlayMaterial: function () {//对边缘线进一步处理,已被废弃
  93983. return new ShaderMaterial( {
  93984. uniforms: {
  93985. "maskTexture": { value: null },
  93986. "edgeTexture1": { value: null },
  93987. "edgeTexture2": { value: null },
  93988. "patternTexture": { value: null },
  93989. "edgeStrength": { value: 1.0 },
  93990. "edgeGlow": { value: 1.0 },
  93991. "usePatternTexture": { value: 0.0 }
  93992. },
  93993. vertexShader:
  93994. "varying vec2 vUv;\n\
  93995. void main() {\n\
  93996. vUv = uv;\n\
  93997. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
  93998. }",
  93999. /* fragmentShader:
  94000. "varying vec2 vUv;\
  94001. uniform sampler2D maskTexture;\
  94002. uniform sampler2D edgeTexture1;\
  94003. uniform sampler2D edgeTexture2;\
  94004. uniform sampler2D patternTexture;\
  94005. uniform float edgeStrength;\
  94006. uniform float edgeGlow;\
  94007. uniform bool usePatternTexture;\
  94008. \
  94009. void main() {\
  94010. vec4 edgeValue1 = texture2D(edgeTexture1, vUv);\
  94011. vec4 edgeValue2 = texture2D(edgeTexture2, vUv);\
  94012. vec4 maskColor = texture2D(maskTexture, vUv);\
  94013. vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\
  94014. float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\
  94015. vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\
  94016. vec4 finalColor = edgeStrength * maskColor.r * edgeValue;\ // 删除 * maskColor.r 也就是去掉遮罩,使模型部分也有outline
  94017. if(usePatternTexture)\
  94018. finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\
  94019. gl_FragColor = finalColor;\
  94020. }", */
  94021. fragmentShader:
  94022. `varying vec2 vUv;
  94023. uniform sampler2D edgeTexture1;
  94024. uniform float edgeStrength;
  94025. void main() {
  94026. gl_FragColor = edgeStrength * texture2D(edgeTexture1, vUv);
  94027. }`,
  94028. blending: AdditiveBlending,
  94029. depthTest: false,
  94030. depthWrite: false,
  94031. transparent: true
  94032. } );
  94033. }
  94034. } );
  94035. OutlinePass.BlurDirectionX = new Vector2( 1.0, 0.0 );
  94036. OutlinePass.BlurDirectionY = new Vector2( 0.0, 1.0 );
  94037. /*
  94038. 渲染步骤:(没有showHiddenPart时)
  94039. 仅绘制选中部分,材质为普通的单色材质,颜色是黑色不透明。未绘制部分的clearColor是白色不透明。
  94040. (详见prepareMaskMaterial,输出的r要为0)
  94041. 然后在上面绘制的图中,根据r的差值,得到边缘线。
  94042. 正常绘制场景之后,将上面的边缘线覆盖于其上。
  94043. (如果showHiddenPart,最开始还要先隐藏选中部分,这是为了得到非选中部分的深度值,然后再绘制选中部分时去比较选中和非选中部分之间的深度差异。以判断是否被遮挡。)
  94044. */
  94045. /**
  94046. * @author mschuetz / http://mschuetz.at
  94047. *
  94048. * adapted from THREE.OrbitControls by
  94049. *
  94050. * @author qiao / https://github.com/qiao
  94051. * @author mrdoob / http://mrdoob.com
  94052. * @author alteredq / http://alteredqualia.com/
  94053. * @author WestLangley / http://github.com/WestLangley
  94054. * @author erich666 / http://erichaines.com
  94055. *
  94056. *
  94057. *
  94058. */
  94059. let Buttons$2 = Potree.defines.Buttons;
  94060. class FirstPersonControls extends EventDispatcher {
  94061. constructor (viewer, viewport) {
  94062. super();
  94063. this.viewer = viewer;
  94064. this.renderer = viewer.renderer;
  94065. this.scene = viewer.scene;
  94066. this.rotationSpeed = 200;
  94067. this.moveSpeed = 10;
  94068. this.setCurrentViewport({hoverViewport:viewport, force:true}); //this.currentViewport = viewport
  94069. this.keys = {
  94070. FORWARD: ['W'.charCodeAt(0), 38],
  94071. BACKWARD: ['S'.charCodeAt(0), 40],
  94072. LEFT: ['A'.charCodeAt(0), 37],
  94073. RIGHT: ['D'.charCodeAt(0), 39],
  94074. UP: ['Q'.charCodeAt(0)],
  94075. DOWN: ['E'.charCodeAt(0)],
  94076. //SHIFT : [16],
  94077. ALT : [18],
  94078. Rotate_LEFT : ['L'.charCodeAt(0)],
  94079. Rotate_RIGHT : ['J'.charCodeAt(0)],
  94080. Rotate_UP : ['K'.charCodeAt(0)],
  94081. Rotate_DOWN : ['I'.charCodeAt(0)],
  94082. };
  94083. this.fadeFactor = 20;
  94084. this.yawDelta = 0;
  94085. this.pitchDelta = 0;
  94086. this.translationDelta = new Vector3(0, 0, 0);
  94087. this.translationWorldDelta = new Vector3(0, 0, 0);
  94088. this.tweens = [];
  94089. this.dollyStart = new Vector2;
  94090. this.dollyEnd = new Vector2;
  94091. //this.enableChangePos = true
  94092. this.viewer.addEventListener('camera_changed',(e)=>{
  94093. if(this.viewer.name == 'mapViewer' || e.changeInfo && e.changeInfo.positionChanged && !window.viewer.mainViewport.view.isFlying() ){
  94094. this.setFPCMoveSpeed(e.viewport);
  94095. }
  94096. });
  94097. let drag = (e) => {
  94098. if(!this.enabled)return
  94099. let viewport = e.dragViewport;
  94100. if(!viewport)return
  94101. let camera = viewport.camera;
  94102. let mode;
  94103. if(e.isTouch){
  94104. if(e.touches.length == 1){
  94105. mode = (!e.dragViewport || e.dragViewport.name == 'MainView') ? 'rotate' : 'pan';
  94106. }else if(e.touches.length == 2){
  94107. mode = Potree.settings.displayMode == 'showPanos' ? 'scale' : 'pan-scale';
  94108. }else {
  94109. mode = (!e.dragViewport || e.dragViewport.name == 'MainView') ? 'pan' : 'scale';
  94110. }
  94111. }else {
  94112. mode = (camera.type == 'OrthographicCamera' && e.buttons === Buttons$2.LEFT || camera.type != 'OrthographicCamera' && e.buttons === Buttons$2.RIGHT) ? 'pan' : 'rotate';
  94113. }
  94114. //console.log('mode ', mode )
  94115. let moveSpeed = this.currentViewport.getMoveSpeed();
  94116. if (e.drag.startHandled === undefined) {///???????
  94117. e.drag.startHandled = true;
  94118. this.dispatchEvent({type: 'start'});
  94119. }
  94120. if (mode.includes('rotate')) {//旋转
  94121. if(camera.type == "OrthographicCamera"){
  94122. let moveVec = Utils.getOrthoCameraMoveVec(e.drag.pointerDelta, camera );//最近一次移动向量
  94123. return viewer.navCubeViewer.rotateSideCamera( -e.drag.pointerDelta.x)
  94124. }
  94125. //来自panoramaControl updateRotation
  94126. if(!this.pointerDragStart){
  94127. return this.pointerDragStart = e.pointer.clone()
  94128. }
  94129. let view = this.scene.view;
  94130. if(this.rotateStartInfo.rotAroundPoint){//定点旋转: 以当前intersect的点为target旋转,不改点在屏幕中的位置
  94131. let distance = camera.position.distanceTo(this.rotateStartInfo.rotCenter/* this.intersectStart.location */); //不按下ctrl的话
  94132. if(this.rotateStartInfo.rotCenter2d.z>1)distance *= -1; //在背面
  94133. //按照orbitControl的方式旋转:
  94134. let rotationSpeed = 2;
  94135. this.yawDelta -= e.drag.pointerDelta.x * rotationSpeed;
  94136. this.pitchDelta += e.drag.pointerDelta.y * rotationSpeed;
  94137. /* //旋转方向和偏移量尽量和在漫游点处旋转方式的一样
  94138. this.yawDelta += e.drag.pointerDelta.x / 500 * viewport.resolution.x
  94139. this.pitchDelta -= e.drag.pointerDelta.y / 500 * viewport.resolution.y */
  94140. //先更新一下相机:
  94141. this.update();
  94142. view.applyToCamera(camera);
  94143. //然后得到新的相机角度下,原先点在屏幕中的位置所对应的3d点现在的坐标。只需要平移一下新旧坐标差值即可。//感觉貌似也可以用project和unproject后的差值的方式,还不用判断z背面
  94144. let newPointerDir = viewer.inputHandler.getMouseDirection(this.rotateStartInfo.rotCenter2d).direction.clone().multiplyScalar(distance);
  94145. let pivot = new Vector3().addVectors(camera.position, newPointerDir); //新的3d点
  94146. let moveVec = new Vector3().subVectors(pivot, this.rotateStartInfo.rotCenter);
  94147. this.translationWorldDelta.copy(moveVec.negate());
  94148. //立即更新下,防止因update和此drag频率不同而打滑。
  94149. this.update();
  94150. view.applyToCamera(camera);
  94151. }else {
  94152. let _matrixWorld = camera.matrixWorld;
  94153. camera.matrixWorld = new Matrix4;//unproject 前先把相机置于原点
  94154. var e1 = new Vector3(this.pointerDragStart.x,this.pointerDragStart.y,-1).unproject(camera)
  94155. , t = new Vector3(e.pointer.x,e.pointer.y,-1).unproject(camera)
  94156. , i = Math.sqrt(e1.x * e1.x + e1.z * e1.z)
  94157. , n = Math.sqrt(t.x * t.x + t.z * t.z)
  94158. , o = Math.atan2(e1.y, i)
  94159. , a = Math.atan2(t.y, n);
  94160. this.pitchDelta += o - a; //上下旋转
  94161. e1.y = 0,
  94162. t.y = 0;
  94163. var s = Math.acos(e1.dot(t) / e1.length() / t.length());
  94164. if(!isNaN(s)){
  94165. var yawDelta = s; //左右旋转
  94166. this.pointerDragStart.x > e.pointer.x && (yawDelta *= -1);
  94167. this.yawDelta += yawDelta;
  94168. }
  94169. //console.log('rotate:', this.pitchDelta, e.pointer.toArray(), this.pointerDragStart.toArray())
  94170. this.pointerDragStart.copy(e.pointer);
  94171. camera.matrixWorld = _matrixWorld ;
  94172. }
  94173. }
  94174. if (mode.includes('pan')) {//平移
  94175. if(!this.canMovePos(viewport)){
  94176. return
  94177. }
  94178. if(camera.type == "OrthographicCamera"){
  94179. let moveVec = Utils.getOrthoCameraMoveVec(e.drag.pointerDelta, camera );//最近一次移动向量
  94180. this.translationWorldDelta.add(moveVec.negate());
  94181. }else { //perspectiveCamera:
  94182. if(e.drag.intersectStart){//如果拖拽着点云
  94183. let ifInit = e.drag.z == void 0;
  94184. let pointerStartPos2d = e.drag.intersectStart.location.clone().project(camera);//识别到的点云点的位置
  94185. e.drag.z = pointerStartPos2d.z; //记录z,保持拖拽物体到屏幕距离不变,所以z深度不变(如果拖拽过程中没有缩放,这个z其实不变)
  94186. if(ifInit){//拖拽开始
  94187. e.drag.projectionMatrixInverse = camera.projectionMatrixInverse.clone();
  94188. //防止吸附到最近点上(因为鼠标所在位置并非识别到的点云点的位置,需要得到鼠标所在位置的3d坐标。)
  94189. let pointerStartPos2dReal = new Vector3(this.pointerDragStart.x,this.pointerDragStart.y, e.drag.z);
  94190. e.drag.translateStartPos = pointerStartPos2dReal.clone().unproject(camera);
  94191. //console.log('开始拖拽', e.pointer.clone())
  94192. }
  94193. //拖拽的过程中将projectionMatrixInverse替换成开始拖拽时的,因为near、far一直在变,会导致unproject计算出的3d坐标改变很大而闪烁。
  94194. var _projectionMatrixInverse = camera.projectionMatrixInverse;
  94195. camera.projectionMatrixInverse = e.drag.projectionMatrixInverse;
  94196. let newPos2d = new Vector3(e.pointer.x,e.pointer.y, e.drag.z );
  94197. let newPos3d = newPos2d.clone().unproject(camera);
  94198. let moveVec = newPos3d.clone().sub( e.drag.translateStartPos /* e.drag.intersectStart.location */ );//移动相机,保持鼠标下的位置永远不变,所以用鼠标下的新位置减去鼠标下的原始位置
  94199. camera.projectionMatrixInverse = _projectionMatrixInverse;
  94200. this.translationWorldDelta.copy(moveVec.negate()); //这里没法用add,原因未知,打开console时会跳动
  94201. //console.log('pan 1', this.translationWorldDelta.clone())
  94202. //四指松开剩三指时会偏移一下,暂不知道哪里的问题,或许跟开头防止点云吸附有关?
  94203. }else { //如果鼠标没有找到和点云的交点,就假设移动整个模型(也可以去扩大范围寻找最近点云)
  94204. let lastIntersect = this.target || viewport.lastIntersect && (viewport.lastIntersect.location || viewport.lastIntersect);//该viewport的最近一次鼠标和点云的交点
  94205. if(!lastIntersect || !(lastIntersect instanceof Vector3))lastIntersect = viewer.bound.center;
  94206. let speed = camera.position.distanceTo(lastIntersect);
  94207. let fov = cameraLight.getHFOVForCamera(camera, true);
  94208. let ratio = speed * Math.tan(fov/2);
  94209. this.translationDelta.x -= e.drag.pointerDelta.x * ratio;
  94210. this.translationDelta.z -= e.drag.pointerDelta.y * ratio;
  94211. //console.log('pan2', e.drag.pointerDelta)
  94212. }
  94213. }
  94214. this.useAttenuation = false;
  94215. }
  94216. if(mode.includes('scale')){//触屏缩放
  94217. this.dollyEnd.subVectors(e.touches[0].pointer, e.touches[1].pointer);
  94218. //if(!this.dollyStart)return
  94219. var scale = this.dollyEnd.length() / this.dollyStart.length();
  94220. let pointer = new Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5);//两个指头的中心点
  94221. dolly({
  94222. pointer,
  94223. scale, camera, drag:e.drag
  94224. });
  94225. this.dollyStart.copy(this.dollyEnd);
  94226. }
  94227. //最好按ctrl可以变为dollhouse的那种旋转
  94228. };
  94229. let drop = e => {
  94230. if(!this.enabled)return
  94231. this.dispatchEvent({type: 'end'});
  94232. };
  94233. let dolly = (e={})=>{
  94234. if(Potree.settings.displayMode == 'showPanos' && this.currentViewport == viewer.mainViewport/* this.currentViewport.unableChangePos */){//全景时
  94235. this.dispatchEvent({type:'dollyStopCauseUnable',delta:e.delta, scale:e.scale});
  94236. return
  94237. }
  94238. let camera = e.camera;
  94239. if(camera.type == "OrthographicCamera"){
  94240. let ratio;
  94241. if(e.delta != void 0){//滚轮缩放
  94242. if(e.delta == 0){//mac
  94243. return
  94244. }else if (e.delta < 0) {
  94245. ratio = 0.9;
  94246. } else if (e.delta > 0) {
  94247. ratio = 1.12; //增加的需要比减少的多一些,否则缩放相同次数下,r0 * ([1+s)(1-s)]^n = r0 * (1-s^2)^n < r0
  94248. }
  94249. }else {
  94250. ratio = e.scale; //触屏缩放
  94251. }
  94252. let zoom = camera.zoom * ratio;
  94253. let limit = camera.zoomLimit;
  94254. if(limit) zoom = MathUtils$1.clamp(zoom, limit.min,limit.max );
  94255. let pointerPos = new Vector3(e.pointer.x, e.pointer.y,0.5);
  94256. let oldPos = pointerPos.clone().unproject(camera);
  94257. if(camera.zoom != zoom){
  94258. camera.zoom = zoom;
  94259. camera.updateProjectionMatrix();
  94260. }
  94261. let newPos = pointerPos.clone().unproject(camera);
  94262. //定点缩放, 恢复一下鼠标所在位置的位置改变量
  94263. let moveVec = new Vector3().subVectors(newPos,oldPos);
  94264. this.translationWorldDelta.add(moveVec.negate());
  94265. this.useAttenuation = false;
  94266. }else {
  94267. let speed = this.currentViewport.getMoveSpeed() * 15, direction;
  94268. if(e.delta != void 0){//滚轮缩放
  94269. if(e.delta == 0)return //mac
  94270. /*if(this.target && !e.intersect){//如果没有intersect点云且有target的话,就朝target的方向. 但无限靠近时有问题,且到背面时前进却是后退
  94271. direction = new THREE.Vector3().subVectors(this.target, camera.position).normalize()
  94272. }else{ */
  94273. direction = this.viewer.inputHandler.getMouseDirection().direction; //定点缩放
  94274. if(e.intersect && e.intersect.location){//和intersect的墙越接近,速度越慢,便于focus细节
  94275. let dis = camera.position.distanceTo(e.intersect.location);
  94276. speed = MathUtils$1.clamp(dis * 0.1, 0.3, speed);
  94277. }
  94278. if (e.delta < 0) {
  94279. speed *= -1;
  94280. }
  94281. this.useAttenuation = true;
  94282. }else {//触屏缩放
  94283. direction = this.viewer.inputHandler.getMouseDirection(e.pointer).direction; //定点缩放
  94284. if(e.drag.intersectStart){//和intersect的墙越接近,速度越慢,便于focus细节
  94285. let dis = camera.position.distanceTo(e.drag.intersectStart.location);
  94286. let r = 1-1/e.scale;
  94287. let closeMin = 0.1, standardMin = 0.001, disBound1 = 2, disBound2 = 5;
  94288. if(math.closeTo(e.scale,1,0.03)){//如果偏差小于0.01,就不限制最小值,因为平移容易正负抖动,近距离有最小值的话抖动明显
  94289. closeMin = 0; //所以若缩放不明显(双指滑动慢),就不设置最低值。(这时候穿越障碍物会比较困难。)
  94290. }
  94291. //console.log('closeMin',closeMin)
  94292. let min = math.linearClamp(dis, disBound1, disBound2, closeMin, standardMin); //触屏和滚轮不一样,触发较为连续,所以最小值设低一点。若要保持双指相对点云位置不变,理想最小值是0,但那样就无法穿越点云(最小值太小的话穿越密集点云如树丛很困难;太大会打滑)所以当离点云近时增大最小值
  94293. speed = Math.sign(r) * MathUtils$1.clamp(dis * Math.abs(r), min, speed);
  94294. //console.log(speed, dis, e.scale)
  94295. }else {
  94296. this.useAttenuation = true;
  94297. let accelerate = 80;
  94298. if(math.closeTo(e.scale,1,0.02)){//缩放小的时候很可能是双指平移时,容易抖动,所以降低移动速度
  94299. accelerate *= Math.min(40*Math.abs(e.scale-1), 0.8);
  94300. }
  94301. // console.log('accelerate',accelerate)
  94302. const constantDis = this.currentViewport.getMoveSpeed() * accelerate; //constantDis = 10;//常量系数,当放大一倍时前进的距离。可以调整
  94303. speed = (e.scale-1)*constantDis;
  94304. }
  94305. }
  94306. var vec = direction.multiplyScalar(speed );
  94307. //this.translationWorldDelta.copy(vec)
  94308. this.translationWorldDelta.add(vec);
  94309. //console.log(vec, speed)
  94310. }
  94311. };
  94312. let scroll = (e) => {
  94313. if(!this.enabled || !e.hoverViewport)return
  94314. this.setCurrentViewport(e);
  94315. e.camera = e.hoverViewport.camera;
  94316. dolly(e);
  94317. };
  94318. let dblclick = (e) => {
  94319. if(!this.enabled)return
  94320. if(!Potree.settings.dblToFocusPoint)return;//调试时才可双击
  94321. if(Potree.settings.displayMode == 'showPointCloud'/* !viewer.images360.isAtPano() */) this.zoomToLocation(e.mouse);
  94322. };
  94323. this.viewer.addEventListener('global_drag', drag);
  94324. /* this.viewer.addEventListener('global_touchmove', (e)=>{
  94325. if(!this.enabled)return
  94326. if(e.touches.length>1){//单指的就触发上一句
  94327. //console.log('global_touchmove' )
  94328. drag(e)
  94329. }
  94330. }); */
  94331. this.viewer.addEventListener('global_drop', drop);
  94332. this.viewer.addEventListener('global_mousewheel', scroll);
  94333. this.viewer.addEventListener('global_dblclick', dblclick);
  94334. let prepareScale = (e)=>{//触屏的scale
  94335. this.dollyStart.subVectors(e.touches[0].pointer, e.touches[1].pointer);
  94336. e.drag.camDisToPointStart = null;
  94337. };
  94338. let prepareRotate = (e)=>{
  94339. this.pointerDragStart = e.pointer.clone();
  94340. if(e.viewer.name != 'mainViewer' )return
  94341. let intersect = e.intersect || e.dragViewport.lastIntersect;
  94342. //在数据集外部时绕中心点旋转,在数据集内部时绕intersect点旋转(其他数据集的点也可以) 或者 原地旋转镜头
  94343. let rotAroundPoint = Potree.settings.rotAroundPoint && e.dragViewport.camera.type != 'OrthographicCamera' && (viewer.atDatasets.length == 0 || intersect) && this.canMovePos(viewport) && !viewer.images360.isAtPano() && !this.viewer.inputHandler.pressedKeys[32];
  94344. let rotCenter2d, rotCenter;
  94345. if(rotAroundPoint){
  94346. let pivotType = this.target ? 'target' : viewer.atDatasets.length > 0 ? 'intersect' : viewer.inputHandler.selection.length ? 'selection' : this.target2 ? 'target2' : 'boundCenter';
  94347. rotCenter = pivotType == 'target'? this.target :pivotType == 'intersect' ? intersect.location : pivotType == 'selection' ? viewer.inputHandler.selection[0].position : pivotType == 'target2' ? this.target2 :viewer.bound.center;
  94348. if(rotCenter){
  94349. rotCenter2d = rotCenter.clone().project(e.dragViewport.camera); //点在屏幕中的位置
  94350. }else {
  94351. rotAroundPoint = false;
  94352. }
  94353. }
  94354. this.rotateStartInfo = {
  94355. rotAroundPoint, //定点旋转
  94356. rotCenter,
  94357. rotCenter2d
  94358. };
  94359. //缺点:多数据集绕中心点转很难操作,感觉可以也改为绕lastIntersect
  94360. //console.log('prepareRotate' )
  94361. };
  94362. let preparePan = (e)=>{//触屏的pan点云 还是会偏移
  94363. this.pointerDragStart = e.pointer.clone();
  94364. e.drag.z = void 0; //清空
  94365. drag(e); //触屏点击时更新的pointer直接用一次drag
  94366. //console.log('preparePan ' )
  94367. };
  94368. this.viewer.addEventListener('global_mousedown'/* 'startDragging' */, (e)=>{
  94369. if(!this.enabled)return
  94370. this.setCurrentViewport(e);
  94371. prepareRotate(e);
  94372. });
  94373. //注意,每次增减指头都会修改pointer,需要更新下状态
  94374. this.viewer.addEventListener('global_touchstart', (e)=>{
  94375. if(!this.enabled)return
  94376. if(e.touches.length==2){//只监听开头两个指头
  94377. prepareScale(e);
  94378. preparePan(e);
  94379. }else if(e.touches.length>=3){
  94380. preparePan(e);
  94381. }
  94382. });
  94383. this.viewer.addEventListener('global_touchend', (e)=>{//e.touches是剩余的指头
  94384. if(!this.enabled)return
  94385. if(e.touches.length==2){//停止平移,开始scale
  94386. prepareScale(e);
  94387. preparePan(e);
  94388. }else if(e.touches.length==1){//停止scale,开始rotate
  94389. prepareRotate(e);
  94390. }else if(e.touches.length>=3){//重新准备下平移(因为抬起的指头可能包含平移使用的数据),否则抬起时漂移
  94391. preparePan(e);
  94392. }
  94393. });
  94394. /* this.viewer.addEventListener('enableChangePos', (e)=>{
  94395. if(!this.enabled)return
  94396. this.enableChangePos = e.canLeavePano
  94397. }) */
  94398. }
  94399. canMovePos(viewport){
  94400. if(viewport == viewer.mainViewport && (Potree.settings.displayMode == 'showPanos'
  94401. || viewer.images360.bumping || viewer.images360.latestToPano))return false
  94402. else return true
  94403. }
  94404. setEnable(enabled){
  94405. this.enabled = enabled;
  94406. }
  94407. setTarget(target, index){//绕该点旋转,类似orbitControl
  94408. if(index == 2)this.target2 = target;
  94409. else this.target = target;
  94410. }
  94411. setFPCMoveSpeed(viewport){
  94412. if(viewport.camera.type == 'OrthographicCamera'){
  94413. let s = 1 / viewport.camera.zoom;
  94414. viewport.setMoveSpeed(s);
  94415. }else {
  94416. //根据和漫游点的最短距离算moveSpeed。缺点:对于导入的无漫游点的数据集没有意义。
  94417. if(viewport == viewer.mainViewport && viewer.images360){
  94418. let position = viewer.mainViewport.view.position;
  94419. let speed;
  94420. let pano = viewer.images360.findNearestPano();
  94421. if(!pano){
  94422. if(!viewer.bound)return
  94423. let boundFloor = viewer.bound.boundingBox.clone();
  94424. boundFloor.max.z = boundFloor.min.z;
  94425. speed = boundFloor.distanceToPoint(viewer.mainViewport.view.position);
  94426. speed = Math.sqrt(speed) / 50;
  94427. }else {
  94428. let dis = pano.position.distanceTo(position);
  94429. let minSpeed = 0.05, minDis = 3, multiplier = 0.005;
  94430. speed = dis <= minDis ? minSpeed : minSpeed + (dis-minDis) * multiplier;
  94431. //console.log('dis', dis, 'speed', speed, pano.id )
  94432. }
  94433. viewer.setMoveSpeed(speed);
  94434. }
  94435. //调试场景t-FhDWmV5xur 两个数据集,大的数据集没有漫游点。
  94436. }
  94437. }
  94438. setCurrentViewport(o={}){//add
  94439. if(!this.enabled && !o.force )return
  94440. if(o.hoverViewport && this.currentViewport != o.hoverViewport ){
  94441. this.currentViewport = o.hoverViewport;
  94442. //this.viewer.setMoveSpeed(this.currentViewport.radius/100);
  94443. this.setFPCMoveSpeed(this.currentViewport);
  94444. }
  94445. if(this.currentViewport.camera.type == 'OrthographicCamera'){
  94446. this.lockElevationOri = true;
  94447. this.lockRotation = true;
  94448. }else {
  94449. this.lockElevationOri = false;
  94450. this.lockRotation = false;
  94451. }
  94452. }
  94453. setScene (scene) {
  94454. this.scene = scene;
  94455. }
  94456. stop(){
  94457. this.yawDelta = 0;
  94458. this.pitchDelta = 0;
  94459. this.translationDelta.set(0, 0, 0);
  94460. }
  94461. zoomToLocation(mouse){
  94462. if(!this.enabled)return
  94463. let camera = this.scene.getActiveCamera();
  94464. /* let I = Utils.getMousePointCloudIntersection(
  94465. mouse,
  94466. camera,
  94467. this.viewer,
  94468. this.scene.pointclouds); */
  94469. var I = this.viewer.inputHandler.intersect;
  94470. if (!I) {
  94471. return;
  94472. }
  94473. let targetRadius = 0;
  94474. {
  94475. let minimumJumpDistance = 0.2;
  94476. let domElement = this.renderer.domElement;
  94477. let ray = Utils.mouseToRay(this.viewer.inputHandler.pointer, camera);
  94478. let {origin, direction} = this.viewer.inputHandler.getMouseDirection();
  94479. let raycaster = new Raycaster();
  94480. raycaster.ray.set(origin, direction);
  94481. let nodes = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, ray);
  94482. let nodes2 = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, raycaster.ray);
  94483. let lastNode = nodes[nodes.length - 1];
  94484. let radius = lastNode.getBoundingSphere(new Sphere()).radius;
  94485. targetRadius = Math.min(this.scene.view.radius, radius);
  94486. targetRadius = Math.max(minimumJumpDistance, targetRadius);
  94487. }
  94488. let d = this.scene.view.direction.multiplyScalar(-1);
  94489. let cameraTargetPosition = new Vector3().addVectors(I.location, d.multiplyScalar(targetRadius));
  94490. // TODO Unused: let controlsTargetPosition = I.location;
  94491. let animationDuration = 600;
  94492. let easing = TWEEN.Easing.Quartic.Out;
  94493. { // animate
  94494. let value = {x: 0};
  94495. let tween = new TWEEN.Tween(value).to({x: 1}, animationDuration);
  94496. tween.easing(easing);
  94497. this.tweens.push(tween);
  94498. let startPos = this.scene.view.position.clone();
  94499. let targetPos = cameraTargetPosition.clone();
  94500. let startRadius = this.scene.view.radius;
  94501. let targetRadius = cameraTargetPosition.distanceTo(I.location);
  94502. tween.onUpdate(() => {
  94503. let t = value.x;
  94504. this.scene.view.position.x = (1 - t) * startPos.x + t * targetPos.x;
  94505. this.scene.view.position.y = (1 - t) * startPos.y + t * targetPos.y;
  94506. this.scene.view.position.z = (1 - t) * startPos.z + t * targetPos.z;
  94507. this.scene.view.radius = (1 - t) * startRadius + t * targetRadius;
  94508. this.viewer.setMoveSpeed(this.scene.view.radius / 2.5);
  94509. });
  94510. tween.onComplete(() => {
  94511. this.tweens = this.tweens.filter(e => e !== tween);
  94512. });
  94513. tween.start();
  94514. }
  94515. }
  94516. update (delta=1) {
  94517. if(!this.enabled)return
  94518. //console.log('update')
  94519. let view = this.currentViewport.view;
  94520. { // cancel move animations on user input
  94521. let changes = [ this.yawDelta,
  94522. this.pitchDelta,
  94523. this.translationDelta.length(),
  94524. this.translationWorldDelta.length() ];
  94525. let changeHappens = changes.some(e => Math.abs(e) > 0.001);
  94526. if (changeHappens && this.tweens.length > 0) {
  94527. this.tweens.forEach(e => e.stop());
  94528. this.tweens = [];
  94529. }
  94530. }
  94531. { // accelerate while input is given
  94532. let ih = this.viewer.inputHandler;
  94533. let moveForward = this.keys.FORWARD.some(e => ih.pressedKeys[e]);
  94534. let moveBackward = this.keys.BACKWARD.some(e => ih.pressedKeys[e]);
  94535. let moveLeft = this.keys.LEFT.some(e => ih.pressedKeys[e]);
  94536. let moveRight = this.keys.RIGHT.some(e => ih.pressedKeys[e]);
  94537. let moveUp = this.keys.UP.some(e => ih.pressedKeys[e]);
  94538. let moveDown = this.keys.DOWN.some(e => ih.pressedKeys[e]);
  94539. let rotateLeft = this.keys.Rotate_LEFT.some(e => ih.pressedKeys[e]);
  94540. let rotateRight = this.keys.Rotate_RIGHT.some(e => ih.pressedKeys[e]);
  94541. let rotateUp = this.keys.Rotate_UP.some(e => ih.pressedKeys[e]);
  94542. let rotateDown = this.keys.Rotate_DOWN.some(e => ih.pressedKeys[e]);
  94543. this.lockElevation = this.lockElevationOri || this.keys.ALT.some(e => ih.pressedKeys[e]);
  94544. if(!this.lockRotation){
  94545. if(rotateLeft){
  94546. this.yawDelta -= 0.01;
  94547. }else if(rotateRight){
  94548. this.yawDelta += 0.01;
  94549. }
  94550. if(rotateUp){
  94551. this.pitchDelta -= 0.01;
  94552. }else if(rotateDown){
  94553. this.pitchDelta += 0.01;
  94554. }
  94555. }
  94556. if(this.canMovePos(this.currentViewport) && !this.lockKey){
  94557. if(this.lockElevation){
  94558. let dir = view.direction;
  94559. dir.z = 0;
  94560. dir.normalize();
  94561. if (moveForward && moveBackward) {
  94562. this.translationWorldDelta.set(0, 0, 0);
  94563. } else if (moveForward) {
  94564. this.translationWorldDelta.copy(dir.multiplyScalar(this.currentViewport.getMoveSpeed()));
  94565. } else if (moveBackward) {
  94566. this.translationWorldDelta.copy(dir.multiplyScalar(-this.currentViewport.getMoveSpeed()));
  94567. }
  94568. }else {
  94569. if (moveForward && moveBackward) {
  94570. this.translationDelta.y = 0;
  94571. } else if (moveForward) {
  94572. this.translationDelta.y = this.currentViewport.getMoveSpeed();
  94573. } else if (moveBackward) {
  94574. this.translationDelta.y = -this.currentViewport.getMoveSpeed();
  94575. }
  94576. }
  94577. if (moveLeft && moveRight) {
  94578. this.translationDelta.x = 0;
  94579. } else if (moveLeft) {
  94580. this.translationDelta.x = -this.currentViewport.getMoveSpeed();
  94581. } else if (moveRight) {
  94582. this.translationDelta.x = this.currentViewport.getMoveSpeed();
  94583. }
  94584. if (moveUp && moveDown) {
  94585. this.translationWorldDelta.z = 0;
  94586. } else if (moveUp) {
  94587. this.translationWorldDelta.z = this.currentViewport.getMoveSpeed();
  94588. } else if (moveDown) {
  94589. this.translationWorldDelta.z = -this.currentViewport.getMoveSpeed();
  94590. }
  94591. if(moveUp || moveDown || moveForward || moveBackward){
  94592. this.useAttenuation = false;
  94593. }
  94594. }
  94595. }
  94596. { // apply rotation
  94597. let yaw = view.yaw;
  94598. let pitch = view.pitch;
  94599. yaw += this.yawDelta; /* * delta; */
  94600. pitch += this.pitchDelta;/* * delta; */
  94601. view.yaw = yaw;
  94602. view.pitch = pitch;
  94603. if(this.yawDelta || this.pitchDelta){
  94604. view.cancelFlying('rotate');
  94605. }
  94606. this.yawDelta = 0;
  94607. this.pitchDelta = 0;
  94608. }
  94609. /* if(this.translationWorldDelta.length()>0) {
  94610. // console.log('translationDelta')
  94611. } */
  94612. { // apply translation
  94613. view.translate(
  94614. this.translationDelta.x, /* * delta, */
  94615. this.translationDelta.y, /* * delta, */
  94616. this.translationDelta.z, /* * delta */
  94617. );
  94618. this.translationDelta.set(0,0,0);
  94619. //if(this.translationWorldDelta.length())console.log(translationWorldDelta)
  94620. view.translateWorld(
  94621. this.translationWorldDelta.x /* * delta */,
  94622. this.translationWorldDelta.y /* * delta */,
  94623. this.translationWorldDelta.z /* * delta */
  94624. );
  94625. //this.translationWorldDelta.set(0,0,0)
  94626. }
  94627. { // set view target according to speed
  94628. //view.radius = 1 * this.currentViewport.getMoveSpeed();
  94629. /* if(viewer.bound) view.radius = view.position.distanceTo(viewer.bound.center)
  94630. let speed = view.radius/100;
  94631. this.viewer.setMoveSpeed(speed); */
  94632. //this.setMoveSpeed()
  94633. }
  94634. if(this.useAttenuation){ //只有滚轮缩放时开启
  94635. let attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  94636. /*this.yawDelta *= attenuation;
  94637. this.pitchDelta *= attenuation;
  94638. this.translationDelta.multiplyScalar(attenuation);*/
  94639. this.translationWorldDelta.multiplyScalar(attenuation);
  94640. }else {
  94641. this.translationWorldDelta.set(0,0,0);
  94642. }
  94643. }
  94644. };
  94645. // Adapted from three.js VRButton
  94646. class VRButton {
  94647. constructor(){
  94648. this.onStartListeners = [];
  94649. this.onEndListeners = [];
  94650. this.element = null;
  94651. }
  94652. onStart(callback){
  94653. this.onStartListeners.push(callback);
  94654. }
  94655. onEnd(callback){
  94656. this.onEndListeners.push(callback);
  94657. }
  94658. static async createButton( renderer, options ) {
  94659. if ( options ) {
  94660. console.error( 'THREE.VRButton: The "options" parameter has been removed. Please set the reference space type via renderer.xr.setReferenceSpaceType() instead.' );
  94661. }
  94662. const button = new VRButton();
  94663. const element = document.createElement( 'button' );
  94664. button.element = element;
  94665. function setEnter(){
  94666. button.element.innerHTML = `
  94667. <div style="font-size: 0.5em;">ENTER</div>
  94668. <div style="font-weight: bold;">VR</div>
  94669. `;
  94670. }
  94671. function setExit(){
  94672. button.element.innerHTML = `
  94673. <div style="font-size: 0.5em;">EXIT</div>
  94674. <div style="font-weight: bold;">VR</div>
  94675. `;
  94676. }
  94677. function showEnterVR( /*device*/ ) {
  94678. let currentSession = null;
  94679. function onSessionStarted( session ) {
  94680. session.addEventListener( 'end', onSessionEnded );
  94681. for(let listener of button.onStartListeners){
  94682. listener();
  94683. }
  94684. renderer.xr.setSession( session );
  94685. setExit();
  94686. currentSession = session;
  94687. }
  94688. function onSessionEnded( /*event*/ ) {
  94689. currentSession.removeEventListener( 'end', onSessionEnded );
  94690. for(let listener of button.onEndListeners){
  94691. listener();
  94692. }
  94693. setEnter();
  94694. currentSession = null;
  94695. }
  94696. //
  94697. button.element.style.display = '';
  94698. button.element.style.cursor = 'pointer';
  94699. setEnter();
  94700. button.element.onmouseenter = function () {
  94701. button.element.style.opacity = '1.0';
  94702. };
  94703. button.element.onmouseleave = function () {
  94704. button.element.style.opacity = '0.7';
  94705. };
  94706. button.element.onclick = function () {
  94707. if ( currentSession === null ) {
  94708. // WebXR's requestReferenceSpace only works if the corresponding feature
  94709. // was requested at session creation time. For simplicity, just ask for
  94710. // the interesting ones as optional features, but be aware that the
  94711. // requestReferenceSpace call will fail if it turns out to be unavailable.
  94712. // ('local' is always available for immersive sessions and doesn't need to
  94713. // be requested separately.)
  94714. const sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor', 'hand-tracking' ] };
  94715. navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted );
  94716. } else {
  94717. currentSession.end();
  94718. }
  94719. };
  94720. }
  94721. function stylizeElement( element ) {
  94722. element.style.position = 'absolute';
  94723. element.style.bottom = '20px';
  94724. element.style.padding = '12px 6px';
  94725. element.style.border = '1px solid #fff';
  94726. element.style.borderRadius = '4px';
  94727. element.style.background = 'rgba(0,0,0,0.1)';
  94728. element.style.color = '#fff';
  94729. element.style.font = 'normal 13px sans-serif';
  94730. element.style.textAlign = 'center';
  94731. element.style.opacity = '0.7';
  94732. element.style.outline = 'none';
  94733. element.style.zIndex = '999';
  94734. }
  94735. if ( 'xr' in navigator ) {
  94736. button.element.id = 'VRButton';
  94737. button.element.style.display = 'none';
  94738. stylizeElement( button.element );
  94739. let supported = await navigator.xr.isSessionSupported( 'immersive-vr' );
  94740. if(supported){
  94741. showEnterVR();
  94742. return button;
  94743. }else {
  94744. return null;
  94745. }
  94746. } else {
  94747. if ( window.isSecureContext === false ) {
  94748. console.log("WEBXR NEEDS HTTPS");
  94749. } else {
  94750. console.log("WEBXR not available");
  94751. }
  94752. return null;
  94753. }
  94754. }
  94755. }
  94756. const manager = new LoadingManager();
  94757. let loaders = {};
  94758. let navCubeArea;
  94759. let shelterHistory = [];
  94760. class Viewer extends ViewerBase{
  94761. constructor(domElement, navCubeArea_, args = {}){
  94762. super(domElement, $.extend(args,{name:'mainViewer', antialias:true, preserveDrawingBuffer:true}));
  94763. //注:viewer因为要分屏,尤其是四屏,preserveDrawingBuffer需要为true, 否则无法局部clear
  94764. window.viewer = this;
  94765. navCubeArea = navCubeArea_;
  94766. this.modules = {
  94767. };
  94768. {
  94769. Potree.timeCollect = {
  94770. depthSampler : {minCount:400, median: 25}, //median预置一个中等值,以防止cpu过低的设备首次卡顿
  94771. };
  94772. setTimeout(()=>{
  94773. for(let i in Potree.timeCollect){
  94774. Potree.timeCollect[i].measures = [];
  94775. Potree.timeCollect[i].sum = 0;
  94776. Potree.timeCollect[i].start = true;
  94777. }
  94778. /* setTimeout(()=>{
  94779. console.log('timeCollect', Potree.timeCollect.depthSampler.median, Potree.timeCollect.depthSampler.ave, Potree.timeCollect.depthSampler.measures.length)
  94780. },10000) */
  94781. },2000);
  94782. }
  94783. this.splitScreen = new SplitScreen();
  94784. this.navigateMode = 'free'; // 'panorama'; 'free'自由模式是只显示点云或者未进入到漫游点,
  94785. this.isEdit = true;
  94786. this.waitQueue = [];
  94787. this.unitConvert = new UoMService();
  94788. this.visible = true;
  94789. this.fpVisiDatasets = [];
  94790. this.atDatasets = [];
  94791. this.objs = new Object3D;
  94792. this.testMaxNodeCount = 0;
  94793. //this.lastPos = new THREE.Vector3(Infinity,Infinity,Infinity)
  94794. //-------------
  94795. var supportExtFragDepth = !!Potree.Features.EXT_DEPTH.isSupported(this.renderer.getContext()) ;//iphoneX居然不支持
  94796. //这意味着边缘增强和测量线遮挡失效
  94797. if(!supportExtFragDepth)console.error('ExtFragDepth unsupported! 边缘增强和测量线遮挡失效');
  94798. this.guiLoaded = false;
  94799. this.guiLoadTasks = [];
  94800. this.onVrListeners = [];
  94801. this.messages = [];
  94802. this.elMessages = $(`
  94803. <div id="message_listing"
  94804. style="position: absolute; z-index: 1000; left: 10px; bottom: 10px">
  94805. </div>`);
  94806. $(domElement).append(this.elMessages);
  94807. this.fakeMeasure = {};
  94808. document.addEventListener('visibilitychange',(e)=>{
  94809. //console.log('visibilitychange', !document.hidden )
  94810. this.dispatchEvent({type:'pageVisible', v:!document.hidden} );
  94811. });
  94812. //add
  94813. navCubeArea = $("<div id='navCube' style='position:fixed;width:100px;height:100px;top:0;right:12px;'></div>");
  94814. $(domElement).append(navCubeArea);
  94815. let homeBtn = $("<div id='home' style='position:fixed;width:10px;height:10px;top:0;right:0;background:#fff;'></div>");
  94816. $(domElement).append(homeBtn);
  94817. homeBtn.on('click',()=>{
  94818. this.navCubeViewer.pushHomeBtn();
  94819. });
  94820. try{
  94821. if(!Potree.settings.isOfficial)
  94822. { // generate missing dom hierarchy
  94823. if ($(domElement).find('#potree_map').length === 0) {
  94824. let potreeMap = $(`
  94825. <div id="potree_map" class="mapBox" style="position: absolute; left: 50px; top: 50px; width: 400px; height: 400px; display: none">
  94826. <div id="potree_map_header" style="position: absolute; width: 100%; height: 25px; top: 0px; background-color: rgba(0,0,0,0.5); z-index: 1000; border-top-left-radius: 3px; border-top-right-radius: 3px;">
  94827. </div>
  94828. <div id="potree_map_content" class="map" style="position: absolute; z-index: 100; top: 25px; width: 100%; height: calc(100% - 25px); border: 2px solid rgba(0,0,0,0.5); box-sizing: border-box;"></div>
  94829. </div>
  94830. `);
  94831. $(domElement).append(potreeMap);
  94832. }
  94833. if ($(domElement).find('#potree_description').length === 0) {
  94834. let potreeDescription = $(`<div id="potree_description" class="potree_info_text"></div>`);
  94835. $(domElement).append(potreeDescription);
  94836. }
  94837. if ($(domElement).find('#potree_annotations').length === 0) {
  94838. let potreeAnnotationContainer = $(`
  94839. <div id="potree_annotation_container"
  94840. style="position: absolute; z-index: 100000; width: 100%; height: 100%; pointer-events: none;"></div>`);
  94841. $(domElement).append(potreeAnnotationContainer);
  94842. }
  94843. if ($(domElement).find('#potree_quick_buttons').length === 0) {
  94844. let potreeMap = $(`
  94845. <div id="potree_quick_buttons" class="quick_buttons_container" style="">
  94846. </div>
  94847. `);
  94848. $(domElement).append(potreeMap);
  94849. }
  94850. /* let domRoot = this.renderer.domElement.parentElement;
  94851. let elAttach = $("<input type='button' value='test'></input>");
  94852. elAttach.css({
  94853. position : "absolute",
  94854. right : '10%',
  94855. bottom: '20px',
  94856. zIndex: "10000",
  94857. fontSize:'1em', color:"black",
  94858. background:'rgba(255,255,255,0.8)',
  94859. })
  94860. let state = false
  94861. elAttach.on("click", () => {
  94862. window.buttonFunction && window.buttonFunction()
  94863. });
  94864. domRoot.appendChild(elAttach[0]); */
  94865. }
  94866. this.pointCloudLoadedCallback = args.onPointCloudLoaded || function () {};
  94867. // if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
  94868. // defaultSettings.navigation = "Orbit";
  94869. // }
  94870. this.server = null;
  94871. this.fov = 60;
  94872. this.isFlipYZ = false;
  94873. this.useDEMCollisions = false;
  94874. this.generateDEM = false;
  94875. this.minNodeSize = 30; //允许加载的node的最小可见像素宽度。越大越省性能
  94876. this.edlStrength = 1.0;
  94877. this.edlRadius = 1.4;
  94878. this.edlOpacity = 1.0;
  94879. this.useEDL = false;
  94880. this.description = "";
  94881. this.classifications = ClassificationScheme.DEFAULT;
  94882. this.moveSpeed = 1;
  94883. this.lengthUnit = LengthUnits.METER;
  94884. this.lengthUnitDisplay = LengthUnits.METER;
  94885. this.showBoundingBox = false;
  94886. this.showAnnotations = true;
  94887. this.freeze = false;
  94888. this.elevationGradientRepeat = ElevationGradientRepeat.CLAMP;
  94889. this.filterReturnNumberRange = [0, 7];
  94890. this.filterNumberOfReturnsRange = [0, 7];
  94891. this.filterGPSTimeRange = [-Infinity, Infinity];
  94892. this.filterPointSourceIDRange = [0, 65535];
  94893. this.potreeRenderer = null;
  94894. this.edlRenderer = null;
  94895. this.pRenderer = null;
  94896. this.scene = null;
  94897. this.sceneVR = null;
  94898. this.overlay = null;
  94899. this.overlayCamera = null;
  94900. this.inputHandler = null;
  94901. this.controls = null;
  94902. this.clippingTool = null;
  94903. this.transformationTool = null;
  94904. this.navigationCube = null;
  94905. this.compass = null;
  94906. this.skybox = null;
  94907. this.clock = new Clock();
  94908. this.background = null;
  94909. this.buffers = new Map;
  94910. if(args.noDragAndDrop){
  94911. }else {
  94912. this.initDragAndDrop();
  94913. }
  94914. if(typeof Stats !== "undefined"){
  94915. this.stats = new Stats();
  94916. this.stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
  94917. document.body.appendChild( this.stats.dom );
  94918. }
  94919. {
  94920. this.overlay = new Scene();
  94921. this.overlayCamera = new OrthographicCamera(
  94922. 0, 1,
  94923. 1, 0,
  94924. -1000, 1000
  94925. );
  94926. }
  94927. this.pRenderer = new Renderer$1(this.renderer);
  94928. {
  94929. let near = 2.5;
  94930. let far = 10.0;
  94931. let fov = 90;
  94932. this.shadowTestCam = new PerspectiveCamera(90, 1, near, far);
  94933. this.shadowTestCam.position.set(3.50, -2.80, 8.561);
  94934. this.shadowTestCam.lookAt(new Vector3(0, 0, 4.87));
  94935. }
  94936. let scene = new ExtendScene(this.renderer);
  94937. { // create VR scene
  94938. this.sceneVR = new Scene();
  94939. // let texture = new THREE.TextureLoader().load(`${Potree.resourcePath}/images/vr_controller_help.jpg`);
  94940. // let plane = new THREE.PlaneBufferGeometry(1, 1, 1, 1);
  94941. // let infoMaterial = new THREE.MeshBasicMaterial({map: texture});
  94942. // let infoNode = new THREE.Mesh(plane, infoMaterial);
  94943. // infoNode.position.set(-0.5, 1, 0);
  94944. // infoNode.scale.set(0.4, 0.3, 1);
  94945. // infoNode.lookAt(0, 1, 0)
  94946. // this.sceneVR.add(infoNode);
  94947. // window.infoNode = infoNode;
  94948. }
  94949. this.setScene(scene);
  94950. //add: for 截图时抗锯齿
  94951. {
  94952. this.composer = new EffectComposer( this.renderer );
  94953. this.ssaaRenderPass = new SSAARenderPass(0x000000, 0);
  94954. this.composer.addPass( this.ssaaRenderPass );
  94955. //this.ssaaRenderPass.useCopy = true
  94956. //this.ssaaRenderPass.renderToScreen = true;
  94957. //this.ssaaRenderPass.needsSwap = false
  94958. //见 https://threejs.org/examples/?q=AA#webgl_postprocessing_fxaa 效果和SSAA差不多,都对透明不太友好。
  94959. /* let outlinePass = this.outlinePass = new OutlinePass( );
  94960. this.ssaaRenderPass.addPass(outlinePass)
  94961. */
  94962. //for 融合页面
  94963. let outlinePass = this.outlinePass = new OutlinePass( );
  94964. outlinePass.renderToScreen = true; //这样更流畅,不用ssaa了,缺点是outline有锯齿
  94965. outlinePass.enabled = false;
  94966. this.composer.addPass( outlinePass );
  94967. outlinePass.edgeStrength = 4;
  94968. outlinePass.edgeGlow = 0;
  94969. outlinePass.visibleEdgeColor = new Color("#09a1b3");
  94970. //--------------------------
  94971. /* this.composer2 = new EffectComposer( this.renderer );
  94972. //const renderPass = new RenderPass();
  94973. //renderPass.clearColor = new THREE.Color( 0, 0, 0 );
  94974. //renderPass.clearAlpha = 0;
  94975. //this.composer2.addPass( renderPass );
  94976. this.fxaaPass = new ShaderPass( FXAAShader );
  94977. this.fxaaPass.readTarget = true //add
  94978. this.fxaaPass.setSize = function(width, height){
  94979. this.material.uniforms[ 'resolution' ].value.x = 1 / ( width );
  94980. this.material.uniforms[ 'resolution' ].value.y = 1 / ( height );
  94981. }
  94982. this.fxaaPass.renderToScreen = true;
  94983. this.composer2.addPass( this.fxaaPass );
  94984. this.composer2.readTarget = true
  94985. */
  94986. }
  94987. {
  94988. this.mainViewport = new Viewport( this.scene.view, this.scene.cameraP, {
  94989. left:0, bottom:0, width:1, height: 1, name:'MainView'
  94990. });
  94991. this.viewports = [this.mainViewport];
  94992. Potree.settings.showCompass && (this.compass = new Compass(Potree.settings.compassDom, this.mainViewport));
  94993. this.magnifier = new Magnifier(this);
  94994. this.reticule = new Reticule(this);
  94995. this.scene.scene.add(this.magnifier);
  94996. this.scene.scene.add(this.reticule);
  94997. //add:
  94998. if(navCubeArea){
  94999. this.navCubeViewer = new NavCubeViewer(navCubeArea[0], this.mainViewport);
  95000. }
  95001. this.inputHandler = new InputHandler(this, this.scene.scene);
  95002. //this.inputHandler.setScene(this.scene);
  95003. //this.inputHandler.addInputListener(this);//add
  95004. this.clippingTool = new ClippingTool(this);
  95005. this.transformationTool = new TransformationTool(this);
  95006. /* this.navigationCube = new NavigationCube(this);
  95007. this.navigationCube.visible = false;
  95008. */
  95009. this.createControls();
  95010. this.clippingTool.setScene(this.scene);
  95011. let onPointcloudAdded = (e) => {
  95012. if (this.scene.pointclouds.length === 1) {
  95013. let speed = e.pointcloud.boundingBox.getSize(new Vector3()).length();
  95014. speed = speed / 2000;
  95015. this.setMoveSpeed(speed);
  95016. }
  95017. };
  95018. let onVolumeRemoved = (e) => {
  95019. this.inputHandler.deselect(e.volume);
  95020. };
  95021. this.addEventListener('scene_changed', (e) => {
  95022. this.inputHandler.setScene(e.scene);
  95023. this.clippingTool.setScene(this.scene);
  95024. if(!e.scene.hasEventListener("pointcloud_added", onPointcloudAdded)){
  95025. e.scene.addEventListener("pointcloud_added", onPointcloudAdded);
  95026. }
  95027. if(!e.scene.hasEventListener("volume_removed", onPointcloudAdded)){
  95028. e.scene.addEventListener("volume_removed", onVolumeRemoved);
  95029. }
  95030. });
  95031. this.scene.addEventListener("volume_removed", onVolumeRemoved);
  95032. this.scene.addEventListener('pointcloud_added', onPointcloudAdded);
  95033. }
  95034. { // set defaults
  95035. this.setFOV(60);
  95036. this.setEDLEnabled(false);
  95037. this.setEDLRadius(3);
  95038. this.setEDLStrength(0.01);
  95039. this.setEDLOpacity(1.0);
  95040. this.setPointBudget(1*1000*1000);
  95041. this.setShowBoundingBox(false);
  95042. this.setFreeze(false);
  95043. this.setControls(this.fpControls/* orbitControls */);
  95044. this.setBackground( new Color(Potree.config.background),1 /* 'gradient' */ );
  95045. this.scaleFactor = 1;
  95046. this.loadSettingsFromURL();
  95047. }
  95048. // start rendering!
  95049. //if(args.useDefaultRenderLoop === undefined || args.useDefaultRenderLoop === true){
  95050. //requestAnimationFrame(this.loop.bind(this));
  95051. //}
  95052. this.renderer.setAnimationLoop(this.loop.bind(this));
  95053. this.loadGUI = this.loadGUI.bind(this);
  95054. this.annotationTool = new AnnotationTool(this);
  95055. this.measuringTool = new MeasuringTool(this);
  95056. //this.profileTool = new ProfileTool(this);
  95057. this.volumeTool = new VolumeTool(this);
  95058. this.tagTool = new TagTool(this);
  95059. //-----------
  95060. CursorDeal.init(this, this.mapViewer ? [this, this.mapViewer] : [this]);//ADD
  95061. this.images360 = new Images360(this);
  95062. this.scene.scene.add(this.objs);
  95063. loaders = {
  95064. objLoader : new OBJLoader( manager ),
  95065. mtlLoader : new MTLLoader( manager ),
  95066. glbLoader : new GLTFLoader(undefined, this.renderer, Potree.settings.libsUrl ),
  95067. plyLoader : new PLYLoader( manager ),
  95068. };
  95069. }catch(e){
  95070. this.onCrash(e);
  95071. }
  95072. //-----------------------add----------------------------------------------------
  95073. /* {
  95074. let ratio
  95075. this.addEventListener('resize',(e)=>{
  95076. if(ratio != e.deviceRatio){ //因为devicePixelRatio会影响到点云大小,所以改变时计算下点云大小
  95077. viewer.scene.pointclouds.forEach(p => {
  95078. p.changePointSize()
  95079. })
  95080. }
  95081. ratio = e.deviceRatio
  95082. })
  95083. } */
  95084. {
  95085. let pointDensity = '';
  95086. Object.defineProperty(Potree.settings , "pointDensity",{
  95087. get: function() {
  95088. return pointDensity
  95089. },
  95090. set: (density)=>{
  95091. if(density && density != pointDensity){
  95092. let pointBudget;
  95093. var config = Potree.config.pointDensity[density];
  95094. if(this.magnifier.visible){//放大镜打开时不要切换pointBudget,否则点云会闪烁。这时使用最高密度。
  95095. pointBudget = Potree.config.pointDensity['magnifier'].pointBudget;
  95096. }else {
  95097. pointBudget = config.pointBudget;
  95098. }
  95099. viewer.setMinNodeSize(config.minNodeSize || Potree.config.minNodeSize);
  95100. viewer.setPointBudget(pointBudget );
  95101. //Potree.maxPointLevel = config.maxLevel
  95102. pointDensity = density;
  95103. this.setPointLevels();
  95104. }
  95105. }
  95106. });
  95107. let UserPointDensity = '';
  95108. Object.defineProperty(Potree.settings , "UserPointDensity",{
  95109. get: function() {
  95110. return UserPointDensity
  95111. },
  95112. set: (density)=>{
  95113. if(UserPointDensity != density){
  95114. if(Potree.settings.displayMode == 'showPointCloud' && this.viewports.length != 4){//漫游模式和四屏时都有自己的pointDensity
  95115. Potree.settings.pointDensity = density;
  95116. }
  95117. UserPointDensity = density;
  95118. }
  95119. }
  95120. });
  95121. }
  95122. {
  95123. let cameraFar = Potree.settings.cameraFar;
  95124. Object.defineProperty(Potree.settings , "cameraFar",{
  95125. get: function() {
  95126. return cameraFar
  95127. },
  95128. set: (far)=>{
  95129. if(far != cameraFar){
  95130. if(Potree.settings.displayMode != 'showPanos'){
  95131. this.mainViewport.camera.far = far;
  95132. this.mainViewport.camera.updateProjectionMatrix();
  95133. }
  95134. cameraFar = far;
  95135. }
  95136. }
  95137. });
  95138. }
  95139. this.reticule.addEventListener('update',(e)=>{
  95140. this.needRender = true;
  95141. //if(this.mapViewer && this.mapViewer.attachedToViewer)this.mapViewer.needRender = true //分屏时mapViewer也有reticule
  95142. });
  95143. this.addEventListener('pointcloud_changed',(e)=>{
  95144. this.needRender = true;
  95145. });
  95146. this.addEventListener('allLoaded', ()=>{
  95147. setTimeout(this.testPointcloudsMaxLevel.bind(this), 1000); //延迟一丢丢,等画面出现
  95148. this.scene.pointclouds.forEach(pointcloud=>{
  95149. pointcloud.addEventListener('isVisible',(e)=>{//是否显示该点的mesh(不显示也能走)
  95150. //console.log('pointcloud isVisible', this.id, e.visible)
  95151. if(e.reason != 'displayMode' ){
  95152. this.updateModelBound('visibleChanged');
  95153. }
  95154. this.dispatchEvent('pointcloud_changed');
  95155. });
  95156. pointcloud.material.addEventListener('material_property_changed',()=>{
  95157. this.dispatchEvent('pointcloud_changed');
  95158. });
  95159. });
  95160. });
  95161. {
  95162. let updated, zoomLevel;
  95163. let update = (e)=>{
  95164. if(e.type == 'updateModelBound' || e.viewport == this.mainViewport && (e.changeInfo.positionChanged || zoomLevel != this.images360.zoomLevel)){
  95165. zoomLevel = this.images360.zoomLevel; //对updateMarkerVisibles有影响
  95166. //e.changeInfo.positionChanged && shelterHistory.clear() //清空
  95167. (e.type == 'updateModelBound' || e.changeInfo.positionChanged) && this.updateDatasetAt(); //更新所在数据集
  95168. if(Potree.settings.ifShowMarker && Potree.settings.editType != 'merge'){
  95169. Common$1. intervalTool.isWaiting('updateMarkerVisibles', ()=>{
  95170. if(!this.mainViewport.view.isFlying() ){
  95171. this.updateMarkerVisibles();
  95172. }
  95173. },500);
  95174. }
  95175. }
  95176. };
  95177. this.addEventListener('camera_changed', update);
  95178. this.addEventListener('updateModelBound', update);
  95179. this.addEventListener('showMarkerChanged',()=>{
  95180. this.updatePanosVisibles(this.modules.SiteModel.currentFloor);
  95181. this.updateMarkerVisibles();
  95182. });
  95183. /* if(!Potree.Features.EXT_DEPTH.isSupported()){
  95184. this.images360.addEventListener('endChangeMode',(e)=>{
  95185. if(e.mode == 'showPanos'){
  95186. this.updateMarkerVisibles()
  95187. }
  95188. }) */
  95189. this.images360.addEventListener('getNeighbourAuto',(e)=>{
  95190. if(/* Potree.settings.displayMode == 'showPanos' && */e.panos.includes(this.images360.currentPano)){
  95191. Common$1.intervalTool.isWaiting('updateMarkerVisibles', ()=>{
  95192. this.updateMarkerVisibles();
  95193. },500);
  95194. }
  95195. });
  95196. /* } */
  95197. }
  95198. }
  95199. ifPointBlockedByIntersect(pos3d , panoId, soon ){//点是否被遮挡
  95200. let ifShelter;
  95201. let now = Date.now();
  95202. let extraPanoId = panoId != void 0;
  95203. if(!this.shelterCount)return
  95204. let history = shelterHistory.find(e=>e.pos3d.equals(pos3d));
  95205. let cameraPos = this.mainViewport.view.position.clone();
  95206. if(panoId == void 0){
  95207. if(this.images360.isAtPano(0.05)){
  95208. panoId = this.images360.currentPano.id;
  95209. }
  95210. }
  95211. if(history){
  95212. if(panoId != void 0){
  95213. ifShelter = history.panos[panoId];
  95214. }else {
  95215. if(history.notAtPano.cameraPos && history.notAtPano.cameraPos.equals(cameraPos)){
  95216. ifShelter = history.notAtPano.ifShelter;
  95217. }
  95218. }
  95219. let index = shelterHistory.indexOf(history); //先取出,稍后放回
  95220. shelterHistory.splice(index, 1);
  95221. }else {//新增
  95222. history = {pos3d, panos:{}, notAtPano:{}};
  95223. const minCount = 100;
  95224. if(shelterHistory.length > minCount){//去除最早的
  95225. let old;
  95226. while(old = shelterHistory[0], now - old.lastTime > 1000){//因为不知热点个数,所以需要加上时间限制,超过时间才能删。
  95227. if(old == history || shelterHistory.length == minCount)break;
  95228. shelterHistory.splice(0,1);
  95229. //console.log('delete')
  95230. }
  95231. }
  95232. }
  95233. if(ifShelter == void 0){
  95234. delete history.waitCompute;
  95235. if(this.mainViewport.view.isFlying()){
  95236. return useLastResult()
  95237. }
  95238. if(panoId != void 0){
  95239. let pano = this.images360.getPano(panoId);
  95240. if((soon || this.shelterCount.byTex<this.shelterCount.maxByTex) && pano.depthTex){
  95241. ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({pos3d, margin:Potree.config.shelterMargin, useDepthTex:true, pano } );
  95242. history.panos[panoId] = ifShelter;
  95243. this.shelterCount.byTex ++ ;
  95244. //console.log('computeByTex direct', panoId, pos3d, ifShelter)
  95245. }else {
  95246. //console.log('延迟tex',panoId, pos3d )
  95247. history.waitCompute = {panoId, forceGet:extraPanoId };
  95248. return useLastResult()
  95249. }
  95250. }else {
  95251. if(/* history.ifShelter == void 0 || */ this.shelterCount.byCloud<this.shelterCount.maxByCloud){//弊端:第一个总是直接计算,后面的都是延后。但无法改进,因是一个个传进来的,无法预测。
  95252. ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({pos3d, margin:Potree.config.shelterMargin, pickWindowSize:3} );
  95253. history.notAtPano = {cameraPos , ifShelter };
  95254. this.shelterCount.byCloud ++ ;
  95255. //console.log('computeByCloud direct', pos3d.toArray())
  95256. }else {
  95257. //console.log('延迟cloud' )
  95258. history.waitCompute = {cameraPos};
  95259. return useLastResult()
  95260. }
  95261. }
  95262. }
  95263. history.ifShelter = ifShelter;
  95264. history.lastTime = now;
  95265. shelterHistory.push(history); //最新使用的保持在最后一个,使队列按照从旧到新排列
  95266. function useLastResult(){//暂时先用上一次的值
  95267. shelterHistory.push(history);
  95268. history.lastTime = now;
  95269. return history.ifShelter
  95270. }
  95271. return ifShelter
  95272. }
  95273. computeShelter(){
  95274. //先算用深度图的,然后再点云;
  95275. let depthTiming = Potree.timeCollect.depthSampler.median;
  95276. let byTex=0, byCloud=0;
  95277. let len = shelterHistory.length;
  95278. let waitCloud = [];
  95279. let maxTexCount = Common$1.getBestCount('shelterMaxDepthSample', 1, 50, 1, 13 /* ,true */ );
  95280. for(let i=len-1; i>=0; i--){
  95281. let history = shelterHistory[i];
  95282. if(history.waitCompute){
  95283. if(history.waitCompute.panoId != void 0){
  95284. if(!history.waitCompute.forceGet && (history.waitCompute.panoId != this.images360.currentPano.id || !this.images360.isAtPano(0.1))){
  95285. delete history.waitCompute; //取消计算
  95286. }else {
  95287. if(this.images360.currentPano.depthTex){
  95288. if(byTex >= maxTexCount)break
  95289. byTex ++;
  95290. let ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({pos3d:history.pos3d, margin:Potree.config.shelterMargin, useDepthTex:true } );
  95291. history.panos[this.images360.currentPano.id] = ifShelter;
  95292. history.ifShelter = ifShelter;
  95293. delete history.waitCompute;
  95294. //console.log('补1', history.pos3d.toArray())
  95295. }else {
  95296. if(this.images360.currentPano.pointcloud.hasDepthTex){
  95297. //先等待加载完深度图
  95298. }else {
  95299. waitCloud.push(history);
  95300. }
  95301. }
  95302. }
  95303. }else {
  95304. waitCloud.push(history);
  95305. }
  95306. }
  95307. }
  95308. let maxCloudCount;
  95309. if(byTex < maxTexCount && waitCloud.length){
  95310. maxCloudCount = this.lastFrameChanged ? Common$1.getBestCount('shelterMaxCloud', 0, 2, 4, 8 /* ,true */ ) : 5;
  95311. let waitCloud2 = [];
  95312. if(maxCloudCount){
  95313. for(let i=0; i<waitCloud.length; i++){
  95314. let history = waitCloud[i];
  95315. if(history.waitCompute.cameraPos){
  95316. if(!viewer.mainViewport.view.position.equals(history.waitCompute.cameraPos)){
  95317. delete history.waitCompute;
  95318. //console.log('delete history.waitCompute', history)
  95319. continue; //取消计算
  95320. }else {
  95321. waitCloud2.push(history);
  95322. }
  95323. }else {
  95324. waitCloud2.push(history);
  95325. }
  95326. }
  95327. let list = waitCloud2.map(e=>e.pos3d);
  95328. let result = Common$1.batchHandling.getSlice('shelterByCloud', list, {maxUseCount:maxCloudCount,useEquals:true, stopWhenAllUsed:true} ); //iphonex稳定后大概在7-10。
  95329. //list.length>0 && console.log('list',list, maxCloudCount)
  95330. result.list.forEach(e=>{
  95331. let history = waitCloud2.find(a=>a.pos3d.equals(e));
  95332. let ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({pos3d:history.pos3d, margin: Potree.config.shelterMargin , pickWindowSize:3} );
  95333. if(history.waitCompute.cameraPos){
  95334. history.notAtPano = {cameraPos: history.waitCompute.cameraPos , ifShelter };
  95335. }else {
  95336. history.panos[this.images360.currentPano.id] = ifShelter;
  95337. }
  95338. history.ifShelter = ifShelter;
  95339. byCloud++;
  95340. //console.log('补2', history.pos3d.toArray())
  95341. delete history.waitCompute;
  95342. });
  95343. }
  95344. }
  95345. if(byTex || byCloud){
  95346. //console.log('shelterComputed',byTex,byCloud, maxTexCount, maxCloudCount)
  95347. Common$1.intervalTool.isWaiting('shelterComputed', ()=>{
  95348. //console.log('shelterComputed update')
  95349. this.dispatchEvent('shelterComputed');
  95350. },340);
  95351. }
  95352. }
  95353. updateDatasetAt(force){//更新所在数据集
  95354. let fun = ()=>{
  95355. let currPos = viewer.mainViewport.view.position;
  95356. var at = this.scene.pointclouds.filter(e=>
  95357. (e.visible || e.unvisibleReasons && e.unvisibleReasons.length == 1 && e.unvisibleReasons[0].reason == 'displayMode')
  95358. && e.ifContainsPoint(currPos)
  95359. );
  95360. if(Common$1.getDifferenceSet(at, this.atDatasets).length){
  95361. //console.log('atDatasets', at)
  95362. this.atDatasets = at;
  95363. this.dispatchEvent({type:'pointcloudAtChange',pointclouds:at});
  95364. }
  95365. force = false;
  95366. };
  95367. if(force)fun();
  95368. else Common$1.intervalTool.isWaiting('atWhichDataset', fun , 300);
  95369. }
  95370. updatePanosVisibles(currentFloor){//显示当前楼层的所有panos
  95371. if(!Potree.settings.ifShowMarker)return
  95372. viewer.images360.panos.forEach(pano=>{
  95373. let visible = currentFloor && currentFloor.panos.includes(pano);
  95374. Potree.Utils.updateVisible(pano, 'buildingChange', visible, 2);
  95375. });
  95376. } //注:非official的没有获取sitemodel的信息所以不执行楼层判断,marker显示不对是正常的
  95377. updateMarkerVisibles(){//限制显示的marker个数,因镜头内marker多的时候可能会卡
  95378. if(!Potree.settings.ifShowMarker)return
  95379. if(this.mainViewport.camera.type == 'OrthographicCamera'){
  95380. viewer.images360.panos.forEach(pano=>{
  95381. Potree.Utils.updateVisible(pano.marker, 'limitMarkerShow', true );
  95382. });
  95383. return
  95384. }
  95385. const minRadius = 8 * this.images360.zoomLevel, //当视线垂直于marker时的最小可见距离,此范围内可见的pano绝对可见
  95386. maxRadius = 50 * this.images360.zoomLevel, //当视线垂直于marker时的最大可见距离,此范围外绝对不可见
  95387. hopeCount = browser.isMobile() ? 8 : 15; //期望达到的真实可见的marker数
  95388. let sheltered = (pano)=>{
  95389. if(/* Potree.settings.displayMode == 'showPanos' && !Potree.Features.EXT_DEPTH.isSupported() && */this.images360.isAtPano() && !this.mainViewport.view.isFlying()){
  95390. return !this.images360.currentPano.neighbours.includes(pano) && this.images360.currentPano != pano //起初因不支持EXT_DEPTH时无法用depthTex遮住marker, 后为了减少绘制,都判断
  95391. }
  95392. };
  95393. let panoMap = new Map; //先记录想要设置为可见的
  95394. let set = ()=>{//最后确定设置
  95395. let count = 0;
  95396. viewer.images360.panos.forEach(pano=>{
  95397. let v = panoMap.get(pano).visible;
  95398. v && count++;
  95399. Potree.Utils.updateVisible(pano.marker, 'limitMarkerShow', v );
  95400. });
  95401. //console.log('updateMarkerVisibles marker显示个数', count)
  95402. };
  95403. let isWithinDis = (pano,maxDis)=>{//是否marker到相机的距离 没有超出可视距离。可视距离考虑上倾斜角,倾斜越大可视距离越短
  95404. let camPos = viewer.mainViewport.camera.position;
  95405. let o = panoMap.get(pano);
  95406. o.dis = o.dis || camPos.distanceTo(pano.marker.position);
  95407. o.sin = o.sin || Math.sqrt(Math.abs(camPos.z - pano.marker.position.z) / o.dis); //和地面夹角的sin。 按公式是不加Math.sqrt的,但是这样大马路上在贴近地面时算出的个数非常少,所以增大点……
  95408. return o.dis < maxDis * o.sin
  95409. };
  95410. viewer.images360.panos.forEach(pano=>{//minRadius内的记录为可见
  95411. let o = {};
  95412. panoMap.set(pano, o);
  95413. if(pano.visible && !sheltered(pano) && isWithinDis(pano, minRadius)){
  95414. o.visible = true;
  95415. }
  95416. });
  95417. //不超过hopeCount的话,可以直接确定设置
  95418. if(viewer.images360.panos.filter(pano=> panoMap.get(pano).visible ).length >= hopeCount)return set()
  95419. //距离超过maxRadius就绝对不可见
  95420. let insideOutCirle = viewer.images360.panos.filter(pano=> pano.visible && !sheltered(pano) && isWithinDis(pano, maxRadius));
  95421. if(insideOutCirle.length <= hopeCount){
  95422. insideOutCirle.forEach(pano=>panoMap.get(pano).visible = true );
  95423. return set()
  95424. }
  95425. //数量超过hopeCount时,根据距离排序
  95426. insideOutCirle.sort((a,b)=>{return panoMap.get(a).dis - panoMap.get(b).dis });
  95427. let slice = insideOutCirle.slice(0,hopeCount);
  95428. slice.forEach(pano=>panoMap.get(pano).visible = true );
  95429. set();
  95430. }
  95431. /*
  95432. findPointcloudsAtFloor(entity){//找当前楼层需要显示哪些数据集。
  95433. //数据集的belongToEntity 在这个entity内(否则会出现点击数据集飞过去平面图却不显示)。or 如果数据集有漫游点的话,需要包含>20%的漫游点。 (防止重叠体积很大但其实一个漫游点都不包含)
  95434. //重叠体积>50% 或 包含>50%的漫游点
  95435. const ratio1 = 0.2, ratio2 = 0.5, ratio3 = 0.95
  95436. var lowScores = []
  95437. var pointclouds = viewer.scene.pointclouds.filter(e=>{
  95438. let score = 0
  95439. if(e.belongToEntity && (e.belongToEntity == entity || e.belongToEntity.buildParent == entity)){//条件1 若该数据集挂载到该楼层 或 该数据集挂载到的房间属于该楼层(这样能显示该层所有房间)
  95440. return true
  95441. }
  95442. if(e.panos.length){//条件2
  95443. var insidePanos = e.panos.filter(a=>entity.ifContainsPoint(a.position));
  95444. let panoCountRatio = insidePanos.length / e.panos.length
  95445. if(panoCountRatio > ratio2)return true
  95446. if(panoCountRatio < ratio1){
  95447. score += panoCountRatio//return false
  95448. }
  95449. }
  95450. //条件3
  95451. let volume = entity.intersectPointcloudVolume(e);
  95452. let volumeRatio = volume / entity.getVolume(true) //注:hole加入计算
  95453. if(volumeRatio > ratio3){ //ratio3要高一些,因为点云bounding可能很大,包含很多无点云的空间。即使整个数据集包含entity都不一定看起来在数据集中。(千万要防止两层楼都显示了)
  95454. return true
  95455. }else{
  95456. score += volumeRatio
  95457. }
  95458. lowScores.push({score, pointcloud:e})
  95459. })
  95460. if(pointclouds.length == 0){//从低分项挑一个出来。
  95461. lowScores.sort((a,b)=>{return a.score - b.score})
  95462. if(lowScores[0].score > 0.4){
  95463. pointclouds = [lowScores[0].pointcloud]
  95464. }
  95465. }
  95466. return pointclouds
  95467. }
  95468. updateCadVisibles(visiClouds, force){
  95469. let oldVisi = this.fpVisiDatasets
  95470. var visiClouds = this.fpVisiDatasets = visiClouds
  95471. if(!force){
  95472. var difference = Common.getDifferenceSet(oldVisi , visiClouds)
  95473. if(difference.length == 0)return
  95474. }
  95475. //console.log('visiClouds',visiClouds.map(e=>e.name))
  95476. viewer.scene.pointclouds.forEach(pointcloud=>{
  95477. var floorplan = viewer.mapViewer.mapLayer.getFloorplan(pointcloud.dataset_id)
  95478. var visi = visiClouds.includes(pointcloud)
  95479. if(floorplan){
  95480. Potree.Utils.updateVisible(floorplan.objectGroup, 'buildingChange', visi)
  95481. }
  95482. //已经添加了全局的 floorplanLoaded后会updateCadVisibles,这段就删了
  95483. })
  95484. viewer.mapViewer.mapLayer.needUpdate = true //可能需要更新加载的level程度
  95485. viewer.mapViewer.needRender = true //若上句不触发加载也要立即重新绘制
  95486. } */
  95487. //促使点云加载出最高级别
  95488. testPointcloudsMaxLevel(){ //所有点云都无需testMaxNodeLevel 就停止
  95489. let camera_changed, count = 0, camera;
  95490. let test = (e={})=>{
  95491. camera_changed = true;
  95492. camera = e.camera || this.scene.getActiveCamera();
  95493. Common$1.intervalTool.isWaiting('testPointcloudsMaxLevel', ()=>{
  95494. if(!camera_changed && count>50 || Potree.settings.displayMode == 'showPanos' )return //只有当camera_changed后才继续循环, 除了最开始几次需要连续加载下
  95495. camera_changed = false;
  95496. count ++;
  95497. //console.log('testPointcloudsMaxLevel中',count)
  95498. let oldCount = this.testMaxNodeCount;
  95499. var success = true;
  95500. viewer.scene.pointclouds.forEach(e=>{
  95501. var wait = e.testMaxNodeLevel(camera);
  95502. if(wait){
  95503. success = false;
  95504. }
  95505. });
  95506. if(!success)return true //没有全部加载完,继续循环
  95507. else {
  95508. this.removeEventListener('camera_changed',test);
  95509. console.log('testPointcloudsMaxLevel结束');
  95510. }
  95511. }, count<10 ? 250 : 500);
  95512. };
  95513. this.addEventListener('camera_changed',test);
  95514. test();
  95515. /* 检验:
  95516. viewer.scene.pointclouds.sort((a,b)=>a.nodeMaxLevelPredict.min - b.nodeMaxLevelPredict.min).forEach(e=>console.log(e.nodeMaxLevel, e.nodeMaxLevelPredict.min))
  95517. */
  95518. }
  95519. setPointLevels(){
  95520. this.scene.pointclouds.forEach(e=>{
  95521. e.setPointLevel();
  95522. });
  95523. }
  95524. onCrash(error){
  95525. $(this.renderArea).empty();
  95526. if ($(this.renderArea).find('#potree_failpage').length === 0) {
  95527. let elFailPage = $(`
  95528. <div id="#potree_failpage" class="potree_failpage">
  95529. <h1>Potree Encountered An Error </h1>
  95530. <p>
  95531. This may happen if your browser or graphics card is not supported.
  95532. <br>
  95533. We recommend to use
  95534. <a href="https://www.google.com/chrome/browser" target="_blank" style="color:initial">Chrome</a>
  95535. or
  95536. <a href="https://www.mozilla.org/" target="_blank">Firefox</a>.
  95537. </p>
  95538. <p>
  95539. Please also visit <a href="http://webglreport.com/" target="_blank">webglreport.com</a> and
  95540. check whether your system supports WebGL.
  95541. </p>
  95542. <p>
  95543. If you are already using one of the recommended browsers and WebGL is enabled,
  95544. consider filing an issue report at <a href="https://github.com/potree/potree/issues" target="_blank">github</a>,<br>
  95545. including your operating system, graphics card, browser and browser version, as well as the
  95546. error message below.<br>
  95547. Please do not report errors on unsupported browsers.
  95548. </p>
  95549. <pre id="potree_error_console" style="width: 100%; height: 100%"></pre>
  95550. </div>`);
  95551. let elErrorMessage = elFailPage.find('#potree_error_console');
  95552. elErrorMessage.html(error.stack);
  95553. $(this.renderArea).append(elFailPage);
  95554. }
  95555. throw error;
  95556. }
  95557. // ------------------------------------------------------------------------------------
  95558. // Viewer API
  95559. // ------------------------------------------------------------------------------------
  95560. setScene (scene) {
  95561. if (scene === this.scene) {
  95562. return;
  95563. }
  95564. let oldScene = this.scene;
  95565. this.scene = scene;
  95566. this.dispatchEvent({
  95567. type: 'scene_changed',
  95568. oldScene: oldScene,
  95569. scene: scene
  95570. });
  95571. { // Annotations
  95572. $('.annotation').detach();
  95573. // for(let annotation of this.scene.annotations){
  95574. // this.renderArea.appendChild(annotation.domElement[0]);
  95575. // }
  95576. this.scene.annotations.traverse(annotation => {
  95577. this.renderArea.appendChild(annotation.domElement[0]);
  95578. });
  95579. if (!this.onAnnotationAdded) {
  95580. this.onAnnotationAdded = e => {
  95581. // console.log("annotation added: " + e.annotation.title);
  95582. e.annotation.traverse(node => {
  95583. $("#potree_annotation_container").append(node.domElement);
  95584. //this.renderArea.appendChild(node.domElement[0]);
  95585. node.scene = this.scene;
  95586. });
  95587. };
  95588. }
  95589. if (oldScene) {
  95590. oldScene.annotations.removeEventListener('annotation_added', this.onAnnotationAdded);
  95591. }
  95592. this.scene.annotations.addEventListener('annotation_added', this.onAnnotationAdded);
  95593. }
  95594. };
  95595. setControls(controls/* , setSpeed */){
  95596. if (controls !== this.controls) {
  95597. if (this.controls) {
  95598. this.controls.setEnable(false);
  95599. //this.inputHandler.removeInputListener(this.controls);
  95600. this.controls.moveSpeed = this.moveSpeed; //记录 (因为orbit的radius很大,转为firstPerson时要缩小)
  95601. }
  95602. this.controls = controls;
  95603. controls.moveSpeed && this.setMoveSpeed(controls.moveSpeed); //add
  95604. this.controls.setEnable(true);
  95605. //this.inputHandler.addInputListener(this.controls);
  95606. }
  95607. }
  95608. getControls () {
  95609. if(this.renderer.xr.isPresenting){
  95610. return this.vrControls;
  95611. }else {
  95612. return this.controls;
  95613. }
  95614. }
  95615. getMinNodeSize () {
  95616. return this.minNodeSize;
  95617. };
  95618. setMinNodeSize (value) {
  95619. if (this.minNodeSize !== value) {
  95620. this.minNodeSize = value;
  95621. this.dispatchEvent({'type': 'minnodesize_changed', 'viewer': this});
  95622. }
  95623. };
  95624. getBackground () {
  95625. return this.background;
  95626. }
  95627. setBackground(bg, src){
  95628. /* if (this.background === bg ) {
  95629. return;
  95630. } */
  95631. if(bg === "skybox"){
  95632. if(!src)src = Potree.resourcePath+'/textures/skybox/xingkong.jpg';
  95633. this.skybox = Utils.loadSkybox(src, this.skybox);
  95634. }
  95635. this.background = bg;
  95636. this.backgroundOpacity = 1;//add
  95637. this.dispatchEvent({'type': 'background_changed', 'viewer': this});
  95638. }
  95639. setDescription (value) {
  95640. this.description = value;
  95641. $('#potree_description').html(value);
  95642. //$('#potree_description').text(value);
  95643. }
  95644. getDescription(){
  95645. return this.description;
  95646. }
  95647. setShowBoundingBox (value) {
  95648. if (this.showBoundingBox !== value) {
  95649. this.showBoundingBox = value;
  95650. this.dispatchEvent({'type': 'show_boundingbox_changed', 'viewer': this});
  95651. }
  95652. };
  95653. getShowBoundingBox () {
  95654. return this.showBoundingBox;
  95655. };
  95656. setMoveSpeed (value) {
  95657. if (this.getMoveSpeed() !== value) {
  95658. this.mainViewport.setMoveSpeed(value);
  95659. this.dispatchEvent({'type': 'move_speed_changed', 'viewer': this, 'speed': value});
  95660. }
  95661. };
  95662. getMoveSpeed () {
  95663. return this.mainViewport.moveSpeed;
  95664. };
  95665. setWeightClassification (w) {
  95666. for (let i = 0; i < this.scene.pointclouds.length; i++) {
  95667. this.scene.pointclouds[i].material.weightClassification = w;
  95668. this.dispatchEvent({'type': 'attribute_weights_changed' + i, 'viewer': this});
  95669. }
  95670. };
  95671. setFreeze (value) {
  95672. value = Boolean(value);
  95673. if (this.freeze !== value) {
  95674. this.freeze = value;
  95675. this.dispatchEvent({'type': 'freeze_changed', 'viewer': this});
  95676. }
  95677. };
  95678. getFreeze () {
  95679. return this.freeze;
  95680. };
  95681. setElevationGradientRepeat(value){
  95682. if(this.elevationGradientRepeat !== value){
  95683. this.elevationGradientRepeat = value;
  95684. this.dispatchEvent({
  95685. type: "elevation_gradient_repeat_changed",
  95686. viewer: this});
  95687. }
  95688. }
  95689. setPointBudget (value) { //pointBudget: 每次刷新显示点数量的最大值。 缓存中的点数量也跟此有关,但大于这个数值。
  95690. if (Potree.pointBudget !== value) {
  95691. Potree.pointBudget = parseInt(value);
  95692. this.dispatchEvent({'type': 'point_budget_changed', 'viewer': this});
  95693. }
  95694. };
  95695. getPointBudget () {
  95696. return Potree.pointBudget;
  95697. };
  95698. setShowAnnotations (value) {
  95699. if (this.showAnnotations !== value) {
  95700. this.showAnnotations = value;
  95701. this.dispatchEvent({'type': 'show_annotations_changed', 'viewer': this});
  95702. }
  95703. }
  95704. getShowAnnotations () {
  95705. return this.showAnnotations;
  95706. }
  95707. setDEMCollisionsEnabled(value){
  95708. if(this.useDEMCollisions !== value){
  95709. this.useDEMCollisions = value;
  95710. this.dispatchEvent({'type': 'use_demcollisions_changed', 'viewer': this});
  95711. };
  95712. };
  95713. getDEMCollisionsEnabled () {
  95714. return this.useDEMCollisions;
  95715. };
  95716. setEDLEnabled (value) {
  95717. value = Boolean(value) && Features.SHADER_EDL.isSupported();
  95718. if (this.useEDL !== value) {
  95719. this.useEDL = value;
  95720. this.dispatchEvent({'type': 'use_edl_changed', 'viewer': this});
  95721. this.dispatchEvent('pointcloud_changed');
  95722. }
  95723. };
  95724. getEDLEnabled () {
  95725. return this.useEDL;
  95726. };
  95727. setEDLRadius (value) {
  95728. if (this.edlRadius !== value) {
  95729. this.edlRadius = value;
  95730. this.dispatchEvent({'type': 'edl_radius_changed', 'viewer': this});
  95731. this.dispatchEvent('pointcloud_changed');
  95732. }
  95733. };
  95734. getEDLRadius () {
  95735. return this.edlRadius;
  95736. };
  95737. setEDLStrength (value) {
  95738. if (this.edlStrength !== value) {
  95739. this.edlStrength = value;
  95740. this.dispatchEvent({'type': 'edl_strength_changed', 'viewer': this});
  95741. this.dispatchEvent('pointcloud_changed');
  95742. }
  95743. };
  95744. getEDLStrength () {
  95745. return this.edlStrength;
  95746. };
  95747. setEDLOpacity (value) {
  95748. if (this.edlOpacity !== value) {
  95749. this.edlOpacity = value;
  95750. this.dispatchEvent({'type': 'edl_opacity_changed', 'viewer': this});
  95751. this.dispatchEvent('pointcloud_changed');
  95752. }
  95753. };
  95754. getEDLOpacity () {
  95755. return this.edlOpacity;
  95756. };
  95757. setFOV (value) {
  95758. if (this.fov !== value) {
  95759. let oldFov = this.fov;
  95760. this.fov = value;
  95761. this.scene.cameraP.fov = this.fov; //add
  95762. this.scene.cameraP.updateProjectionMatrix(); //add
  95763. this.dispatchEvent({'type': 'fov_changed', 'viewer': this, oldFov, fov:this.fov});
  95764. }
  95765. };
  95766. getFOV () {
  95767. return this.fov;
  95768. };
  95769. disableAnnotations () {
  95770. this.scene.annotations.traverse(annotation => {
  95771. annotation.domElement.css('pointer-events', 'none');
  95772. // return annotation.visible;
  95773. });
  95774. };
  95775. enableAnnotations () {
  95776. this.scene.annotations.traverse(annotation => {
  95777. annotation.domElement.css('pointer-events', 'auto');
  95778. // return annotation.visible;
  95779. });
  95780. }
  95781. setClassifications(classifications){
  95782. this.classifications = classifications;
  95783. this.dispatchEvent({'type': 'classifications_changed', 'viewer': this});
  95784. }
  95785. setClassificationVisibility (key, value) {
  95786. if (!this.classifications[key]) {
  95787. this.classifications[key] = {visible: value, name: 'no name'};
  95788. this.dispatchEvent({'type': 'classification_visibility_changed', 'viewer': this});
  95789. } else if (this.classifications[key].visible !== value) {
  95790. this.classifications[key].visible = value;
  95791. this.dispatchEvent({'type': 'classification_visibility_changed', 'viewer': this});
  95792. }
  95793. }
  95794. toggleAllClassificationsVisibility(){
  95795. let numVisible = 0;
  95796. let numItems = 0;
  95797. for(const key of Object.keys(this.classifications)){
  95798. if(this.classifications[key].visible){
  95799. numVisible++;
  95800. }
  95801. numItems++;
  95802. }
  95803. let visible = true;
  95804. if(numVisible === numItems){
  95805. visible = false;
  95806. }
  95807. let somethingChanged = false;
  95808. for(const key of Object.keys(this.classifications)){
  95809. if(this.classifications[key].visible !== visible){
  95810. this.classifications[key].visible = visible;
  95811. somethingChanged = true;
  95812. }
  95813. }
  95814. if(somethingChanged){
  95815. this.dispatchEvent({'type': 'classification_visibility_changed', 'viewer': this});
  95816. }
  95817. }
  95818. setFilterReturnNumberRange(from, to){
  95819. this.filterReturnNumberRange = [from, to];
  95820. this.dispatchEvent({'type': 'filter_return_number_range_changed', 'viewer': this});
  95821. }
  95822. setFilterNumberOfReturnsRange(from, to){
  95823. this.filterNumberOfReturnsRange = [from, to];
  95824. this.dispatchEvent({'type': 'filter_number_of_returns_range_changed', 'viewer': this});
  95825. }
  95826. setFilterGPSTimeRange(from, to){
  95827. this.filterGPSTimeRange = [from, to];
  95828. this.dispatchEvent({'type': 'filter_gps_time_range_changed', 'viewer': this});
  95829. }
  95830. setFilterPointSourceIDRange(from, to){
  95831. this.filterPointSourceIDRange = [from, to];
  95832. this.dispatchEvent({'type': 'filter_point_source_id_range_changed', 'viewer': this});
  95833. }
  95834. setLengthUnit (value) {
  95835. switch (value) {
  95836. case 'm':
  95837. this.lengthUnit = LengthUnits.METER;
  95838. this.lengthUnitDisplay = LengthUnits.METER;
  95839. break;
  95840. case 'ft':
  95841. this.lengthUnit = LengthUnits.FEET;
  95842. this.lengthUnitDisplay = LengthUnits.FEET;
  95843. break;
  95844. case 'in':
  95845. this.lengthUnit = LengthUnits.INCH;
  95846. this.lengthUnitDisplay = LengthUnits.INCH;
  95847. break;
  95848. }
  95849. this.dispatchEvent({ 'type': 'length_unit_changed', 'viewer': this, value: value});
  95850. };
  95851. setLengthUnitAndDisplayUnit(lengthUnitValue, lengthUnitDisplayValue) {
  95852. switch (lengthUnitValue) {
  95853. case 'm':
  95854. this.lengthUnit = LengthUnits.METER;
  95855. break;
  95856. case 'ft':
  95857. this.lengthUnit = LengthUnits.FEET;
  95858. break;
  95859. case 'in':
  95860. this.lengthUnit = LengthUnits.INCH;
  95861. break;
  95862. }
  95863. switch (lengthUnitDisplayValue) {
  95864. case 'm':
  95865. this.lengthUnitDisplay = LengthUnits.METER;
  95866. break;
  95867. case 'ft':
  95868. this.lengthUnitDisplay = LengthUnits.FEET;
  95869. break;
  95870. case 'in':
  95871. this.lengthUnitDisplay = LengthUnits.INCH;
  95872. break;
  95873. }
  95874. this.dispatchEvent({ 'type': 'length_unit_changed', 'viewer': this, value: lengthUnitValue });
  95875. };
  95876. zoomTo(node, factor, animationDuration = 0){
  95877. let view = this.scene.view;
  95878. let camera = this.scene.cameraP.clone();
  95879. camera.rotation.copy(this.scene.cameraP.rotation);
  95880. camera.rotation.order = "ZXY";
  95881. camera.rotation.x = Math.PI / 2 + view.pitch;
  95882. camera.rotation.z = view.yaw;
  95883. camera.updateMatrix();
  95884. camera.updateMatrixWorld();
  95885. camera.zoomTo(node, factor);
  95886. let bs;
  95887. if (node.boundingSphere) {
  95888. bs = node.boundingSphere;
  95889. } else if (node.geometry && node.geometry.boundingSphere) {
  95890. bs = node.geometry.boundingSphere;
  95891. } else {
  95892. bs = node.boundingBox.getBoundingSphere(new Sphere());
  95893. }
  95894. bs = bs.clone().applyMatrix4(node.matrixWorld);
  95895. let startPosition = view.position.clone();
  95896. let endPosition = camera.position.clone();
  95897. let startTarget = view.getPivot();
  95898. let endTarget = bs.center;
  95899. let startRadius = view.radius;
  95900. let endRadius = endPosition.distanceTo(endTarget);
  95901. let easing = TWEEN.Easing.Quartic.Out;
  95902. { // animate camera position
  95903. let pos = startPosition.clone();
  95904. let tween = new TWEEN.Tween(pos).to(endPosition, animationDuration);
  95905. tween.easing(easing);
  95906. tween.onUpdate(() => {
  95907. view.position.copy(pos);
  95908. });
  95909. tween.start();
  95910. }
  95911. { // animate camera target
  95912. let target = startTarget.clone();
  95913. let tween = new TWEEN.Tween(target).to(endTarget, animationDuration);
  95914. tween.easing(easing);
  95915. tween.onUpdate(() => {
  95916. view.lookAt(target);
  95917. });
  95918. tween.onComplete(() => {
  95919. view.lookAt(target);
  95920. this.dispatchEvent({type: 'focusing_finished', target: this});
  95921. });
  95922. this.dispatchEvent({type: 'focusing_started', target: this});
  95923. tween.start();
  95924. }
  95925. };
  95926. moveToGpsTimeVicinity(time){
  95927. const result = Potree.Utils.findClosestGpsTime(time, viewer);
  95928. const box = result.node.pointcloud.deepestNodeAt(result.position).getBoundingBox();
  95929. const diameter = box.min.distanceTo(box.max);
  95930. const camera = this.scene.getActiveCamera();
  95931. const offset = camera.getWorldDirection(new Vector3()).multiplyScalar(diameter);
  95932. const newCamPos = result.position.clone().sub(offset);
  95933. this.scene.view.position.copy(newCamPos);
  95934. this.scene.view.lookAt(result.position);
  95935. }
  95936. showAbout () {
  95937. $(function () {
  95938. $('#about-panel').dialog();
  95939. });
  95940. };
  95941. getGpsTimeExtent(){
  95942. const range = [Infinity, -Infinity];
  95943. for(const pointcloud of this.scene.pointclouds){
  95944. const attributes = pointcloud.pcoGeometry.pointAttributes.attributes;
  95945. const aGpsTime = attributes.find(a => a.name === "gps-time");
  95946. if(aGpsTime){
  95947. range[0] = Math.min(range[0], aGpsTime.range[0]);
  95948. range[1] = Math.max(range[1], aGpsTime.range[1]);
  95949. }
  95950. }
  95951. return range;
  95952. }
  95953. fitToScreen (factor = 1, animationDuration = 0) {
  95954. let box = this.getBoundingBox(this.scene.pointclouds);
  95955. let node = new Object3D();
  95956. node.boundingBox = box;
  95957. this.zoomTo(node, factor, animationDuration);
  95958. this.controls.stop();
  95959. };
  95960. /* toggleNavigationCube() {
  95961. this.navigationCube.visible = !this.navigationCube.visible;
  95962. } */
  95963. /* setView(pos, view) {
  95964. if(!pos) return;
  95965. switch(pos) {
  95966. case "F":
  95967. this.setFrontView(view);
  95968. break;
  95969. case "B":
  95970. this.setBackView(view);
  95971. break;
  95972. case "L":
  95973. this.setLeftView(view);
  95974. break;
  95975. case "R":
  95976. this.setRightView(view);
  95977. break;
  95978. case "U":
  95979. this.setTopView(view);
  95980. break;
  95981. case "D":
  95982. this.setBottomView(view);
  95983. break;
  95984. }
  95985. } */
  95986. setTopView(view, dur){
  95987. view = view || this.scene.view;
  95988. view.setCubeView("top");
  95989. this.fitToScreen(1, dur);
  95990. };
  95991. setBottomView(view, dur){
  95992. view = view || this.scene.view;
  95993. view.yaw = -Math.PI;
  95994. view.pitch = Math.PI / 2;
  95995. this.fitToScreen(1, dur);
  95996. };
  95997. setFrontView(view, dur){
  95998. view = view || this.scene.view;
  95999. view.yaw = 0;
  96000. view.pitch = 0;
  96001. this.fitToScreen(1, dur);
  96002. };
  96003. setBackView(view, dur){
  96004. view = view || this.scene.view;
  96005. view.yaw = Math.PI;
  96006. view.pitch = 0;
  96007. this.fitToScreen(1, dur);
  96008. };
  96009. setLeftView(view, dur){
  96010. view = view || this.scene.view;
  96011. view.yaw = -Math.PI / 2;
  96012. view.pitch = 0;
  96013. this.fitToScreen(1, dur);
  96014. };
  96015. setRightView (view, dur) {
  96016. view = view || this.scene.view;
  96017. view.yaw = Math.PI / 2;
  96018. view.pitch = 0;
  96019. this.fitToScreen();
  96020. };
  96021. flipYZ () {
  96022. this.isFlipYZ = !this.isFlipYZ;
  96023. // TODO flipyz
  96024. console.log('TODO');
  96025. }
  96026. setCameraMode(mode){
  96027. this.scene.cameraMode = mode;
  96028. for(let pointcloud of this.scene.pointclouds) {
  96029. pointcloud.material.useOrthographicCamera = mode == CameraMode.ORTHOGRAPHIC;
  96030. }
  96031. this.updateScreenSize({forceUpdateSize:true});//reset camera.left and projectionMatrix
  96032. }
  96033. getProjection(){
  96034. const pointcloud = this.scene.pointclouds[0];
  96035. if(pointcloud){
  96036. return pointcloud.projection;
  96037. }else {
  96038. return null;
  96039. }
  96040. }
  96041. async loadProject(url,done){
  96042. const response = await fetch(url);
  96043. if(response.ok){
  96044. const text = await response.text();
  96045. const json = JSON5.parse(text);
  96046. // const json = JSON.parse(text);
  96047. if(json.type === "Potree"){
  96048. Potree.loadProject(viewer, json, done);
  96049. }
  96050. }else {
  96051. console.warn("未能加载:"+url );
  96052. }
  96053. }
  96054. saveProject(){
  96055. return Potree.saveProject(this);
  96056. }
  96057. loadSettingsFromURL(){
  96058. if(Utils.getParameterByName("pointSize")){
  96059. this.setPointSize(parseFloat(Utils.getParameterByName("pointSize")));
  96060. }
  96061. if(Utils.getParameterByName("FOV")){
  96062. this.setFOV(parseFloat(Utils.getParameterByName("FOV")));
  96063. }
  96064. if(Utils.getParameterByName("opacity")){
  96065. this.setOpacity(parseFloat(Utils.getParameterByName("opacity")));
  96066. }
  96067. if(Utils.getParameterByName("edlEnabled")){
  96068. let enabled = Utils.getParameterByName("edlEnabled") === "true";
  96069. this.setEDLEnabled(enabled);
  96070. }
  96071. if (Utils.getParameterByName('edlRadius')) {
  96072. this.setEDLRadius(parseFloat(Utils.getParameterByName('edlRadius')));
  96073. }
  96074. if (Utils.getParameterByName('edlStrength')) {
  96075. this.setEDLStrength(parseFloat(Utils.getParameterByName('edlStrength')));
  96076. }
  96077. if (Utils.getParameterByName('pointBudget')) {
  96078. this.setPointBudget(parseFloat(Utils.getParameterByName('pointBudget')));
  96079. }
  96080. if (Utils.getParameterByName('showBoundingBox')) {
  96081. let enabled = Utils.getParameterByName('showBoundingBox') === 'true';
  96082. if (enabled) {
  96083. this.setShowBoundingBox(true);
  96084. } else {
  96085. this.setShowBoundingBox(false);
  96086. }
  96087. }
  96088. if (Utils.getParameterByName('material')) {
  96089. let material = Utils.getParameterByName('material');
  96090. this.setMaterial(material);
  96091. }
  96092. if (Utils.getParameterByName('pointSizing')) {
  96093. let sizing = Utils.getParameterByName('pointSizing');
  96094. this.setPointSizing(sizing);
  96095. }
  96096. if (Utils.getParameterByName('quality')) {
  96097. let quality = Utils.getParameterByName('quality');
  96098. this.setQuality(quality);
  96099. }
  96100. if (Utils.getParameterByName('position')) {
  96101. let value = Utils.getParameterByName('position');
  96102. value = value.replace('[', '').replace(']', '');
  96103. let tokens = value.split(';');
  96104. let x = parseFloat(tokens[0]);
  96105. let y = parseFloat(tokens[1]);
  96106. let z = parseFloat(tokens[2]);
  96107. this.scene.view.position.set(x, y, z);
  96108. }
  96109. if (Utils.getParameterByName('target')) {
  96110. let value = Utils.getParameterByName('target');
  96111. value = value.replace('[', '').replace(']', '');
  96112. let tokens = value.split(';');
  96113. let x = parseFloat(tokens[0]);
  96114. let y = parseFloat(tokens[1]);
  96115. let z = parseFloat(tokens[2]);
  96116. this.scene.view.lookAt(new Vector3(x, y, z));
  96117. }
  96118. if (Utils.getParameterByName('background')) {
  96119. let value = Utils.getParameterByName('background');
  96120. this.setBackground(value);
  96121. }
  96122. // if(Utils.getParameterByName("elevationRange")){
  96123. // let value = Utils.getParameterByName("elevationRange");
  96124. // value = value.replace("[", "").replace("]", "");
  96125. // let tokens = value.split(";");
  96126. // let x = parseFloat(tokens[0]);
  96127. // let y = parseFloat(tokens[1]);
  96128. //
  96129. // this.setElevationRange(x, y);
  96130. // //this.scene.view.target.set(x, y, z);
  96131. // }
  96132. };
  96133. // ------------------------------------------------------------------------------------
  96134. // Viewer Internals
  96135. // ------------------------------------------------------------------------------------
  96136. createControls () {
  96137. { // create FIRST PERSON CONTROLS
  96138. this.fpControls = new FirstPersonControls(this, this.mainViewport);
  96139. this.fpControls.enabled = false;
  96140. this.fpControls.addEventListener('start', this.disableAnnotations.bind(this));
  96141. this.fpControls.addEventListener('end', this.enableAnnotations.bind(this));
  96142. /* this.addEventListener("loadPointCloudDone", ()=>{
  96143. let boundPlane = new THREE.Box3()
  96144. boundPlane.expandByPoint(this.bound.boundingBox.min.clone())//最低高度为bound的最低
  96145. boundPlane.expandByPoint(this.bound.boundingBox.max.clone().setZ(this.bound.center.z))//最高高度为bound的中心高度
  96146. FirstPersonControls.boundPlane = boundPlane
  96147. FirstPersonControls.standardSpeed = THREE.Math.clamp( Math.sqrt(this.bound.boundSize.length() )/ 100 , 0.02,0.5); //在这个boundPlane中的速度
  96148. }) */
  96149. }
  96150. // { // create GEO CONTROLS
  96151. // this.geoControls = new GeoControls(this.scene.camera, this.renderer.domElement);
  96152. // this.geoControls.enabled = false;
  96153. // this.geoControls.addEventListener("start", this.disableAnnotations.bind(this));
  96154. // this.geoControls.addEventListener("end", this.enableAnnotations.bind(this));
  96155. // this.geoControls.addEventListener("move_speed_changed", (event) => {
  96156. // this.setMoveSpeed(this.geoControls.moveSpeed);
  96157. // });
  96158. // }
  96159. { // create ORBIT CONTROLS
  96160. this.orbitControls = new OrbitControls(this);
  96161. this.orbitControls.enabled = false;
  96162. this.orbitControls.addEventListener('start', this.disableAnnotations.bind(this));
  96163. this.orbitControls.addEventListener('end', this.enableAnnotations.bind(this));
  96164. }
  96165. /* { // create EARTH CONTROLS
  96166. this.earthControls = new EarthControls(this);
  96167. this.earthControls.enabled = false;
  96168. this.earthControls.addEventListener('start', this.disableAnnotations.bind(this));
  96169. this.earthControls.addEventListener('end', this.enableAnnotations.bind(this));
  96170. }
  96171. { // create DEVICE ORIENTATION CONTROLS
  96172. this.deviceControls = new DeviceOrientationControls(this);
  96173. this.deviceControls.enabled = false;
  96174. this.deviceControls.addEventListener('start', this.disableAnnotations.bind(this));
  96175. this.deviceControls.addEventListener('end', this.enableAnnotations.bind(this));
  96176. } */
  96177. /* { // create VR CONTROLS
  96178. this.vrControls = new VRControls(this);
  96179. this.vrControls.enabled = false;
  96180. this.vrControls.addEventListener('start', this.disableAnnotations.bind(this));
  96181. this.vrControls.addEventListener('end', this.enableAnnotations.bind(this));
  96182. } */
  96183. };
  96184. toggleSidebar () {
  96185. let renderArea = $('#potree_render_area');
  96186. let isVisible = renderArea.css('left') !== '0px';
  96187. if (isVisible) {
  96188. renderArea.css('left', '0px');
  96189. } else {
  96190. renderArea.css('left', '300px');
  96191. }
  96192. };
  96193. toggleMap () {
  96194. // let map = $('#potree_map');
  96195. // map.toggle(100);
  96196. if (this.mapView) {
  96197. this.mapView.toggle();
  96198. }
  96199. };
  96200. onGUILoaded(callback){
  96201. if(this.guiLoaded){
  96202. callback();
  96203. }else {
  96204. this.guiLoadTasks.push(callback);
  96205. }
  96206. }
  96207. promiseGuiLoaded(){
  96208. return new Promise( resolve => {
  96209. if(this.guiLoaded){
  96210. resolve();
  96211. }else {
  96212. this.guiLoadTasks.push(resolve);
  96213. }
  96214. });
  96215. }
  96216. loadGUI(callback){
  96217. if(callback){
  96218. this.onGUILoaded(callback);
  96219. }
  96220. let viewer = this;
  96221. let sidebarContainer = $('#potree_sidebar_container');
  96222. sidebarContainer.load(new URL(Potree.scriptPath + '/' + (Potree.settings.sidebar || 'sidebar1.html')).href, () => {
  96223. sidebarContainer.css('width', '300px');
  96224. sidebarContainer.css('height', '100%');
  96225. let imgMenuToggle = document.createElement('img');
  96226. imgMenuToggle.src = new URL(Potree.resourcePath + '/icons/menu_button.svg').href;
  96227. imgMenuToggle.onclick = this.toggleSidebar;
  96228. imgMenuToggle.classList.add('potree_menu_toggle');
  96229. let imgMapToggle = document.createElement('img');
  96230. imgMapToggle.src = new URL(Potree.resourcePath + '/icons/map_icon.png').href;
  96231. imgMapToggle.style.display = 'none';
  96232. imgMapToggle.onclick = e => { this.toggleMap(); };
  96233. imgMapToggle.id = 'potree_map_toggle';
  96234. let elButtons = $("#potree_quick_buttons").get(0);
  96235. elButtons.append(imgMenuToggle);
  96236. elButtons.append(imgMapToggle);
  96237. VRButton.createButton(this.renderer).then(vrButton => {
  96238. if(vrButton == null){
  96239. console.log("VR not supported or active.");
  96240. return;
  96241. }
  96242. this.renderer.xr.enabled = true;
  96243. let element = vrButton.element;
  96244. element.style.position = "";
  96245. element.style.bottom = "";
  96246. element.style.left = "";
  96247. element.style.margin = "4px";
  96248. element.style.fontSize = "100%";
  96249. element.style.width = "2.5em";
  96250. element.style.height = "2.5em";
  96251. element.style.padding = "0";
  96252. element.style.textShadow = "black 2px 2px 2px";
  96253. element.style.display = "block";
  96254. elButtons.append(element);
  96255. vrButton.onStart(() => {
  96256. this.dispatchEvent({type: "vr_start"});
  96257. });
  96258. vrButton.onEnd(() => {
  96259. this.dispatchEvent({type: "vr_end"});
  96260. });
  96261. });
  96262. /* this.mapView = new MapView(this);
  96263. this.mapView.init(); */
  96264. i18n.init({
  96265. lng: 'en',
  96266. resGetPath: Potree.resourcePath + '/lang/__lng__/__ns__.json',
  96267. preload: ['en', 'fr', 'de', 'jp', 'se', 'es', 'zh'],
  96268. getAsync: true,
  96269. debug: false
  96270. }, function (t) {
  96271. // Start translation once everything is loaded
  96272. $('body').i18n();
  96273. });
  96274. $(() => {
  96275. //initSidebar(this);
  96276. let sidebar = new Sidebar(this);
  96277. sidebar.init();
  96278. this.sidebar = sidebar;
  96279. //if (callback) {
  96280. // $(callback);
  96281. //}
  96282. let elProfile = $('<div>').load(new URL(Potree.scriptPath + '/profile.html').href, () => {
  96283. $(document.body).append(elProfile.children());
  96284. this.profileWindow = new ProfileWindow(this);
  96285. this.profileWindowController = new ProfileWindowController(this);
  96286. $('#profile_window').draggable({
  96287. handle: $('#profile_titlebar'),
  96288. containment: $(document.body)
  96289. });
  96290. $('#profile_window').resizable({
  96291. containment: $(document.body),
  96292. handles: 'n, e, s, w'
  96293. });
  96294. $(() => {
  96295. this.guiLoaded = true;
  96296. for(let task of this.guiLoadTasks){
  96297. task();
  96298. }
  96299. });
  96300. });
  96301. });
  96302. });
  96303. return this.promiseGuiLoaded();
  96304. }
  96305. setLanguage (lang) {
  96306. i18n.setLng(lang);
  96307. $('body').i18n();
  96308. }
  96309. setServer (server) {
  96310. this.server = server;
  96311. }
  96312. initDragAndDrop(){
  96313. function allowDrag(e) {
  96314. e.dataTransfer.dropEffect = 'copy';
  96315. e.preventDefault();
  96316. }
  96317. let dropHandler = async (event) => {
  96318. console.log(event);
  96319. event.preventDefault();
  96320. for(const item of event.dataTransfer.items){
  96321. console.log(item);
  96322. if(item.kind !== "file"){
  96323. continue;
  96324. }
  96325. const file = item.getAsFile();
  96326. const isJson = file.name.toLowerCase().endsWith(".json");
  96327. const isGeoPackage = file.name.toLowerCase().endsWith(".gpkg");
  96328. if(isJson){
  96329. try{
  96330. const text = await file.text();
  96331. const json = JSON.parse(text);
  96332. if(json.type === "Potree"){
  96333. Potree.loadProject(viewer, json);
  96334. }
  96335. }catch(e){
  96336. console.error("failed to parse the dropped file as JSON");
  96337. console.error(e);
  96338. }
  96339. }else if(isGeoPackage){
  96340. const hasPointcloud = viewer.scene.pointclouds.length > 0;
  96341. if(!hasPointcloud){
  96342. let msg = "At least one point cloud is needed that specifies the ";
  96343. msg += "coordinate reference system before loading vector data.";
  96344. console.error(msg);
  96345. }else {
  96346. proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
  96347. proj4.defs("pointcloud", this.getProjection());
  96348. let transform = proj4("WGS84", "pointcloud");
  96349. const buffer = await file.arrayBuffer();
  96350. const params = {
  96351. transform: transform,
  96352. source: file.name,
  96353. };
  96354. const geo = await Potree.GeoPackageLoader.loadBuffer(buffer, params);
  96355. viewer.scene.addGeopackage(geo);
  96356. }
  96357. }
  96358. }
  96359. };
  96360. $("body")[0].addEventListener("dragenter", allowDrag);
  96361. $("body")[0].addEventListener("dragover", allowDrag);
  96362. $("body")[0].addEventListener("drop", dropHandler);
  96363. }
  96364. updateAnnotations () {
  96365. if(!this.visibleAnnotations){
  96366. this.visibleAnnotations = new Set();
  96367. }
  96368. this.scene.annotations.updateBounds();
  96369. this.scene.cameraP.updateMatrixWorld();
  96370. this.scene.cameraO.updateMatrixWorld();
  96371. let distances = [];
  96372. let renderAreaSize = this.renderer.getSize(new Vector2());
  96373. let viewer = this;
  96374. let visibleNow = [];
  96375. this.scene.annotations.traverse(annotation => {
  96376. if (annotation === this.scene.annotations) {
  96377. return true;
  96378. }
  96379. if (!annotation.visible) {
  96380. return false;
  96381. }
  96382. annotation.scene = this.scene;
  96383. let element = annotation.domElement;
  96384. let position = annotation.position.clone();
  96385. position.add(annotation.offset);
  96386. if (!position) {
  96387. position = annotation.boundingBox.getCenter(new Vector3());
  96388. }
  96389. let distance = viewer.scene.cameraP.position.distanceTo(position);
  96390. let radius = annotation.boundingBox.getBoundingSphere(new Sphere()).radius;
  96391. let screenPos = new Vector3();
  96392. let screenSize = 0;
  96393. {
  96394. // SCREEN POS
  96395. screenPos.copy(position).project(this.scene.getActiveCamera());
  96396. screenPos.x = renderAreaSize.x * (screenPos.x + 1) / 2;
  96397. screenPos.y = renderAreaSize.y * (1 - (screenPos.y + 1) / 2);
  96398. // SCREEN SIZE
  96399. if(viewer.scene.cameraMode == CameraMode.PERSPECTIVE) {
  96400. let fov = Math.PI * viewer.scene.cameraP.fov / 180;
  96401. let slope = Math.tan(fov / 2.0);
  96402. let projFactor = 0.5 * renderAreaSize.y / (slope * distance);
  96403. screenSize = radius * projFactor;
  96404. } else {
  96405. screenSize = Utils.projectedRadiusOrtho(radius, viewer.scene.cameraO.projectionMatrix, renderAreaSize.x, renderAreaSize.y);
  96406. }
  96407. }
  96408. element.css("left", screenPos.x + "px");
  96409. element.css("top", screenPos.y + "px");
  96410. //element.css("display", "block");
  96411. let zIndex = 10000000 - distance * (10000000 / this.scene.cameraP.far);
  96412. if(annotation.descriptionVisible){
  96413. zIndex += 10000000;
  96414. }
  96415. element.css("z-index", parseInt(zIndex));
  96416. if(annotation.children.length > 0){
  96417. let expand = screenSize > annotation.collapseThreshold || annotation.boundingBox.containsPoint(this.scene.getActiveCamera().position);
  96418. annotation.expand = expand;
  96419. if (!expand) {
  96420. //annotation.display = (screenPos.z >= -1 && screenPos.z <= 1);
  96421. let inFrustum = (screenPos.z >= -1 && screenPos.z <= 1);
  96422. if(inFrustum){
  96423. visibleNow.push(annotation);
  96424. }
  96425. }
  96426. return expand;
  96427. } else {
  96428. //annotation.display = (screenPos.z >= -1 && screenPos.z <= 1);
  96429. let inFrustum = (screenPos.z >= -1 && screenPos.z <= 1);
  96430. if(inFrustum){
  96431. visibleNow.push(annotation);
  96432. }
  96433. }
  96434. });
  96435. let notVisibleAnymore = new Set(this.visibleAnnotations);
  96436. for(let annotation of visibleNow){
  96437. annotation.display = true;
  96438. notVisibleAnymore.delete(annotation);
  96439. }
  96440. this.visibleAnnotations = visibleNow;
  96441. for(let annotation of notVisibleAnymore){
  96442. annotation.display = false;
  96443. }
  96444. }
  96445. updateMaterialDefaults(pointcloud){
  96446. // PROBLEM STATEMENT:
  96447. // * [min, max] of intensity, source id, etc. are computed as point clouds are loaded
  96448. // * the point cloud material won't know the range it should use until some data is loaded
  96449. // * users can modify the range at runtime, but sensible default ranges should be
  96450. // applied even if no GUI is present
  96451. // * display ranges shouldn't suddenly change even if the actual range changes over time.
  96452. // e.g. the root node has intensity range [1, 478]. One of the descendants increases range to
  96453. // [0, 2047]. We should not automatically change to the new range because that would result
  96454. // in sudden and drastic changes of brightness. We should adjust the min/max of the sidebar slider.
  96455. const material = pointcloud.material;
  96456. const attIntensity = pointcloud.getAttribute("intensity");
  96457. if(attIntensity != null && material.intensityRange[0] === Infinity){
  96458. material.intensityRange = [...attIntensity.range];
  96459. }
  96460. // const attIntensity = pointcloud.getAttribute("intensity");
  96461. // if(attIntensity && material.intensityRange[0] === Infinity){
  96462. // material.intensityRange = [...attIntensity.range];
  96463. // }
  96464. // let attributes = pointcloud.getAttributes();
  96465. // for(let attribute of attributes.attributes){
  96466. // if(attribute.range){
  96467. // let range = [...attribute.range];
  96468. // material.computedRange.set(attribute.name, range);
  96469. // //material.setRange(attribute.name, range);
  96470. // }
  96471. // }
  96472. }
  96473. update(delta, timestamp){
  96474. viewer.addTimeMark('update','start');
  96475. TWEEN.update(timestamp);
  96476. transitions.update(delta);//写在开头,因为这时候最为固定,计时准确
  96477. this.dispatchEvent({
  96478. type: 'update_start',
  96479. delta: delta,
  96480. timestamp: timestamp});
  96481. this.updateScreenSize(); //判断是否改变canvas大小
  96482. const scene = this.scene;
  96483. const camera = scene.getActiveCamera();
  96484. const visiblePointClouds = this.scene.pointclouds.filter(pc => pc.visible);
  96485. Potree.pointLoadLimit = Potree.pointBudget * 2;
  96486. /* const lTarget = camera.position.clone().add(camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(1000));
  96487. this.scene.directionalLight.position.copy(camera.position);
  96488. this.scene.directionalLight.lookAt(lTarget); */
  96489. for (let pointcloud of visiblePointClouds) {
  96490. pointcloud.showBoundingBox = this.showBoundingBox;
  96491. pointcloud.generateDEM = this.generateDEM;
  96492. pointcloud.minimumNodePixelSize = this.minNodeSize;
  96493. let material = pointcloud.material;
  96494. material.uniforms.uFilterReturnNumberRange.value = this.filterReturnNumberRange;
  96495. material.uniforms.uFilterNumberOfReturnsRange.value = this.filterNumberOfReturnsRange;
  96496. material.uniforms.uFilterGPSTimeClipRange.value = this.filterGPSTimeRange;
  96497. material.uniforms.uFilterPointSourceIDClipRange.value = this.filterPointSourceIDRange;
  96498. material.classification = this.classifications;
  96499. material.recomputeClassification();
  96500. this.updateMaterialDefaults(pointcloud);
  96501. }
  96502. {
  96503. if(this.showBoundingBox){
  96504. let bbRoot = this.scene.scene.getObjectByName("potree_bounding_box_root");
  96505. if(!bbRoot){
  96506. let node = new Object3D();
  96507. node.name = "potree_bounding_box_root";
  96508. this.scene.scene.add(node);
  96509. bbRoot = node;
  96510. }
  96511. let visibleBoxes = [];
  96512. for(let pointcloud of this.scene.pointclouds){
  96513. for(let node of pointcloud.visibleNodes.filter(vn => vn.boundingBoxNode !== undefined)){
  96514. let box = node.boundingBoxNode;
  96515. visibleBoxes.push(box);
  96516. }
  96517. }
  96518. bbRoot.children = visibleBoxes;
  96519. }
  96520. }
  96521. if(this.boundNeedUpdate)this.updateModelBound(); //add
  96522. this.scene.cameraP.fov = this.fov;
  96523. let controls = this.getControls();
  96524. if (controls === this.deviceControls) {
  96525. this.controls.setScene(scene);
  96526. this.controls.update(delta);
  96527. this.scene.cameraP.position.copy(scene.view.position);
  96528. this.scene.cameraO.position.copy(scene.view.position);
  96529. } else if (controls !== null) {
  96530. controls.setScene(scene);
  96531. controls.update(delta);
  96532. //更新camera
  96533. this.viewports.forEach(viewport=>{
  96534. if(!viewport.active)return
  96535. viewport.view.applyToCamera(viewport.camera);
  96536. });
  96537. }
  96538. this.lastFrameChanged = this.cameraChanged();//判断camera画面是否改变
  96539. { // update clip boxes
  96540. let boxes = [];
  96541. // volumes with clipping enabled
  96542. boxes.push(...this.scene.volumes.filter(v => (v.clip && v instanceof BoxVolume$1)));
  96543. // profile segments
  96544. for(let profile of this.scene.profiles){
  96545. boxes.push(...profile.boxes);
  96546. }
  96547. // Needed for .getInverse(), pre-empt a determinant of 0, see #815 / #816
  96548. let degenerate = (box) => box.matrixWorld.determinant() !== 0;
  96549. let clipBoxes = boxes.filter(degenerate).map( box => {
  96550. box.updateMatrixWorld();
  96551. let boxInverse = box.matrixWorld.clone().invert();
  96552. //let boxPosition = box.getWorldPosition(new THREE.Vector3());
  96553. return {box: box, inverse: boxInverse/* , position: boxPosition */};
  96554. });
  96555. //改
  96556. let bigClipInBox = clipBoxes.find(e=>e.box.clipTask == ClipTask.SHOW_INSIDE_Big && !e.box.highlight);//裁剪下载 when this.modules.Clip.editing
  96557. let clipBoxes_in = clipBoxes.filter(e=>e.box.clipTask == ClipTask.SHOW_INSIDE && !e.box.highlight);
  96558. let clipBoxes_out = clipBoxes.filter(e=>e.box.clipTask == ClipTask.SHOW_OUTSIDE && !e.box.highlight);
  96559. let highlightBoxes = clipBoxes.filter(e=>e.box.highlight );
  96560. // set clip volumes in material
  96561. for(let pointcloud of visiblePointClouds){
  96562. let clipBoxes_in2 = [], clipBoxes_out2 = [], highlightBoxes2 = [];
  96563. if(pointcloud.dataset_id == Potree.settings.originDatasetId){ //实时裁剪只对初始数据集有效
  96564. clipBoxes_in2 = clipBoxes_in, clipBoxes_out2 = clipBoxes_out, highlightBoxes2 = highlightBoxes;
  96565. }
  96566. pointcloud.material.setClipBoxes(bigClipInBox, clipBoxes_in2, clipBoxes_out2, highlightBoxes2);
  96567. }
  96568. }
  96569. {
  96570. for(let pointcloud of visiblePointClouds){
  96571. pointcloud.material.elevationGradientRepeat = this.elevationGradientRepeat;
  96572. }
  96573. }
  96574. { // update navigation cube
  96575. this.navCubeViewer.update(delta);
  96576. }
  96577. this.updateAnnotations();
  96578. this.transformationTool.update();
  96579. this.dispatchEvent({ type: 'update', delta: delta, timestamp: timestamp}); //在有sidebar时耗高cpu,占本update函数80%
  96580. viewer.addTimeMark('update','end');
  96581. //add ------
  96582. this.reticule.updateVisible();
  96583. }
  96584. updateViewPointcloud(camera, areaSize, isViewport){
  96585. let result = Potree.updatePointClouds(this.scene.pointclouds, camera, areaSize );
  96586. //if(isViewport)return
  96587. const tStart = performance.now();
  96588. const campos = camera.position;
  96589. let closestImage = Infinity;
  96590. for(const images of this.scene.orientedImages){
  96591. for(const image of images.images){
  96592. const distance = image.mesh.position.distanceTo(campos);
  96593. closestImage = Math.min(closestImage, distance);
  96594. }
  96595. }
  96596. //const tEnd = performance.now();
  96597. //改:不根据点云修改视野near far
  96598. var near = camera.near, far = camera.far;
  96599. if(!camera.limitFar && result.lowestSpacing !== Infinity){
  96600. //let near = result.lowestSpacing * 10.0;
  96601. let far = -this.getBoundingBox().applyMatrix4(camera.matrixWorldInverse).min.z;
  96602. far = Math.max(far * 1.5, 10000);
  96603. //near = Math.min(100.0, Math.max(0.01, near));
  96604. //near = Math.min(near, closestImage);
  96605. far = Math.max(far, near + 10000);
  96606. /* if(near === Infinity){
  96607. near = 0.1;
  96608. } */
  96609. //camera.near = near; //为了其他物体的显示,不修改near
  96610. camera.far = far;
  96611. }
  96612. /* if(this.scene.cameraMode == CameraMode.ORTHOGRAPHIC) {//???
  96613. camera.near = -camera.far;
  96614. } */
  96615. if(/* near != camera.near || */far != camera.far){
  96616. camera.updateProjectionMatrix();
  96617. }
  96618. //注:pointcloud.visibleNodes会随着near far自动更新
  96619. }
  96620. getPRenderer(){
  96621. if(this.useHQ){
  96622. if (!this.hqRenderer) {
  96623. this.hqRenderer = new HQSplatRenderer(this);
  96624. }
  96625. this.hqRenderer.useEDL = this.useEDL;
  96626. return this.hqRenderer;
  96627. }else {
  96628. /* if (this.useEDL && Features.SHADER_EDL.isSupported()) {
  96629. if (!this.edlRenderer) {
  96630. this.edlRenderer = new EDLRenderer(this);
  96631. }
  96632. return this.edlRenderer;
  96633. } else {
  96634. if (!this.potreeRenderer) {
  96635. this.potreeRenderer = new PotreeRenderer(this);
  96636. }
  96637. return this.potreeRenderer;
  96638. } */
  96639. if (!this.edlRenderer) {
  96640. this.edlRenderer = new EDLRenderer(this);
  96641. }
  96642. return this.edlRenderer;
  96643. }
  96644. }
  96645. renderVR(){//渲染部分没改完
  96646. let renderer = this.renderer;
  96647. renderer.setClearColor(0x550000, 0);
  96648. renderer.clear();
  96649. let xr = renderer.xr;
  96650. let dbg = new PerspectiveCamera();
  96651. let xrCameras = xr.getCamera(dbg);
  96652. if(xrCameras.cameras.length !== 2){
  96653. return;
  96654. }
  96655. let makeCam = this.vrControls.getCamera.bind(this.vrControls);
  96656. { // clear framebuffer
  96657. if(viewer.background === "skybox"){
  96658. renderer.setClearColor(0xff0000, 1);
  96659. }else if(viewer.background === "gradient"){
  96660. renderer.setClearColor(0x112233, 1);
  96661. }else if(viewer.background === "black"){
  96662. renderer.setClearColor(0x000000, 1);
  96663. }else if(viewer.background === "white"){
  96664. renderer.setClearColor(0xFFFFFF, 1);
  96665. }else {
  96666. renderer.setClearColor(0x000000, 0);
  96667. }
  96668. renderer.clear();
  96669. }
  96670. // render background
  96671. if(this.background === "skybox"){
  96672. let {skybox} = this;
  96673. let cam = makeCam();
  96674. skybox.camera.rotation.copy(cam.rotation);
  96675. skybox.camera.fov = cam.fov;
  96676. skybox.camera.aspect = cam.aspect;
  96677. // let dbg = new THREE.Object3D();
  96678. let dbg = skybox.parent;
  96679. // dbg.up.set(0, 0, 1);
  96680. dbg.rotation.x = Math.PI / 2;
  96681. // skybox.camera.parent = dbg;
  96682. // dbg.children.push(skybox.camera);
  96683. dbg.updateMatrix();
  96684. dbg.updateMatrixWorld();
  96685. skybox.camera.updateMatrix();
  96686. skybox.camera.updateMatrixWorld();
  96687. skybox.camera.updateProjectionMatrix();
  96688. renderer.render(skybox.scene, skybox.camera);
  96689. // renderer.render(skybox.scene, cam);
  96690. }else if(this.background === "gradient"){
  96691. // renderer.render(this.scene.sceneBG, this.scene.cameraBG);
  96692. }
  96693. this.renderer.xr.getSession().updateRenderState({
  96694. depthNear: 0.1,
  96695. depthFar: 10000
  96696. });
  96697. let cam = null;
  96698. let view = null;
  96699. { // render world scene
  96700. cam = makeCam();
  96701. cam.position.z -= 0.8 * cam.scale.x;
  96702. cam.parent = null;
  96703. // cam.near = 0.05;
  96704. cam.near = viewer.scene.getActiveCamera().near;
  96705. cam.far = viewer.scene.getActiveCamera().far;
  96706. cam.updateMatrix();
  96707. cam.updateMatrixWorld();
  96708. this.scene.scene.updateMatrix();
  96709. this.scene.scene.updateMatrixWorld();
  96710. this.scene.scene.matrixAutoUpdate = false;
  96711. let camWorld = cam.matrixWorld.clone();
  96712. view = camWorld.clone().invert();
  96713. this.scene.scene.matrix.copy(view);
  96714. this.scene.scene.matrixWorld.copy(view);
  96715. cam.matrix.identity();
  96716. cam.matrixWorld.identity();
  96717. cam.matrixWorldInverse.identity();
  96718. renderer.render(this.scene.scene, cam);
  96719. this.scene.scene.matrixWorld.identity();
  96720. }
  96721. for(let pointcloud of this.scene.pointclouds){
  96722. let viewport = xrCameras.cameras[0].viewport;
  96723. pointcloud.material.useEDL = false;
  96724. pointcloud.screenHeight = viewport.height;
  96725. pointcloud.screenWidth = viewport.width;
  96726. // automatically switch to paraboloids because they cause far less flickering in VR,
  96727. // when point sizes are larger than around 2 pixels
  96728. // if(Features.SHADER_INTERPOLATION.isSupported()){
  96729. // pointcloud.material.shape = Potree.PointShape.PARABOLOID;
  96730. // }
  96731. }
  96732. // render point clouds
  96733. for(let xrCamera of xrCameras.cameras){
  96734. let v = xrCamera.viewport;
  96735. renderer.setViewport(v.x, v.y, v.width, v.height);
  96736. // xrCamera.fov = 90;
  96737. { // estimate VR fov
  96738. let proj = xrCamera.projectionMatrix;
  96739. let inv = proj.clone().invert();
  96740. let p1 = new Vector4(0, 1, -1, 1).applyMatrix4(inv);
  96741. let rad = p1.y;
  96742. let fov = 180 * (rad / Math.PI);
  96743. xrCamera.fov = fov;
  96744. }
  96745. for(let pointcloud of this.scene.pointclouds){
  96746. const {material} = pointcloud;
  96747. material.useEDL = false;
  96748. }
  96749. let vrWorld = view.clone().invert();
  96750. vrWorld.multiply(xrCamera.matrixWorld);
  96751. let vrView = vrWorld.clone().invert();
  96752. this.pRenderer.render(this.scene.scenePointCloud, xrCamera, null, {
  96753. viewOverride: vrView,
  96754. });
  96755. }
  96756. { // render VR scene
  96757. let cam = makeCam();
  96758. cam.parent = null;
  96759. renderer.render(this.sceneVR, cam);
  96760. }
  96761. renderer.resetState();
  96762. }
  96763. clear(params={}){
  96764. let background = params.background || this.background;
  96765. let backgroundOpacity = params.backgroundOpacity == void 0 ? this.backgroundOpacity : params.backgroundOpacity;//如果想完全透明,只需要backgroundOpacity为0
  96766. let renderer = this.renderer;
  96767. //let gl = renderer.getContext()
  96768. if(background instanceof Color){ //add
  96769. renderer.setClearColor(background, backgroundOpacity);
  96770. }else if(background === "skybox"){
  96771. renderer.setClearColor(0x000000, 0 );
  96772. } else if (background === 'gradient') {
  96773. renderer.setClearColor(0x000000, 0);
  96774. } else if (background === 'black') {
  96775. renderer.setClearColor(0x000000, 1);
  96776. } else if (background === 'white') {
  96777. renderer.setClearColor(0xFFFFFF, 1);
  96778. } else {
  96779. renderer.setClearColor(background, backgroundOpacity);
  96780. }
  96781. params.target || renderer.clear();
  96782. }
  96783. getBuffer(viewport){//根据不同viewport返回rtEDL的texture
  96784. var buffer = this.buffers.get(viewport);
  96785. if(!buffer){
  96786. buffer = new WebGLRenderTarget(viewport.resolution.x, viewport.resolution.y, {
  96787. minFilter: NearestFilter,
  96788. magFilter: NearestFilter,
  96789. format: RGBAFormat,
  96790. type: FloatType
  96791. });
  96792. this.buffers.set(viewport, rtEDL);
  96793. }
  96794. return buffer
  96795. }
  96796. renderDefault(params_={}){
  96797. if(!this.visible || this.paused )return
  96798. let pRenderer = this.getPRenderer();
  96799. let viewports = params_.viewports || this.viewports;
  96800. /* if(!this.needRender){
  96801. viewports = viewports.filter(v=>v.needRender) //可以渲染的条件是viewer或viewport的needRender为true
  96802. }
  96803. viewports = viewports.filter(v=>v.active)
  96804. if(viewports.length == 0)return */
  96805. viewer.addTimeMark('renderDefault','start');
  96806. //console.log('render', viewports.map(e=>e.name).join(','))
  96807. let renderSize;
  96808. if(params_.target){
  96809. renderSize = new Vector2(params_.target.width, params_.target.height); //是画布大小
  96810. //可能需要viewer.setSize
  96811. }else {
  96812. renderSize = this.renderer.getSize(new Vector2()); //是client大小
  96813. }
  96814. let needSResize = viewports.length > 1 || params_.resize;
  96815. viewports.forEach(view=>{
  96816. let params = $.extend({},params_);
  96817. params.viewport = view;
  96818. //if(!params.target){
  96819. params.camera = params.camera || view.camera;
  96820. params.extraEnableLayers = view.extraEnableLayers;
  96821. params.cameraLayers = view.cameraLayers;
  96822. //}
  96823. var left,bottom,width,height;
  96824. {
  96825. left = Math.ceil(renderSize.x * view.left);
  96826. bottom = Math.ceil(renderSize.y * view.bottom);
  96827. if(params_.target){//有target时最好viewport是专门建出来的
  96828. width = Math.ceil(renderSize.x * view.width); //target的大小可能和viewport不同,比如截图,这时会更改viewport大小
  96829. height = Math.ceil(renderSize.y * view.height);
  96830. }else {
  96831. width = view.resolution.x; // 用的是client的width和height
  96832. height = view.resolution.y;
  96833. }
  96834. if(width == 0 || height == 0)return
  96835. let scissorTest = view.width<1 || view.height<1;
  96836. if(params_.target){
  96837. params_.target.viewport.set(left, bottom, width, height);
  96838. scissorTest && params_.target.scissor.set(left, bottom, width, height);
  96839. params_.target.scissorTest = scissorTest;
  96840. this.renderer.setRenderTarget(params_.target);
  96841. }else {
  96842. this.renderer.setViewport(left, bottom, width, height); //规定视口,影响图形变换(画布的使用范围)
  96843. scissorTest && this.renderer.setScissor( left, bottom, width, height );//规定渲染范围
  96844. this.renderer.setScissorTest( scissorTest );//开启WebGL剪裁测试功能,如果不开启,.setScissor方法设置的范围不起作用 | width==1且height==1时开启会只有鼠标的地方刷新,很奇怪
  96845. }
  96846. }
  96847. if(needSResize){
  96848. this.ifEmitResize( { viewport:view} );
  96849. }
  96850. viewer.dispatchEvent({type: "render.begin", viewer: viewer, viewport:view, params });
  96851. view.beforeRender && view.beforeRender();
  96852. if(view.render){
  96853. if(!view.render($.extend({}, params, {
  96854. renderer:this.renderer, clear:this.clear.bind(this), resize:null,
  96855. renderBG:this.renderBG.bind(this), force:true //viewer content_change时map也直接渲染吧 //!view.noPointcloud //如果要渲染点云,必须也一直渲染地图,否则地图会被覆盖(点云目前未能获取是否改变,也可能有其他动态物体,所以还是一直渲染的好)
  96856. })))return
  96857. }else {
  96858. this.clear(params);
  96859. pRenderer.clearTargets(params);
  96860. this.renderBG(view);
  96861. if(Potree.settings.notAdditiveBlending){
  96862. params.renderBeforeCloud = true;
  96863. this.renderOverlay1(params); //先渲染不透明的model。 但drawedModelOnRT时这里提前多渲染了一遍
  96864. }
  96865. }
  96866. if(!view.noPointcloud ){
  96867. this.updateViewPointcloud(params.camera, view.resolution, true);
  96868. pRenderer.render(params); //渲染点云 skybox
  96869. }
  96870. if(Potree.settings.notAdditiveBlending){ // 融合页面才用到
  96871. params.renderBeforeCloud = false;
  96872. this.renderOverlay1(params);
  96873. this.renderOverlay2(params);
  96874. }else {
  96875. this.renderOverlay(params);
  96876. }
  96877. view.afterRender && view.afterRender();
  96878. this.dispatchEvent({type: "render.end", viewer: this, viewport:view });
  96879. view.needRender = false;
  96880. });
  96881. /* if(params_.screenshot){ //抗锯齿
  96882. params_.target.viewport.set(0, 0, params_.target.width, params_.target.height);
  96883. //scissorTest && params_.target.scissor.set(left, bottom, width, height);
  96884. params_.target.scissorTest = false
  96885. this.renderer.setRenderTarget(params_.target)
  96886. this.composer.render();
  96887. this.renderer.setRenderTarget(params_.target) //本想再画一层标签,但是viewport总是出错
  96888. } */
  96889. this.renderer.setRenderTarget(null);
  96890. viewer.scene.pointclouds[0] && this.addFakeMeasure('visibleNodes', viewer.scene.pointclouds[0].visibleNodes.length );//
  96891. this.addFakeMeasure('numVisiblePoints', Potree.numVisiblePoints/100000);//十万 numVisiblePoints和帧率成反比(若每一帧都render的话),和render用时成正比 (y=kn+b)。但visibleNodes个数也影响,多的话也更卡。visibleNodes和numVisiblePoints不成正比,少的visibleNodes可能numVisiblePoints多
  96892. viewer.addTimeMark('renderDefault','end');
  96893. }
  96894. renderBG(view){
  96895. let background = view.background || viewer.background;
  96896. let backgroundOpacity = view.backgroundOpacity == void 0 ? viewer.backgroundOpacity : view.backgroundOpacity;//如果想完全透明,只需要backgroundOpacity为0
  96897. if(backgroundOpacity != 0){//绘制背景
  96898. if(background === "skybox"){
  96899. //限制相机到原点的距离。
  96900. let skyCamera = view.camera.type == "OrthographicCamera" ? viewer.skybox.cameraOrtho : viewer.skybox.camera;
  96901. let safeRatio = 0.02;
  96902. let safeWidth = Potree.config.skyboxBgWidth * safeRatio / 2; //相机只能在这个范围内移动
  96903. if(!view.skyboxFixPos){ //允许不在全景图中心,允许位移造成一定程度畸变
  96904. let dir = new Vector3().subVectors(view.camera.position, viewer.bound.center);
  96905. let length = dir.length();
  96906. const moveMax = 100;
  96907. let aimRadius = easing.easeOutQuart(Math.min(length, moveMax) , 0, safeWidth, moveMax); //(x, startY, wholeY, maxX) 当自变量为0-moveMax时,相机位移量为0-safeWidth
  96908. dir.multiplyScalar(aimRadius/length);
  96909. skyCamera.position.copy(dir);
  96910. }else {
  96911. skyCamera.position.set(0,0,0);
  96912. }
  96913. skyCamera.rotation.copy(view.camera.rotation);
  96914. skyCamera.aspect = view.camera.aspect;
  96915. if(view.camera.type == "OrthographicCamera"){ //调节zoom
  96916. skyCamera.left = view.camera.left; skyCamera.right = view.camera.right; skyCamera.top = view.camera.top; skyCamera.bottom = view.camera.bottom;
  96917. let a = Potree.config.skyboxBgWidth / 2 - safeWidth;
  96918. let minY = Math.max(skyCamera.right / a, skyCamera.top / a, view.skyboxMinZoom||0); //能够使skybox铺满画布的最小zoom. 提示:越远zoom越小
  96919. let maxY = Math.max(20, minY) ;//自定义一个 不会超过的最大实际zoom
  96920. //view.camera.zoom自变量的变化范围:
  96921. let minX = 1;
  96922. let maxX = 80;
  96923. let x = MathUtils$1.clamp(view.camera.zoom - minX, minX, maxX);
  96924. skyCamera.zoom = easing.easeOutCubic(x-minX, minY, maxY-minY, maxX-minX); //自变量范围从0开始,所以减去minX
  96925. //pos的范围先不管了 其实aimRadius是有误的,但效果还行
  96926. }else {
  96927. skyCamera.fov = view.camera.fov;
  96928. skyCamera.zoom = 1;
  96929. }
  96930. view.skyboxRenderFun && view.skyboxRenderFun();
  96931. skyCamera.updateProjectionMatrix();
  96932. skyCamera.updateMatrixWorld();
  96933. viewer.renderer.render(viewer.skybox.scene, skyCamera);
  96934. }else if(background === 'gradient'){
  96935. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
  96936. viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  96937. }else if(background === 'overlayColor'){//在不clear的前提下加一层背景色
  96938. viewer.scene.bg2.material.color.copy(view.backgroundColor);
  96939. viewer.scene.bg2.material.opacity = view.backgroundOpacity;
  96940. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg2);
  96941. viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  96942. }
  96943. }
  96944. //全景图的部分和点云有点相关就不移动到这了。但是如果是showPanos模式,就不要渲染背景了。
  96945. }
  96946. /*
  96947. 关于透明度:
  96948. 由于点云和mesh是分开渲染的,且材质很不一样,所以透明和blend有冲突
  96949. 1 如果点云的blend是AdditiveBlending,也就是普通的叠加模式。
  96950. 则半透明点云的depthTest和depthWrite都为false
  96951. 这时候mesh要后渲染,且depthWrite不能为false(除非depthTest也为false),否则将被点云遮住。
  96952. 2 如果点云的blend是普通型
  96953. 则半透明点云的depthTest和depthWrite都为true。(为何depthWrite不能像mesh一样为false, 否则点云自身透明会错乱,可能因为太多points了)
  96954. 这时候若mesh全部先渲染,则 透过depthWrite为false的半透明mesh看不透明点云,mesh会完全被点云遮住。但是透明的物体就是depthWrite要为false,否则也会完全遮住点云
  96955. 即使是后渲染半透明的mesh,若透过点云看mesh,mesh会完全被点云遮住(为什么之前遇到过 透过点云看mesh,点云会显示不出)
  96956. 最终选择是先渲染不透明的mesh,然后点云,然后透明的mesh。虽然点云对mesh透明会失效。
  96957. */
  96958. renderOverlay(params){
  96959. viewer.addTimeMark('renderOverlay','start');
  96960. this.renderOverlay1(params);
  96961. this.renderOverlay2(params);
  96962. viewer.addTimeMark('renderOverlay','end');
  96963. }
  96964. renderOverlay1(params){
  96965. let camera = params.camera ? params.camera : this.scene.getActiveCamera();
  96966. this.reticule.updateAtViewports(params.viewport);
  96967. this.renderer.setRenderTarget(params.target||null);
  96968. //为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖
  96969. let cameraLayers;
  96970. if(params.cameraLayers) cameraLayers = params.cameraLayers;
  96971. else {
  96972. if(params.viewport.name == "mapViewport" )cameraLayers = ['bothMapAndScene', 'light'];
  96973. else {
  96974. cameraLayers = ['sceneObjects', 'light', 'bothMapAndScene' ];
  96975. if(!params.drawedModelOnRT){
  96976. cameraLayers.push('model');
  96977. }
  96978. }
  96979. }
  96980. if(cameraLayers.length){
  96981. Potree.Utils.setCameraLayers(camera, cameraLayers, params.extraEnableLayers); //透明贴图层 skybox 、reticule marker 不能遮住测量线
  96982. if('renderBeforeCloud' in params){
  96983. this.scene.scene.traverse((object)=>{
  96984. if(object.material){
  96985. Potree.Utils.updateVisible(object, 'renderOpa',
  96986. (params.renderBeforeCloud && (object.material.opacity<1 || !object.material.depthTest) || (!params.renderBeforeCloud) && (object.material.opacity==1 && object.material.depthTest))? false:true);
  96987. //点云之前渲染的话隐藏半透明的, 点云之后渲染的话隐藏不透明的。 depthTest==false的也最后渲染
  96988. }
  96989. });//ground的材质中opacity为1,所以被当做不透明了
  96990. }
  96991. this.renderer.render(this.scene.scene, camera);
  96992. if('renderBeforeCloud' in params){
  96993. this.scene.scene.traverse((object)=>{
  96994. if(object.material){
  96995. Potree.Utils.updateVisible(object, 'renderOpa', true); //恢复
  96996. }
  96997. });
  96998. }
  96999. }
  97000. this.dispatchEvent({type: "render.pass.scene", viewer: viewer});
  97001. }
  97002. renderOverlay2(params){
  97003. let camera = params.camera ? params.camera : this.scene.getActiveCamera();
  97004. //清除深度 !!!!
  97005. this.renderer.clearDepth();
  97006. if(!params.magnifier){
  97007. //测量线
  97008. this.dispatchEvent({type: "render.pass.perspective_overlay", camera, screenshot:params.screenshot});
  97009. if(!params.screenshot && params.viewport.name != "mapViewport" ){
  97010. Potree.Utils.setCameraLayers(camera, ['magnifier']); //magnifier 遮住测量线
  97011. this.renderer.render(this.scene.scene, camera);
  97012. }
  97013. }
  97014. if(params.viewport.name != "mapViewport" ) {
  97015. Potree.Utils.setCameraLayers(camera, ['volume','transformationTool']);
  97016. this.renderer.render(this.clippingTool.sceneVolume, camera); //official 可以删
  97017. this.renderer.render(this.transformationTool.scene, camera);
  97018. }
  97019. }
  97020. setLimitFar(state){//切换是否limitFar
  97021. viewer.mainViewport.camera.limitFar = !!state;
  97022. if(state){
  97023. viewer.mainViewport.camera.near = 0.02;
  97024. viewer.mainViewport.camera.far = Potree.settings.displayMode == 'showPanos' ? viewer.farWhenShowPano : Potree.settings.cameraFar;
  97025. viewer.mainViewport.camera.updateProjectionMatrix();
  97026. }
  97027. }
  97028. setClipState(state){//有时候需要暂时关闭下clip
  97029. state = !!state;
  97030. if(this.clipUnabled == !state)return
  97031. this.scene.volumes.filter(v=>/* v.clip && */ v instanceof Potree.BoxVolume).map(volume=>{
  97032. volume.clip = state;
  97033. Potree.Utils.updateVisible(volume, 'setClipState', state);
  97034. });
  97035. this.clipUnabled = !state;
  97036. }
  97037. /* 大规模WebGL应用引发浏览器崩溃的几种情况及解决办法
  97038. https://blog.csdn.net/weixin_30378311/article/details/94846947 */
  97039. render(params={}){//add params
  97040. viewer.addTimeMark('render','start');
  97041. const vrActive = this.renderer.xr.isPresenting;
  97042. //Potree.settings.useRTPoint = !(SiteModel.editing && SiteModel.selected && SiteModel.selected.buildType == 'room' )//空间模型的房间选中材质是需要depth的,这时候需要绘制两次点云
  97043. Potree.settings.pointEnableRT = this.scene.measurements.length > 0 || !Potree.settings.useRTPoint;
  97044. if(vrActive){
  97045. this.renderVR();
  97046. }else {
  97047. let specialRender = !!params.viewports;
  97048. let viewports = params.viewports || this.viewports;
  97049. if(!this.needRender){
  97050. viewports = viewports.filter(v=>v.needRender); //可以渲染的条件是viewer或viewport的needRender为true
  97051. }
  97052. viewports = viewports.filter(v=>v.active);
  97053. if(viewports.length > 0){
  97054. params.viewports = viewports;
  97055. if(this.outlinePass.selectedObjects.length && this.outlinePass.edgeStrength > 0 && !params.screenshot){
  97056. let scenes = this.inputHandler.interactiveScenes.concat(this.scene.scene).concat(viewer.scene.scenePointCloud);
  97057. this.composer.render(scenes, null, this.viewports, this.renderDefault.bind(this));
  97058. }else {
  97059. this.renderDefault(params);
  97060. }
  97061. }
  97062. if(!specialRender) this.needRender = false;
  97063. }
  97064. viewer.addTimeMark('render','end');
  97065. }
  97066. startScreenshot(info={}, width=800, height=400, compressRatio ){//add
  97067. //let deferred = info.deferred || $.Deferred();
  97068. let getImageDeferred = info.getImageDeferred || $.Deferred();
  97069. let finishDeferred = info.finishDeferred || $.Deferred();
  97070. let viewerMaster = info.map ? this.mapViewer : this; //截图主体
  97071. let useMap = info.type == 'measure' || info.map;
  97072. if(Potree.settings.displayMode == 'showPanos' && viewer.scene.view.isFlying('pos')){//如果在飞,飞完再截图
  97073. info.getImageDeferred = getImageDeferred , info.finishDeferred = finishDeferred;
  97074. let f = ()=>{
  97075. this.startScreenshot(info, width, height, compressRatio);
  97076. };
  97077. viewer.scene.view.addEventListener('flyingDone', f, {once:true});
  97078. return {getImagePromise:getImageDeferred.promise(), finishPromise:finishDeferred.promise()}
  97079. }
  97080. var sid = Date.now();
  97081. //抗锯齿待加 1 post处理 2截图大张再抗锯齿缩小
  97082. console.log('startScreenshot: '+sid);
  97083. let updateCamera = ()=>{
  97084. this.viewports.forEach(e=>{
  97085. e.view.applyToCamera(e.camera); //因为fly时只更新了view所以要强制更新下camera
  97086. this.dispatchEvent({ //update map and sprite
  97087. type: "camera_changed",
  97088. camera: e.camera,
  97089. viewport : e,
  97090. changeInfo:{positionChanged:true,changed:true}
  97091. });
  97092. });
  97093. };
  97094. let screenshot = ()=>{
  97095. let pose;
  97096. useMap && (viewer.mapViewer.needRender = true);
  97097. this.needRender = true;
  97098. let { dataUrl } = viewerMaster.makeScreenshot( new Vector2(width,height), null, compressRatio );
  97099. if(!Potree.settings.isOfficial){
  97100. Common$1.downloadFile(dataUrl, 'screenshot.jpg');
  97101. }
  97102. var finish = ()=>{
  97103. oldStates.viewports.forEach(old=>{//恢复相机
  97104. var viewport = viewports.find(v=>v.name == old.name);
  97105. viewport.left = old.left;
  97106. viewport.width = old.width;
  97107. viewport.view.copy(old.view);
  97108. viewport.view.applyToCamera(viewport.camera);
  97109. });
  97110. viewer.updateScreenSize({forceUpdateSize:true});//更新像素
  97111. /* oldStates.viewports.forEach(old=>{//恢复相机
  97112. var viewport = [mapViewport, mainViewport].find(v=>v.name == old.name);
  97113. this.dispatchEvent({ //update map
  97114. type: "camera_changed",
  97115. camera: viewport.camera,
  97116. viewport : viewport
  97117. })
  97118. }) */
  97119. updateCamera();
  97120. finishDeferred.resolve({dataUrl, pose});
  97121. console.log('screenshot done: '+sid);
  97122. };
  97123. {//恢复:
  97124. if(info.type == 'measure'){
  97125. this.scene.measurements.forEach(e=>Potree.Utils.updateVisible(e, 'screenshot',true));
  97126. info.measurement.setSelected(false, 'screenshot');
  97127. }
  97128. this.images360.panos.forEach(pano=>{
  97129. Potree.Utils.updateVisible(pano, 'screenshot', true);
  97130. });
  97131. if(info.hideMeasures){
  97132. viewer.scene.measurements.forEach((e)=>{
  97133. Potree.Utils.updateVisible(e, 'screenshot', true);
  97134. });
  97135. }else {
  97136. viewer.scene.measurements.forEach((e)=>{
  97137. e.edgeLabels.forEach(label=>{
  97138. label.backgroundColor.a = label._oldA ;//透明的抗锯齿渲染会变黑,所以去除透明
  97139. label.updateTexture();
  97140. });
  97141. });
  97142. }
  97143. Potree.Utils.updateVisible(this.reticule, 'screenshot', true);
  97144. if(useMap){
  97145. Potree.Utils.updateVisible(this.mapViewer.cursor, 'screenshot', true);
  97146. if(oldStates.attachedToViewer != this.mapViewer.attachedToViewer){
  97147. if(info.type == 'measure'){
  97148. this.mapViewer.attachToMainViewer(false );
  97149. }
  97150. }
  97151. mapViewport.camera.zoom = oldStates.mapZoom;
  97152. mapViewport.camera.updateProjectionMatrix();
  97153. }
  97154. let recover = ()=>{
  97155. if(Potree.settings.displayMode == 'showPanos') {
  97156. viewer.images360.flyToPano({pano:oldStates.pano, duration:0, callback:()=>{
  97157. finish();
  97158. }});
  97159. }else {
  97160. finish();
  97161. }
  97162. };
  97163. if(info.ifGetPose){
  97164. Potree.sdk.scene.getPose().done(pose_ =>{
  97165. pose = pose_;
  97166. getImageDeferred.resolve({dataUrl, pose});
  97167. recover();
  97168. });
  97169. }else {
  97170. recover();
  97171. }
  97172. }
  97173. };// screenshot end
  97174. let mapViewport;
  97175. let mainViewport = this.mainViewport;
  97176. let viewports = [mainViewport];
  97177. let oldStates = {
  97178. viewports : [mainViewport.clone()],
  97179. pano: Potree.settings.displayMode == 'showPanos' ? viewer.images360.currentPano : null,
  97180. };
  97181. if(useMap){
  97182. mapViewport = this.mapViewer.viewports[0];
  97183. viewports.push(mapViewport);
  97184. oldStates.viewports.push(mapViewport.clone());
  97185. oldStates.attachedToViewer = this.mapViewer.attachedToViewer;
  97186. oldStates.mapZoom = mapViewport.camera.zoom;
  97187. Potree.Utils.updateVisible(this.mapViewer.cursor, 'screenshot', false);//令mapCursor不可见
  97188. }
  97189. if(info.hideMarkers){
  97190. this.images360.panos.forEach(pano=>{//令漫游点不可见
  97191. Potree.Utils.updateVisible(pano, 'screenshot', false);
  97192. });
  97193. }
  97194. if(info.hideMeasures){
  97195. viewer.scene.measurements.forEach((e)=>{
  97196. Potree.Utils.updateVisible(e, 'screenshot', false);
  97197. });
  97198. }else {
  97199. viewer.scene.measurements.forEach((e)=>{
  97200. e.edgeLabels.forEach(label=>{
  97201. label._oldA = label.backgroundColor.a;
  97202. label.backgroundColor.a = 1 ;//透明的抗锯齿渲染会变黑,所以去除透明
  97203. label.updateTexture();
  97204. });
  97205. });
  97206. }
  97207. Potree.Utils.updateVisible(this.reticule, 'screenshot', false);//令reticule不可见
  97208. if(info.type == 'measure'){//要截图双屏
  97209. this.scene.measurements.forEach(e=>Potree.Utils.updateVisible(e,'screenshot',e == info.measurement) );
  97210. info.measurement.setSelected(true, 'screenshot');
  97211. //因为分屏后位置才最终确定,才能确定是否显示出floorplan所以先分屏
  97212. if(Potree.settings.floorplanEnable){
  97213. this.mapViewer.attachToMainViewer(true, 'measure', 0.5 );
  97214. }
  97215. viewer.updateScreenSize({forceUpdateSize:true, width, height}); //更新viewports相机透视 使focusOnObject在此窗口大小下
  97216. let begin = ()=>{
  97217. useMap = this.mapViewer.attachedToViewer;
  97218. updateCamera();
  97219. let waitTime = Potree.settings.displayMode == 'showPointCloud' ? 500 : 0; //等点云加载 网速差的话还是加载稀疏 是否要用最高质量点云
  97220. if(useMap){
  97221. let waitMap = ()=>{
  97222. //console.log('waitMap: '+sid)
  97223. this.mapViewer.waitLoadDone(screenshot.bind(this));//等待地图所有加载完
  97224. };
  97225. setTimeout(waitMap.bind(this), waitTime);
  97226. }else {
  97227. setTimeout(screenshot.bind(this), waitTime);
  97228. }
  97229. };
  97230. let {promise}= this.focusOnObject(info.measurement, 'measure', 0, {basePanoSize:1024} );//注意:不同角度截图 得到三维的会不一样,因为focusOnObject是根据方向的
  97231. promise.done(()=>{
  97232. //console.log('promise.done')
  97233. //根据当前位置更新floorplan显示
  97234. //console.log('view Pos ', this.mainViewport.view.position.toArray())
  97235. this.updateDatasetAt(true);
  97236. this.modules.SiteModel.updateEntityAt(true);
  97237. //this.updateFpVisiDatasets()
  97238. //console.log('currentFloor', this.modules.SiteModel.currentFloor, 'currentDataset', this.atDatasets )
  97239. let floorplanShowed = this.mapViewer.mapLayer.maps.some(e => e.name.includes('floorplan') && e.objectGroup.visible);
  97240. if(!floorplanShowed && this.mapViewer.attachedToViewer){
  97241. this.mapViewer.attachToMainViewer(false); //取消分屏
  97242. viewer.updateScreenSize({forceUpdateSize:true, width, height}); //更新viewports相机透视
  97243. let {promise} = this.focusOnObject(info.measurement, 'measure', 0, {basePanoSize:1024} );//因画面比例更改,重新focus
  97244. promise.done(()=>{
  97245. begin();
  97246. });
  97247. }else {
  97248. begin();
  97249. }
  97250. });
  97251. }else {
  97252. screenshot();
  97253. }
  97254. /*
  97255. 测量线的截图因为要调用分屏的,会改变画面
  97256. 但是普通截图的话,不会改变画面
  97257. */
  97258. return {getImagePromise:getImageDeferred.promise(), finishPromise:finishDeferred.promise()}
  97259. }
  97260. focusOnObject(object, type, duration, o={} ) {
  97261. //飞向热点、测量线等 。
  97262. //console.log('focusOnObject: ', object, type)
  97263. let deferred = o.deferred || $.Deferred();
  97264. let target = new Vector3, //相机focus的位置
  97265. position = new Vector3, //相机最终位置
  97266. dis; //相机距离目标
  97267. duration = duration == void 0 ? 1200 : duration;
  97268. let camera = o.endCamera || o.camera || viewer.scene.getActiveCamera();
  97269. let cameraPos = camera.position.clone();
  97270. let boundSize;
  97271. /* if(camera.type == 'OrthographicCamera'){
  97272. return console.error('focusOnObject暂不支持OrthographicCamera。因情况复杂,请视情况使用splitScreenTool.viewportFitBound')
  97273. }
  97274. */
  97275. let getPosWithFullBound = (points, boundingBox, target, cameraPos )=>{//使boundingBox差不多占满屏幕时的相机到target的距离
  97276. // points 和 boundingBox 至少有一个
  97277. let scale;
  97278. if(o.dontChangeCamDir){
  97279. var inv = camera.matrixWorldInverse;
  97280. }else {
  97281. var cameraTemp = camera.clone();
  97282. let view = viewer.mainViewport.view.clone();
  97283. view.position.copy(cameraPos);
  97284. view.lookAt(target);
  97285. if(o.endPitch != void 0){
  97286. view.pitch = o.endPitch;
  97287. view.yaw = o.endYaw;
  97288. }
  97289. view.applyToCamera(cameraTemp);
  97290. //对镜头的bound
  97291. var inv = cameraTemp.matrixWorldInverse;
  97292. }
  97293. var bound = new Box3();
  97294. if(points){//使用points得到的bound更小 //如果points和boundingbox的差别较大,尤其使target和points中心不一致,那么points不一定会刚好在boundingbox内
  97295. points.forEach(e=>{
  97296. var p = e.clone().applyMatrix4(inv);
  97297. bound.expandByPoint(p);
  97298. });
  97299. scale = 1.3;
  97300. }else {
  97301. bound = boundingBox.applyMatrix4(inv);
  97302. scale = 1.0;//0.9;
  97303. }
  97304. boundSize = bound.getSize(new Vector3);
  97305. {
  97306. boundSize.x *= scale; //稍微放大一些,不然会靠到屏幕边缘
  97307. boundSize.y *= scale;
  97308. let min = 0.0001;
  97309. boundSize.x = Math.max(min, boundSize.x);
  97310. boundSize.y = Math.max(min, boundSize.y);
  97311. }
  97312. if(camera.type == 'OrthographicCamera'){
  97313. if(o.dontChangeCamDir) {
  97314. //必须在模型外部(如点击测量线时)
  97315. this.mainViewport.targetPlane.setFromNormalAndCoplanarPoint(this.mainViewport.view.direction, this.bound.center );
  97316. this.mainViewport.targetPlane.projectPoint(target, this.mainViewport.shiftTarget ); //得到target在中心面的投影
  97317. let pos = this.splitScreen.getPosOutOfModel(this.mainViewport, this.bound.size); //得到观察位置(shiftTarget投影到模型外部)
  97318. dis = pos.distanceTo(target);
  97319. }else {
  97320. dis = boundSize.length();
  97321. }
  97322. }else {
  97323. let aspect = boundSize.x / boundSize.y;
  97324. if(camera.aspect > aspect){//视野更宽则用bound的纵向来决定
  97325. dis = boundSize.y/2/ Math.tan(MathUtils$1.degToRad(camera.fov / 2)) + boundSize.z/2;
  97326. }else {
  97327. let hfov = cameraLight.getHFOVForCamera(camera, true);
  97328. dis = boundSize.x/2 / Math.tan(hfov / 2) + boundSize.z/2;
  97329. }
  97330. }
  97331. dis = Math.max(0.1,dis);
  97332. //三个顶点以上的由于measure的中心不等于bound的中心,所以点会超出bound外。 且由于视椎近大远小,即使是两个点的,bound居中后线看上去仍旧不居中.
  97333. //获得相机最佳位置
  97334. let dir;
  97335. if(o.dontChangeCamDir){
  97336. dir = viewer.mainViewport.view.direction.negate();
  97337. }else {
  97338. dir = new Vector3().subVectors(cameraPos, target).normalize();
  97339. }
  97340. if(o.dontLookUp && dir.z < 0){
  97341. dir.negate();
  97342. }
  97343. position.copy(target).add(dir.multiplyScalar(dis));
  97344. if(false){//打开以检查box
  97345. if(!this.boundBox){//调试
  97346. this.boundBox = new Mesh(new BoxGeometry(1,1,1,1));
  97347. this.boundBox.material.wireframe = true;
  97348. this.boundBox.up.set(0,0,1);
  97349. Potree.Utils.setObjectLayers(this.boundBox,'sceneObjects');
  97350. this.scene.scene.add(this.boundBox);
  97351. }
  97352. this.boundBox.position.copy(target);
  97353. this.boundBox.scale.copy(boundSize);
  97354. this.boundBox.lookAt(position);
  97355. }
  97356. return position
  97357. };
  97358. if(this.images360.flying){
  97359. let f = ()=>{
  97360. this.focusOnObject(object, type, duration, $.extend(o,{deferred}));
  97361. this.images360.removeEventListener('cameraMoveDone',f);
  97362. };
  97363. this.images360.addEventListener('cameraMoveDone',f);
  97364. return {promise: deferred.promise() }
  97365. }
  97366. if (type == 'measure') {
  97367. target.copy(object.getCenter());
  97368. if(!o.dontChangeCamDir){
  97369. //试试改变位置(方向),直视测量线。能避免倾斜角度造成的非常不居中、以及看不到面的情况
  97370. if(object.points.length>2/* && window.focusMeasureFaceToIt */){
  97371. let facePlane = object.facePlane || new Plane().setFromCoplanarPoints(...object.points.slice(0,3) );
  97372. let normal = facePlane.normal.clone();
  97373. let angle = this.scene.view.direction.angleTo(normal);
  97374. let minDiff = MathUtils$1.degToRad(60);
  97375. //console.log('angle',angle)
  97376. if(angle>minDiff && angle<Math.PI-minDiff){//当几乎正对时就不执行
  97377. if(angle<Math.PI/2){ //在背面
  97378. normal.negate();
  97379. }
  97380. let dir = new Vector3().subVectors(camera.position, target).normalize();
  97381. let newDir = new Vector3().addVectors(dir,normal);//两个角度的中间
  97382. cameraPos.copy(target.clone().add(newDir));
  97383. }
  97384. }else if(object.points.length == 2){ //线段
  97385. let lineDir = new Vector3().subVectors(object.points[0],object.points[1]).normalize();
  97386. let angle = this.scene.view.direction.angleTo(lineDir);
  97387. let maxDiff = Math.PI*0.25;// 45度
  97388. if(angle<maxDiff || angle>Math.PI-maxDiff){//当几乎正对时就不执行
  97389. if(angle>Math.PI/2){ //令dir和lineDir成钝角
  97390. lineDir.negate();
  97391. }
  97392. let dir = new Vector3().subVectors(camera.position, target).normalize();
  97393. let mid = new Vector3().addVectors(lineDir, dir).normalize(); //中间法向量(如果刚好dir和lineDir反向,那得到的为零向量,就不移动了,但一般不会酱紫吧)
  97394. let newDir = new Vector3().addVectors(dir, mid);
  97395. cameraPos.copy(target.clone().add(newDir));
  97396. }
  97397. }else {
  97398. console.error('measure 没有facePlane points点数还不为2?');
  97399. }
  97400. }
  97401. position = getPosWithFullBound(object.points, null, target, cameraPos );
  97402. if(this.mapViewer/* .attachedToViewer */){
  97403. //console.log('mapFocusOn: '+target.toArray())
  97404. const minBound = new Vector2(4,4);//针对垂直线,在地图上只有一个点
  97405. //原始的bound
  97406. let boundOri = new Box3();
  97407. object.points.forEach(e=>{
  97408. boundOri.expandByPoint(e);
  97409. });
  97410. let boundSizeOri = boundOri.getSize(new Vector3);
  97411. let boundSizeMap = boundSizeOri.clone().multiplyScalar(2);
  97412. boundSizeMap.x = Math.max(minBound.x, boundSizeMap.x );
  97413. boundSizeMap.y = Math.max(minBound.y, boundSizeMap.y );
  97414. this.mapViewer.moveTo(target.clone(), boundSizeMap, duration);
  97415. }
  97416. if(Potree.settings.displayMode == 'showPointCloud'){ //点云
  97417. let minDis = 0.3;
  97418. if(o.checkIntersect){
  97419. let checkIntersect = ( )=>{
  97420. let intersect = this.inputHandler.ifBlockedByIntersect({pos3d:position, cameraPos: target});// 不一定准确
  97421. if(intersect){
  97422. let blockCount = 0, unblockCount = 0, visi;
  97423. for(let i=0;i<object.points.length;i++){ //如果顶点超过一半不可见,就要更改位置
  97424. let p = object.points[i];
  97425. let blocked = this.inputHandler.ifBlockedByIntersect({pos3d:p, margin:0.3 , cameraPos:position, pickWindowSize:4});
  97426. if(blocked){
  97427. blockCount ++;
  97428. if(blockCount / object.points.length >= 0.5){
  97429. visi = false;
  97430. break
  97431. }
  97432. }else {
  97433. unblockCount ++;
  97434. if(unblockCount / object.points.length > 0.5){
  97435. visi = true;
  97436. break
  97437. }
  97438. }
  97439. }
  97440. if(visi == void 0){
  97441. visi = unblockCount / object.points.length > 0.5;
  97442. }
  97443. let shrink = ()=>{
  97444. let dir = new Vector3().subVectors(position, target).normalize().multiplyScalar(intersect.distance);
  97445. position.copy(target).add(dir);
  97446. console.log('checkIntersect newPos', position.clone() );
  97447. };
  97448. if(!visi){//更改位置距离target如果小于最小距离,需要反向。 否则直接缩短距离。
  97449. if(intersect.distance < minDis ){
  97450. console.log('检测到intersect 反向', intersect.distance );
  97451. let position1 = position.clone();
  97452. let dir = new Vector3().subVectors(position, target);
  97453. position.copy(target).sub(dir);
  97454. let intersect2 = this.inputHandler.ifBlockedByIntersect({pos3d: position, cameraPos:target});// 不一定准确
  97455. if(intersect2){
  97456. if(intersect2.distance < intersect.distance ){
  97457. position.copy(position1);//恢复
  97458. }
  97459. shrink();
  97460. }
  97461. }else {
  97462. shrink();
  97463. }
  97464. }
  97465. }
  97466. };
  97467. checkIntersect();
  97468. //多折线没有areaPlane 有时候会看向空白区域 - -
  97469. }
  97470. }else if(Potree.settings.displayMode == 'showPanos'){//全景 (比较难校准)
  97471. let target2, dir;
  97472. if( object.measureType.includes('MulDistance')){//因为该线不闭合,可能看向target的方向会没有线,所以换一个target
  97473. target2 = object.points[Math.round(object.points.length / 2) ];//直接看向中间点
  97474. dir = new Vector3().subVectors(target2, position).normalize();
  97475. }
  97476. let pano = viewer.images360.fitPanoTowardPoint({
  97477. /*point : target, //不使用目标点来判断是因为缺少measure角度的信息。比如虽然可以靠近线的中心,但是线朝向屏幕,那几乎就是一个点了。
  97478. //bestDistance : dis * 0.5, //乘以小数是为了尽量靠近
  97479. boundSphere: boundOri.getBoundingSphere(new THREE.Sphere), */
  97480. target,
  97481. dir,
  97482. point : position,
  97483. bestDistance : 0 ,
  97484. checkIntersect: true//o.checkIntersect
  97485. });
  97486. let result = {promise:deferred.promise() };
  97487. if(pano && pano.msg){
  97488. pano = pano.pano;
  97489. result.msg = pano.msg;
  97490. }
  97491. if(pano){
  97492. viewer.images360.flyToPano({pano, target : target2 || target, duration, deferred, dontMoveMap:true , basePanoSize:o.basePanoSize});//dontMoveMap不要移动map,否则flytopano会自动在map中focus到漫游点的位置,而非测量线了
  97493. if(viewer.images360.currentPano == pano){
  97494. let dis1 = viewer.images360.currentPano.position.distanceTo(target);
  97495. let dis2 = position.distanceTo(target);
  97496. //console.log('dis1 / dis2',dis1 / dis2, 'dis1-dis2', dis1-dis2)
  97497. return {msg: (dis1 / dis2 > 1.5 && dis1-dis2>10)? 'tooFar' : 'posNoChange', promise : deferred.promise() }
  97498. }
  97499. }
  97500. return result
  97501. //出现过到达位置后测量线标签闪烁的情况
  97502. }
  97503. } else if (type == 'tag' || type == 'point') {
  97504. //dimension = 1
  97505. target.copy(object.position);
  97506. let bestDistance = o.distance || 3;
  97507. if(!o.dontMoveMap && this.mapViewer){
  97508. //console.log('mapFocusOn: '+target.toArray())
  97509. this.mapViewer.moveTo(target.clone(), null, duration);
  97510. }
  97511. if(Potree.settings.displayMode == 'showPointCloud'){
  97512. if(o.dontChangePos){
  97513. position.copy(cameraPos);
  97514. }else {
  97515. dis = bestDistance;
  97516. let dir = o.direction ? o.direction.clone().negate() : this.mainViewport.view.direction.negate();// */new THREE.Vector3().subVectors(camera.position, target).normalize()
  97517. if(o.dontLookUp && dir.z<0) dir.z *= -1;
  97518. position.copy(target).add(dir.multiplyScalar(dis));
  97519. }
  97520. if(o.sameFloor){//需要在同一楼层
  97521. let atFloor = this.modules.SiteModel.pointInWhichEntity(target, 'floor');
  97522. if(atFloor){
  97523. let camFloor = this.modules.SiteModel.pointInWhichEntity(position, 'floor');
  97524. if(camFloor != atFloor){
  97525. let raycaster = new Raycaster();
  97526. let origin = target;
  97527. let dir = new Vector3().subVectors( position, target ).normalize();
  97528. raycaster.set(origin, dir);
  97529. let intersect = Potree.Utils.getIntersect(null, [atFloor.box], null, raycaster);
  97530. if(intersect){
  97531. let dis = MathUtils$1.clamp(intersect.distance - 0.2, camera.near, intersect.distance);
  97532. position.addVectors(origin, dir.multiplyScalar(dis));
  97533. console.log('移动到楼层');
  97534. }else {
  97535. console.error('?no intersect?');
  97536. }
  97537. }
  97538. }
  97539. }
  97540. if(o.checkIntersect){//识别被点云遮住的话
  97541. let intersect; //反向查找从target到相机的第一个intersect
  97542. intersect = this.inputHandler.ifBlockedByIntersect({pos3d:position, margin:0, cameraPos:target} /* {pos3d:target, margin: 0.2, cameraPos:position} */);
  97543. if(intersect){
  97544. position.copy(intersect.location);
  97545. console.log('移近');
  97546. }
  97547. }
  97548. }else if(Potree.settings.displayMode == 'showPanos'){
  97549. let pano = viewer.images360.fitPanoTowardPoint({
  97550. point : target,
  97551. dir : this.scene.view.direction, //尽量不改相机方向,避免镜头晃动
  97552. checkIntersect: o.checkIntersect, sameFloor:o.sameFloor,
  97553. bestDistance, maxDis: o.maxDis //越近越好,但不要太近,bestDistance左右差不多
  97554. });
  97555. let result = {promise:deferred.promise() };
  97556. if(pano && pano.msg){
  97557. pano = pano.pano;
  97558. result.msg = pano.msg;
  97559. }
  97560. pano && viewer.images360.flyToPano({pano, target, duration, deferred, dontMoveMap:true , basePanoSize:o.basePanoSize });
  97561. return result
  97562. }
  97563. }else if(object.boundingBox && type == 'boundingBox'){//使屏幕刚好看全boundingBox
  97564. target = object.boundingBox.getCenter(new Vector3);
  97565. if(o.dir){ //指定方向
  97566. cameraPos.copy(target).sub(o.dir);
  97567. }
  97568. position = getPosWithFullBound(object.points, object.boundingBox.clone(), target, cameraPos );
  97569. if(Potree.settings.displayMode == 'showPanos'){//全景 (比较难校准)
  97570. let pano = viewer.images360.fitPanoTowardPoint({
  97571. point : position,
  97572. bestDistance : 0 ,
  97573. });
  97574. let result = {promise:deferred.promise() };
  97575. if(pano && pano.msg){
  97576. pano = pano.pano;
  97577. result.msg = pano.msg;
  97578. }
  97579. pano && viewer.images360.flyToPano({pano, target, duration, deferred, dontMoveMap:true , basePanoSize:o.basePanoSize});//dontMoveMap不要移动map,否则flytopano会自动在map中focus到漫游点的位置,而非测量线了
  97580. if(!pano){
  97581. console.error('no pano');
  97582. }
  97583. return result
  97584. //出现过到达位置后测量线标签闪烁的情况
  97585. }else {
  97586. }
  97587. }
  97588. if(o.startCamera && o.endCamera){
  97589. viewer.scene.view.tranCamera(this.mainViewport, { endPosition:position, target ,
  97590. boundSize,
  97591. callback:()=>{
  97592. //console.log('focusOnObjectSuccess: '+object.name, type)
  97593. deferred.resolve();
  97594. }, startCamera:o.startCamera, endCamera:o.endCamera, midCamera:this.scene.cameraBasic,
  97595. endYaw:o.endYaw, endPitch:o.endPitch
  97596. }, duration);
  97597. }else if(camera.type == "OrthographicCamera"){
  97598. viewer.scene.view.moveOrthoCamera(this.mainViewport, { endPosition:position,
  97599. target: o.dontChangeCamDir?null:target,
  97600. boundSize,
  97601. endYaw:o.endYaw, endPitch:o.endPitch,
  97602. callback:()=>{
  97603. //console.log('focusOnObjectSuccess: '+object.name, type)
  97604. deferred.resolve();
  97605. },
  97606. }, duration);
  97607. }else {
  97608. viewer.scene.view.setView({position, target, duration,
  97609. endYaw:o.endYaw, endPitch:o.endPitch,
  97610. callback:()=>{
  97611. //console.log('focusOnObjectSuccess: '+object.name, type)
  97612. deferred.resolve();
  97613. }
  97614. }
  97615. );}
  97616. this.dispatchEvent({type:'focusOnObject', CamTarget:target, position}); //给controls发送信息
  97617. return {promise:deferred.promise()}
  97618. }
  97619. flyToDataset(o={}){
  97620. var pointcloud;
  97621. if(o instanceof Object3D) pointcloud = o;
  97622. else if(o.pointcloud) pointcloud = o.pointcloud;
  97623. else pointcloud = this.scene.pointclouds.find(p => p.dataset_id == o.id);
  97624. let duration = o.duration == void 0 ? 1000 : o.duration;
  97625. var center = pointcloud.bound.getCenter(new Vector3);
  97626. let position;
  97627. let getPano = ()=>{//获取离中心最近的pano
  97628. let request = [];
  97629. let rank = [
  97630. Images360.scoreFunctions.distanceSquared({position: center})
  97631. ];
  97632. let r = Common$1.sortByScore(pointcloud.panos, request, rank);
  97633. if(r.length){
  97634. return r[0].item
  97635. }
  97636. };
  97637. if(Potree.settings.displayMode == 'showPanos'){
  97638. let pano = getPano();
  97639. if(pano){
  97640. if(pano == this.images360.currentPano) return 'posNoChange'
  97641. this.images360.flyToPano({
  97642. pano
  97643. });
  97644. }else return false
  97645. }else {
  97646. let target;
  97647. position = center;
  97648. if(pointcloud.panosBound){
  97649. let panosCenter = pointcloud.panosBound.center; //pano集中的地方,也就是真正有点云的地方
  97650. position = panosCenter.clone();
  97651. /* let ratio = 0.2
  97652. position.z = center.z * ratio + panosCenter.z * (1-ratio) //因为panos一般比较低,为了不让相机朝下时看不到点云,加一丢丢中心高度
  97653. */
  97654. let pano = getPano();
  97655. if(pano){
  97656. target = pano.position; //针对像隧道一样的场景, 中心点还是panosCenter都在没有点云的地方,所以还是看向其中一个漫游点好。
  97657. position.z = target.z; //水平, 避免朝上或朝下
  97658. }
  97659. }
  97660. if(this.modules.Clip.editing){
  97661. position.z = center.z; //剪裁时在中心高度,因为以点云为重点
  97662. this.modules.Clip.bus.dispatchEvent({type:'flyToPos', position, duration });
  97663. }else {
  97664. if(math.closeTo(position, this.images360.position)) return 'posNoChange'
  97665. viewer.scene.view.setView({position, target, duration });
  97666. }
  97667. o.dontMoveMap || viewer.mapViewer.fitToPointcloud(pointcloud, duration);
  97668. }
  97669. return true
  97670. }
  97671. addTimeMark(name, type){
  97672. let record = Potree.timeCollect[name];
  97673. let needRecord = record && record.start && record.measures.length < record.minCount;
  97674. if(needRecord || Potree.measureTimings){
  97675. performance.mark(name+"-"+type);
  97676. if(type == 'end'){
  97677. let measure = performance.measure(name,name+"-start",name+"-end");
  97678. if(needRecord){
  97679. record.measures.push( measure.duration );
  97680. record.sum += measure.duration;
  97681. record.ave = record.sum / record.measures.length;
  97682. record.measures.sort( (a, b) => a - b );
  97683. record.median = record.measures[parseInt(record.measures.length / 2)];
  97684. }
  97685. }
  97686. }
  97687. }
  97688. addFakeMeasure(name,duration){//把一些count当做duration来统计
  97689. if(!Potree.measureTimings)return
  97690. if(!this.fakeMeasure[name]){
  97691. this.fakeMeasure[name] = [];
  97692. }
  97693. let object = {
  97694. name, duration
  97695. };
  97696. this.fakeMeasure[name].push(object);
  97697. }
  97698. resolveTimings(timestamp,log){//打印用时。 注:performance手机的精度只到整数位 。 sidebar中监听update时有高cpu的函数所以不要用demo测
  97699. if(!this.toggle){
  97700. this.toggle = timestamp;
  97701. }
  97702. let duration = timestamp - this.toggle;
  97703. if(duration > 1000.0){
  97704. if(log){
  97705. let measures = performance.getEntriesByType("measure");
  97706. for(let i in this.fakeMeasure){
  97707. measures.push(...this.fakeMeasure[i]);
  97708. }
  97709. let names = new Set();
  97710. for(let measure of measures){
  97711. names.add(measure.name);
  97712. }
  97713. let groups = new Map();
  97714. for(let name of names){
  97715. groups.set(name, {
  97716. measures: [],
  97717. sum: 0,
  97718. n: 0,
  97719. min: Infinity,
  97720. max: -Infinity
  97721. });
  97722. }
  97723. for(let measure of measures){
  97724. let group = groups.get(measure.name);
  97725. group.measures.push(measure);
  97726. group.sum += measure.duration;
  97727. group.n++;
  97728. group.min = Math.min(group.min, measure.duration);
  97729. group.max = Math.max(group.max, measure.duration);
  97730. }
  97731. /* let glQueries = Potree.resolveQueries(this.renderer.getContext()); // resolveQueries 无
  97732. for(let [key, value] of glQueries){
  97733. let group = {
  97734. measures: value.map(v => {return {duration: v}}),
  97735. sum: value.reduce( (a, i) => a + i, 0),
  97736. n: value.length,
  97737. min: Math.min(...value),
  97738. max: Math.max(...value)
  97739. };
  97740. let groupname = `[tq] ${key}`;
  97741. groups.set(groupname, group);
  97742. names.add(groupname);
  97743. } */
  97744. for(let [name, group] of groups){
  97745. group.mean = group.sum / group.n;
  97746. /* group.measures.sort( (a, b) => a.duration - b.duration );
  97747. if(group.n === 1){
  97748. group.median = group.measures[0].duration;
  97749. }else if(group.n > 1){
  97750. group.median = group.measures[parseInt(group.n / 2)].duration;
  97751. }
  97752. */
  97753. let measures = group.measures.slice();
  97754. measures.sort( (a, b) => a.duration - b.duration );
  97755. if(group.n === 1){
  97756. group.median = measures[0].duration;
  97757. }else if(group.n > 1){
  97758. group.median = measures[parseInt(group.n / 2)].duration;
  97759. }
  97760. }
  97761. let cn = Array.from(names).reduce( (a, i) => Math.max(a, i.length), 0) + 5;
  97762. let cmin = 6;
  97763. let cmed = 6;
  97764. let cmax = 6;
  97765. let csam = 4;
  97766. let message = ` ${"NAME".padEnd(cn)} |`
  97767. + ` ${"MIN".padStart(cmin)} |`
  97768. + ` ${"MEDIAN".padStart(cmed)} |`
  97769. + ` ${"MAX".padStart(cmax)} |`
  97770. + ` ${"AVE".padStart(cmax)} |`
  97771. + ` ${"SAMPLES".padStart(csam)} \n`;
  97772. message += ` ${"-".repeat(message.length) }\n`;
  97773. names = Array.from(names).sort();
  97774. for(let name of names){
  97775. let group = groups.get(name);
  97776. let min = group.min.toFixed(3);
  97777. let median = group.median.toFixed(3);
  97778. let max = group.max.toFixed(3);
  97779. let ave = group.mean.toFixed(3); //add
  97780. let n = group.n;
  97781. message += ` ${name.padEnd(cn)} |`
  97782. + ` ${min.padStart(cmin)} |`
  97783. + ` ${median.padStart(cmed)} |`
  97784. + ` ${max.padStart(cmax)} |`
  97785. + ` ${ave.padStart(cmax)} |`
  97786. + ` ${n.toString().padStart(csam)}\n`;
  97787. }
  97788. message += `\n`;
  97789. console.log(message);
  97790. }
  97791. this.fakeMeasure = {}; //clear
  97792. performance.clearMarks();
  97793. performance.clearMeasures();
  97794. this.toggle = timestamp;
  97795. }
  97796. //注意,console.log本身用时挺高,降4倍时可能占用0.5毫秒,所以不能每帧都打印
  97797. }
  97798. loop(timestamp){
  97799. //let startTime = performance.now()
  97800. //console.log('间隔:' ,parseInt((startTime - this.lastEndTime)*100 )/100)
  97801. if(performance.getEntriesByName("loopWaitNext-start").length)viewer.addTimeMark('loopWaitNext','end');
  97802. if(this.stats){
  97803. this.stats.begin();
  97804. }
  97805. performance.mark('loop-start') ;// 无论有没有reportTimings都要获取,因为getBestCound需要
  97806. this.dispatchEvent('loopStart');
  97807. this.shelterCount = {byTex:0, byCloud:0, maxByTex: 100, maxByCloud:0 }; //清空 因ifPointBlockedByIntersect可能在任何时候触发,所以需要一开始就定义这个,且每次计算最大可计算次数太麻烦了就定义一个吧。
  97808. let deltaTime = this.clock.getDelta();
  97809. this.update(deltaTime, timestamp);
  97810. this.magnifier.render();
  97811. this.render();
  97812. this.objs.children.forEach(e=>{
  97813. if(e.fileType == '3dTiles'){
  97814. e.runtime.update(deltaTime, this.renderer, this.mainViewport.camera);
  97815. }
  97816. });
  97817. // let vrActive = viewer.renderer.xr.isPresenting;
  97818. // if(vrActive){
  97819. // this.update(this.clock.getDelta(), timestamp);
  97820. // this.render();
  97821. // }else{
  97822. // this.update(this.clock.getDelta(), timestamp);
  97823. // this.render();
  97824. // }
  97825. Potree.framenumber++;
  97826. //-------------
  97827. this.images360.update();
  97828. this.computeShelter();
  97829. //-------------
  97830. if(this.stats){
  97831. this.stats.end();
  97832. }
  97833. viewer.addTimeMark('loop','end');
  97834. viewer.addTimeMark('loopWaitNext','start');
  97835. this.resolveTimings(timestamp, Potree.measureTimings);
  97836. //Potree.measureTimings = 1
  97837. }
  97838. postError(content, params = {}){
  97839. let message = this.postMessage(content, params);
  97840. message.element.addClass("potree_message_error");
  97841. return message;
  97842. }
  97843. postMessage(content, params = {}){
  97844. let message = new Message(content);
  97845. let animationDuration = 100;
  97846. message.element.css("display", "none");
  97847. message.elClose.click( () => {
  97848. message.element.slideToggle(animationDuration);
  97849. let index = this.messages.indexOf(message);
  97850. if(index >= 0){
  97851. this.messages.splice(index, 1);
  97852. }
  97853. });
  97854. this.elMessages.prepend(message.element);
  97855. message.element.slideToggle(animationDuration);
  97856. this.messages.push(message);
  97857. if(params.duration !== undefined){
  97858. let fadeDuration = 500;
  97859. let slideOutDuration = 200;
  97860. setTimeout(() => {
  97861. message.element.animate({
  97862. opacity: 0
  97863. }, fadeDuration);
  97864. message.element.slideToggle(slideOutDuration);
  97865. }, params.duration);
  97866. }
  97867. return message;
  97868. }
  97869. getBoundingBox (pointclouds) {
  97870. //可以直接返回viewer.bound
  97871. if(!this.bound){
  97872. this.updateModelBound();
  97873. }
  97874. return this.bound.boundingBox.clone()//this.scene.getBoundingBox(pointclouds);
  97875. };
  97876. updateModelBound(reason){
  97877. this.boundNeedUpdate = false;
  97878. this.bound = Utils.computePointcloudsBound(this.scene.pointclouds.filter(pointcloud=> //只求可见
  97879. pointcloud.visible || pointcloud.unvisibleReasons && pointcloud.unvisibleReasons.length == 1 && pointcloud.unvisibleReasons[0].reason == 'displayMode'
  97880. ));
  97881. if(Potree.settings.boundAddObjs){//加上obj的bound
  97882. this.objs.children.forEach(e=>{
  97883. this.bound.boundingBox.union(e.boundingBox.clone().applyMatrix4(e.matrixWorld));
  97884. });
  97885. this.bound.boundingBox.getSize(this.bound.boundSize);
  97886. this.bound.boundingBox.getCenter(this.bound.center);
  97887. }
  97888. viewer.farWhenShowPano = this.bound.boundSize.length() * 10;//全景漫游时要能看到整个skybox 原本*2的但对于距离特远的数据集需要乘大一些否则会黑面
  97889. /* let boundPlane = new THREE.Box3()
  97890. boundPlane.expandByPoint(this.bound.boundingBox.min.clone())//最低高度为bound的最低
  97891. boundPlane.expandByPoint(this.bound.boundingBox.max.clone().setZ(this.bound.center.z))//最高高度为bound的中心高度
  97892. FirstPersonControls.boundPlane = boundPlane */
  97893. //FirstPersonControls.standardSpeed = THREE.Math.clamp( Math.sqrt(this.bound.boundSize.length() )/ 100 , 0.02,0.5); //在这个boundPlane中的速度
  97894. viewer.scene.pointclouds.forEach(e=>{//海拔范围
  97895. e.material.heightMin = this.bound.boundingBox.min.z;
  97896. e.material.heightMax = this.bound.boundingBox.max.z;
  97897. });
  97898. this.dispatchEvent({type:'updateModelBound'});
  97899. }
  97900. waitForLoad(object, isLoadedCallback){//等待加载时显示loading。主要是贴图
  97901. this.waitQueue.push({
  97902. object,
  97903. isLoadedCallback,
  97904. });
  97905. 1 === this.waitQueue.length && this.dispatchEvent({type:"loading", show:true});
  97906. }
  97907. ifAllLoaded( ){
  97908. if(this.waitQueue.length>0){
  97909. this.waitQueue = this.waitQueue.filter(function(e) {
  97910. return !e.isLoadedCallback()
  97911. });
  97912. }
  97913. 0 === this.waitQueue.length && this.dispatchEvent({type:"loading", show:false});
  97914. }
  97915. cancelLoad(object){//add 突然出现还没加载完就被deactivateTiledPano但还在loading的情况,所以加了这个
  97916. this.waitQueue = this.waitQueue.filter(function(e) {
  97917. return e.object != object
  97918. });
  97919. this.ifAllLoaded();
  97920. }
  97921. setView(o={}){
  97922. let callback = ()=>{
  97923. if(o.displayMode){
  97924. Potree.settings.displayMode = o.displayMode;
  97925. }
  97926. o.callback && o.callback();
  97927. };
  97928. if(o.pano != void 0){//pano 权重高于 position
  97929. this.images360.flyToPano(o);
  97930. }else {
  97931. this.scene.view.setView($.extend({},o, {callback}));
  97932. }
  97933. }
  97934. //设置点云为标准模式
  97935. setPointStandardMat(state, pointDensity, fitPointsize){
  97936. console.log('setPointStandardMat',state);
  97937. if(state){
  97938. if(this.pointStatesBefore){
  97939. return console.error('已设置过pointStatesBefore!')
  97940. }
  97941. this.pointStatesBefore = {
  97942. opacity : new Map(),
  97943. size: new Map(),
  97944. density:Potree.settings.pointDensity,
  97945. useEDL:this.getEDLEnabled(),
  97946. shape: viewer.scene.pointclouds[0].material.shape
  97947. };
  97948. viewer.scene.pointclouds.forEach(e=>{
  97949. this.pointStatesBefore.opacity.set(e, e.temp.pointOpacity); //因为更改pointDensity时会自动变opacity,所以这项最先获取
  97950. this.pointStatesBefore.colorType = e.material.activeAttributeName;
  97951. fitPointsize && this.pointStatesBefore.size.set(e,e.temp.pointSize); //这项不一定有用,因为会被后期覆盖
  97952. });
  97953. if(pointDensity)Potree.settings.pointDensity = pointDensity; //万一之后切换到全景模式怎么办
  97954. if(fitPointsize)Potree.settings.sizeFitToLevel = true;
  97955. viewer.scene.pointclouds.forEach(e=>{
  97956. e.material.activeAttributeName = 'rgba';
  97957. e.material.shape = Potree.PointShape['SQUARE'];
  97958. fitPointsize && e.changePointSize(Potree.config.material.realPointSize, true);
  97959. e.changePointOpacity(1);
  97960. });
  97961. viewer.setEDLEnabled(false);
  97962. }else {
  97963. if(!this.pointStatesBefore){
  97964. return console.error('未设置过pointStatesBefore!')
  97965. }
  97966. Potree.settings.sizeFitToLevel = false;
  97967. if(pointDensity)Potree.settings.pointDensity = this.pointStatesBefore.pointDensity;
  97968. viewer.scene.pointclouds.forEach(e=>{
  97969. e.material.activeAttributeName = this.pointStatesBefore.colorType;
  97970. e.changePointOpacity(this.pointStatesBefore.opacity.get(e));
  97971. e.material.shape = this.pointStatesBefore.shape;
  97972. let size = this.pointStatesBefore.size.get(e);
  97973. if(size) e.changePointSize(size);
  97974. });
  97975. viewer.setEDLEnabled(this.pointStatesBefore.useEDL);
  97976. this.pointStatesBefore = null;
  97977. }
  97978. }
  97979. //调试时显示transformControl来调节object
  97980. transformObject(object){
  97981. let seleted = viewer.inputHandler.selection[0];
  97982. if(!object){//取消
  97983. seleted && viewer.inputHandler.toggleSelection(seleted);
  97984. return
  97985. }
  97986. if(seleted && seleted != object){//要更换,先取消
  97987. this.transformObject(null);
  97988. }
  97989. if(!object.boundingBox){
  97990. object.boundingBox = new Box3(); //任意大小 只是为了显示黄色外框
  97991. //??? computeBoundingBox
  97992. }
  97993. if(!viewer.inputHandler.selection.includes(object)){
  97994. viewer.inputHandler.toggleSelection(object);
  97995. }
  97996. }
  97997. pointInWhichPointcloud(pos){//选择最接近中心的那个 使用boundSphere
  97998. let result = Common$1.sortByScore(this.scene.pointclouds,[],[
  97999. (pointcloud)=>{
  98000. var size = pointcloud.pcoGeometry.tightBoundingBox.getSize(new Vector3);
  98001. var center = pointcloud.bound.getCenter(new Vector3);
  98002. var length = size.length() / 2;
  98003. var dis = pos.distanceTo(center);
  98004. return length / dis //到数据集中心的距离占数据集大小越小越好
  98005. }
  98006. ]);
  98007. //若要求更准确的话,可以使用ifContainsPoint判断一下是否在bound中
  98008. let r = result[0];
  98009. return r && r.score > 1 ? result[0].item : null
  98010. }
  98011. /* addObjectTest1(){//加水管
  98012. if(Potree.settings.number == 't-8KbK1JjubE'){
  98013. let boundingBox = new THREE.Box3()
  98014. boundingBox.min.set(-1,-1,-1); boundingBox.max.set(1,1,1)
  98015. let radius = 0.08;
  98016. let radialSegments = 5
  98017. let radSegments = Math.PI*2 / radialSegments
  98018. var circlePts = [];//横截面
  98019. for(let i=0;i<radialSegments;i++){
  98020. let angle = radSegments * i;
  98021. circlePts.push(new THREE.Vector2(radius * Math.cos(angle), radius * Math.sin(angle) ))
  98022. }
  98023. var count = 0
  98024. var addMesh = (color, path, height)=>{//height:在path之上的高度,负数代表在path之下
  98025. var name = 'cylinder'+count
  98026. var mat = new THREE.MeshStandardMaterial({color, depthTest:false, roughness:0.4,metalness:0.5}) 
  98027. let linePath = path.map(e=>new THREE.Vector3().copy(e).setZ(e.z+height))
  98028. let geo = MeshDraw.getExtrudeGeo( circlePts, null,{ extrudePath:linePath, tension:0.2} )
  98029. var mesh = new THREE.Mesh(geo,mat);
  98030. mesh.name = name
  98031. window[name] = mesh
  98032. mesh.boundingBox = boundingBox
  98033. mesh.matrixAutoUpdate = false
  98034. mesh.matrix.copy(viewer.scene.pointclouds[0].transformMatrix)
  98035. mesh.matrixWorldNeedsUpdate = true
  98036. this.scene.scene.add(mesh);
  98037. count ++
  98038. }
  98039. let linePath, height
  98040. //地上管子 黄色
  98041. linePath = [{"x":-109.83,"y":-68.33,"z":-7.52},{"x":-95.17,"y":-59.3,"z":-7.38}, {"x":-38.75,"y":-24.01,"z":-6.01},{"x":0.5,"y":0.19,"z":-3.89},{"x":39.29,"y":24.41,"z":-1.31}
  98042. ,{"x":43.58,"y":27.7,"z":-0.97},{"x":40.22,"y":35.37,"z":-0.67}// 拐弯向右
  98043. , {"x":39.18,"y":36.71,"z":0.35},{"x":38.69,"y":36.04,"z":18.04} // 拐弯向上
  98044. ]
  98045. height = radius + 0.05;
  98046. addMesh('#b86', linePath, height)
  98047. //地下管子 藍色
  98048. linePath = [{"x":-108.24,"y":-70.61,"z":-7.52}, {"x":-57.8,"y":-39.31,"z":-6.72},{"x":-18.8,"y":-15.35,"z":-5.01},{"x":55.87,"y":31.67,"z":-0.04},{"x":110.53,"y":66.48,"z":5.14}
  98049. ]
  98050. height = -0.5;
  98051. addMesh('#48a', linePath, height)
  98052. }
  98053. }
  98054. */
  98055. /* createRoomEv(){
  98056. const environment = new RoomEnvironment();
  98057. const pmremGenerator = new THREE.PMREMGenerator( this.renderer );
  98058. }
  98059. */
  98060. async loadModel(fileInfo, done, onProgress_, onError){
  98061. console.log('开始加载', Common$1.getNameFromURL(fileInfo.name) );
  98062. let boundingBox = new Box3();
  98063. /* if(!Potree.settings.boundAddObjs){
  98064. boundingBox.min.set(-0.5,-0.5,-0.5); boundingBox.max.set(0.5,0.5,0.5)
  98065. } */
  98066. if(fileInfo.objurl){
  98067. fileInfo.url = fileInfo.objurl, fileInfo.fileType = 'obj'; //兼容最早的
  98068. }
  98069. if(fileInfo.url instanceof Array){
  98070. if(fileInfo.url.length == 1){
  98071. fileInfo.url = fileInfo.url[0];
  98072. }else {
  98073. fileInfo.loadedCount = 0;
  98074. fileInfo.modelGroup = new Object3D; //parentGroup.name = fileInfo.title
  98075. fileInfo.url.forEach((url,i)=>{
  98076. let fileInfoS = Common$1.CloneObject(fileInfo);
  98077. fileInfoS.url = url;
  98078. fileInfoS.name = 'child-'+i;
  98079. fileInfoS.parentInfo = fileInfo;
  98080. this.loadModel(fileInfoS, done, onProgress_, onError);
  98081. });
  98082. return
  98083. }
  98084. }
  98085. fileInfo.url = Common$1.dealURL(fileInfo.url); //去除'+'
  98086. fileInfo.loadStartTime = Date.now();
  98087. //let fileType = fileInfo.tilesUrl ? '3dTiles' : fileInfo.objurl ? 'obj' : 'glb'
  98088. let loadDone = (object, fileInfo_ /* , total, url */)=>{
  98089. fileInfo_ = fileInfo_ || fileInfo;
  98090. if(fileInfo_.parentInfo){
  98091. object.name = fileInfo_.name;
  98092. fileInfo_.parentInfo.loadedCount ++;
  98093. fileInfo_.parentInfo.modelGroup.add(object);
  98094. if(fileInfo_.parentInfo.loadedCount == fileInfo_.parentInfo.url.length){
  98095. return loadDone(fileInfo_.parentInfo.modelGroup, fileInfo_.parentInfo)
  98096. }else {
  98097. return
  98098. }
  98099. }
  98100. object.name = fileInfo_.name != void 0 ? fileInfo_.name : fileInfo_.type;
  98101. object.fileType = fileInfo_.fileType;
  98102. object.boundingBox = boundingBox; //未乘上matrixWorld的本地boundingBox
  98103. //object.scale.set(1,1,1);//先获取原始的大小时的boundingBox
  98104. object.opacity = 1; //初始化 记录
  98105. object.updateMatrixWorld();
  98106. if(fileInfo_.id != void 0)object.dataset_id = fileInfo_.id;
  98107. fileInfo_.loadCostTime = Date.now() - fileInfo_.loadStartTime;
  98108. /* let weight = Math.round((total / 1024 / 1024) * 100) / 100;*/
  98109. console.log( '加载完毕:', Common$1.getNameFromURL(fileInfo_.name), '耗时(ms)', fileInfo_.loadCostTime, /* 模型数据量:' + weight + 'M' */);
  98110. if(fileInfo_.fileType == '3dTiles'){
  98111. let tileset = object.runtime.getTileset();
  98112. //TileHeader: tileset.root
  98113. //参见另一个工程 TileRenderer.js preprocessNode
  98114. //let boundingVolume = tileset.root.boundingVolume //这个坐标位置几万…… let data = boundingVolume.halfAxes //但这个似乎是premultiply( transform );过后的,可能需还原下
  98115. let json = tileset.tileset;
  98116. let box = json.root.boundingVolume.box;
  98117. let center = new Vector3(box[0],box[1],box[2]);
  98118. let boundSize = new Vector3( );
  98119. // get the extents of the bounds in each axis
  98120. let vecX = new Vector3( box[ 3 ], box[ 4 ], box[ 5 ] );
  98121. let vecY = new Vector3( box[ 6 ], box[ 7 ], box[ 8 ] );
  98122. let vecZ = new Vector3( box[ 9 ], box[ 10 ], box[ 11 ] );
  98123. const scaleX = vecX.length();
  98124. const scaleY = vecY.length();
  98125. const scaleZ = vecZ.length();
  98126. /* boundingBox.expandByPoint(center);
  98127. boundingBox.expandByVector(new THREE.Vector3(scaleX,scaleY,scaleZ)) */
  98128. boundingBox.min.set( - scaleX, - scaleY, - scaleZ );
  98129. boundingBox.max.set( scaleX, scaleY, scaleZ );
  98130. //中心点居然没用。可能是漏用了什么信息,也许这和LVBADUI_qp是散的有关。
  98131. console.log('3d tiles json',json);
  98132. json.root.refine = 'ADD';
  98133. json.refine = 'ADD';
  98134. }else {
  98135. Potree.Utils.setObjectLayers(object,'model');
  98136. object.traverse( ( child )=>{
  98137. if ( child instanceof Mesh || child instanceof Points ) {
  98138. child.renderOrder = Potree.config.renderOrders.model;
  98139. if(Potree.settings.boundAddObjs){
  98140. child.geometry.computeBoundingBox();
  98141. //console.log(child.matrixWorld.clone())
  98142. boundingBox.union(child.geometry.boundingBox.clone().applyMatrix4(child.matrixWorld)); //但感觉如果最外层object大小不为1,要还原下scale再乘
  98143. }//获取在scale为1时,表现出的大小
  98144. //Potree.Utils.makeTexDontResize(child.material.map)
  98145. //console.log(child.name, 'roughness',child.material.roughness,'metalness',child.material.metalness)
  98146. /* //暂时用这种材质:
  98147. if(fileInfo.unlit && (!(child.material instanceof THREE.MeshBasicMaterial) || fileType == 'glb')){
  98148. //let material = new THREE.MeshBasicMaterial({map:child.material.map})
  98149. let material = new BasicMaterial({map : child.material.map}) //很奇怪glb的图会使原本的MeshBasicMaterial 会偏暗,所以自己重新写
  98150. //child.material.dispose()
  98151. child.material = material
  98152. } */
  98153. if(child.material instanceof MeshStandardMaterial){
  98154. child.material.roughness = 0.6;
  98155. child.material.metalness = 0.3;
  98156. }
  98157. }
  98158. } );
  98159. }
  98160. this.objs.add(object);
  98161. if(fileInfo_.transform){
  98162. let setTransfrom = (name)=>{
  98163. let value = fileInfo_.transform[name];
  98164. if(!value)return
  98165. if(value instanceof Array){
  98166. object[name].fromArray(value);
  98167. }else {
  98168. object[name].copy(value);
  98169. }
  98170. };
  98171. setTransfrom('position');
  98172. setTransfrom('rotation');
  98173. setTransfrom('scale');
  98174. }
  98175. if(fileInfo_.moveWithPointcloud){
  98176. object.updateMatrix();
  98177. object.matrixAutoUpdate = false;
  98178. object.matrix.premultiply(viewer.scene.pointclouds[0].transformMatrix); //默认跟随第一个数据集
  98179. object.matrixWorldNeedsUpdate = true;
  98180. }
  98181. done && done(object);
  98182. };
  98183. let onProgress = function ( xhr ) {
  98184. if ( xhr.lengthComputable ) {
  98185. let percentComplete = xhr.loaded / xhr.total * 100;
  98186. //console.log( Math.round(percentComplete, 2) + '% downloaded' );
  98187. onProgress_ && onProgress_(percentComplete);
  98188. }
  98189. };
  98190. if(fileInfo.fileType == 'obj'){ //暂时不支持数组
  98191. loaders.mtlLoader.load( fileInfo.mtlurl , (materials)=>{
  98192. materials.preload();
  98193. loaders.objLoader.setMaterials( materials ).load(fileInfo.objurl, (object, total)=>{
  98194. loadDone(object/* , total, fileInfo.objurl */);
  98195. });
  98196. } , onProgress, onError );
  98197. }else if(fileInfo.fileType == 'glb'){
  98198. loaders.glbLoader.unlitMat = true;//!!fileInfo.unlit
  98199. loaders.glbLoader.load(fileInfo.url, ( gltf, total )=>{
  98200. //console.log('loadGLTF', gltf)
  98201. loadDone(gltf.scene/* , total, fileInfo.url */);
  98202. }, onProgress, onError);
  98203. }else if(fileInfo.fileType == 'ply'){
  98204. loaders.plyLoader.load( fileInfo.url, (geometry) => {
  98205. let object;
  98206. console.log('ply加载完毕', geometry);
  98207. if(!geometry.index){//点云
  98208. object = new Points(geometry, new PointsMaterial({vertexColors:true, size:0.02}));
  98209. //141M的点云,intersect费时300ms以上
  98210. }else {//mesh
  98211. object = new Mesh(geometry);
  98212. }
  98213. loadDone(object);
  98214. });
  98215. }else if(fileInfo.fileType == '3dTiles'){
  98216. let result = await Loader3DTiles.load({
  98217. url: fileInfo.url,
  98218. gltfLoader : loaders.glbLoader,
  98219. //renderer: SceneRenderer.renderer
  98220. options: {
  98221. //dracoDecoderPath: '../utils/loaders/DRACOLoader/draco',
  98222. //basisTranscoderPath: '../utils/loaders/KTX2Loader/basis',
  98223. maximumScreenSpaceError: 50,
  98224. maxDepth: 100,
  98225. maximumMemoryUsage: 700, //缓存大小。 若太小,密集的tile反复加载很卡
  98226. //debug:true,
  98227. parent: this.scene.scene
  98228. },
  98229. });
  98230. console.log(result);
  98231. result.model.runtime = result.runtime;
  98232. loadDone(result.model/* , null, fileInfo.url */);
  98233. let loaded = false;
  98234. let tileset = result.runtime.getTileset();
  98235. tileset.addEventListener('endTileLoading', function (data) {//Tileset3D
  98236. if (data.loadingCount == 0 && !loaded) {
  98237. loaded = true;
  98238. console.log('loaded!!!!!!!!!!!!!');
  98239. }
  98240. });
  98241. tileset.addEventListener('tileLoaded',(e)=>{ //每一个tile加载完要更改透明度
  98242. let opacity = result.model.opacity;
  98243. MergeEditor.changeOpacity(e.tileContent,opacity);
  98244. });
  98245. }
  98246. }
  98247. removeObj(object){
  98248. this.objs.remove(object);
  98249. if(Potree.settings.boundAddObjs){
  98250. this.updateModelBound();
  98251. }
  98252. }
  98253. addFire(){
  98254. if(Potree.settings.number == 't-CwfhfqJ'){
  98255. let position = Potree.Utils.datasetPosTransform({
  98256. pointcloud:viewer.scene.pointclouds[0],
  98257. position: new Vector3(4.4318,-0.580291847759, -0.78),
  98258. fromDataset:true
  98259. });
  98260. viewer.modules.ParticleEditor.addParticle( {
  98261. type:'fire',
  98262. positions:[position],
  98263. radius:0.42,
  98264. height:10,
  98265. });
  98266. viewer.modules.ParticleEditor.addParticle( {
  98267. type:'smoke',
  98268. positions: [ new Vector3().addVectors(position,new Vector3(0,0,0.3))],
  98269. positionStyle : 'sphere' ,
  98270. positionRadius : 0.3,
  98271. sizeTween: [[0, 0.3, 0.9, 1], [0.05, 0.1, 1, 0.8]],
  98272. opacityBase : 0.2,
  98273. opacityTween :[ [0, 0.3, 0.7, 0.95, 1], [0, 0.2, 1 , 0.1, 0] ],
  98274. velocityBase : new Vector3( 0, 0, 1),
  98275. velocitySpread : new Vector3( 0.2, 0.2, -0.3),
  98276. accelerationBase : 0.2,
  98277. accelerationSpread : 0.7,
  98278. radius:0,
  98279. //particlesPerSecond : 30,
  98280. particleDeathAge : 3.0,
  98281. });
  98282. viewer.modules.ParticleEditor.addParticle( {
  98283. type:'explode',
  98284. name:'fire splash',
  98285. position: new Vector3().addVectors(position,new Vector3(0,0,0.3)),
  98286. size: 0.1,
  98287. sizeRange: 0.3,
  98288. sizeTween:[[0, 0.05, 0.3, 0.45], [0, 0.02, 0.1, 0.05] ],
  98289. opacityTween: [[0, 0.05, 0.3, 0.45], [1, 1, 0.5, 0]] ,
  98290. speed : 1, //sphere
  98291. speedRange : 4,
  98292. radius: 0.1,
  98293. acceleration : 0.3,
  98294. accelerationRange : 1,
  98295. particleSpaceTime:0,
  98296. strength:4,
  98297. });
  98298. }
  98299. }
  98300. addVideo(){
  98301. if(Potree.settings.number != 'SS-t-P6zBR73Gke')return
  98302. var geo = new PlaneGeometry(1, 1, 1, 1);
  98303. var videoInfo = this.videoInfo = [
  98304. {
  98305. id: '40-2',
  98306. url: 'https://laser-oss.4dkankan.com/testdata/SS-t-P6zBR73Gke/temp/poi/2022/05/10/0aabafee-36b8-455d-9c11-0780bf694786.mp4',
  98307. rotation:[-1.494468618954883, -1.4987317433158989, -3.061254983446741],
  98308. position:[ 19.801820617361624, 2.884673619844108, -0.03362305858221648],
  98309. scale:[3.5741423153151763, 2.8738725275578703, 1],
  98310. },
  98311. {
  98312. id: 40,
  98313. /* rotation:[-1.534692822378723, 0.01083403560862361, 3.141535283661569],
  98314. position:[17.2934294239949861, 2.413510747928117, -0.008057029580231356], */
  98315. url: 'https://laser-oss.4dkankan.com/testdata/SS-t-P6zBR73Gke/temp/poi/2022/05/09/7896d6ef-a2d6-4fd7-949c-768782a5b484.mp4',
  98316. rotation:[-1.5487684197910518, 0.021848470169552752, -3.1387534893955236],
  98317. position:[17.277316608096, 2.0840432922115846, -0.0931149415437065],
  98318. scale:[2.0821757723834047, 0.6129478480765236, 1],
  98319. visibles: [40]
  98320. },
  98321. ];
  98322. let add = (info)=>{
  98323. var video = $(`<video controls="controls" loop autoplay x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload"></video>`)[0];
  98324. video.setAttribute("crossOrigin", 'Anonymous');
  98325. video.src = info.url || Potree.resourcePath+`/video/${Potree.settings.number}/${info.id}.mp4`;
  98326. var map = new VideoTexture(video);
  98327. var plane = this.videoPlane = new Mesh(geo, new MeshBasicMaterial({
  98328. color:"#ffffff",
  98329. transparent: !0,
  98330. depthTest:false,
  98331. opacity:0 ,
  98332. //side:2,
  98333. map
  98334. }));
  98335. plane.position.fromArray(info.position);
  98336. plane.rotation.fromArray(info.rotation);
  98337. info.scale && plane.scale.fromArray(info.scale);
  98338. this.scene.scene.add(plane);
  98339. info.plane = plane;
  98340. plane.boundingBox = new Box3(new Vector3(0,-0.5,0),new Vector3(1,-0.4,0.2));
  98341. video.addEventListener('loadeddata', function(e) {
  98342. video.play();
  98343. if(!info.visibles/* ||!viewer.images360.currentPano || info.visibles.includes(viewer.images360.currentPano.id) */){
  98344. plane.material.opacity = 1;
  98345. }
  98346. info.scale || plane.scale.set(video.videoWidth/1000,video.videoHeight/1000,1); // 1080 * 1920
  98347. console.log('video loadeddata', info.id);
  98348. });
  98349. if(info.visibles){
  98350. this.images360.addEventListener('flyToPano' ,(e)=>{//飞之前
  98351. if(info.visibles.includes(e.toPano.pano.id)){ //出现
  98352. setTimeout(()=>{
  98353. plane.visible = true;
  98354. video.currentTime = 0;
  98355. video.play();
  98356. if(video.paused){
  98357. var startPlay = ()=>{
  98358. plane.visible && video.play();
  98359. this.removeEventListener('global_mousedown', startPlay);
  98360. };
  98361. this.addEventListener('global_mousedown', startPlay);
  98362. }
  98363. Potree.settings.zoom.enabled = false;
  98364. transitions.start(lerp.property(plane.material, "opacity", 1 ) , e.toPano.duration*0.4 , ()=>{
  98365. }, 0, easing['easeInOutQuad']);
  98366. }, e.toPano.duration*0.6); //时间上不能和消失的重叠 延迟
  98367. }else {
  98368. //消失
  98369. transitions.start(lerp.property(plane.material, "opacity", 0, ) , e.toPano.duration*0.4, ()=>{
  98370. if(!info){
  98371. plane.visible = false;
  98372. video.pause();
  98373. Potree.settings.zoom.enabled = true;
  98374. }
  98375. }, 0, easing['easeInOutQuad']);
  98376. }
  98377. });
  98378. }
  98379. var startPlay = ()=>{
  98380. video.play();
  98381. //video.pause()
  98382. //video.currentTime = 0.1;
  98383. this.removeEventListener('global_mousedown', startPlay);
  98384. };
  98385. this.addEventListener('global_mousedown', startPlay);
  98386. Potree.settings.isTest && plane.addEventListener('select',(e)=>{console.log(e);});
  98387. };
  98388. videoInfo.forEach(info=>{
  98389. add(info);
  98390. });
  98391. /* this.images360.addEventListener('flyToPano' ,(e)=>{//飞之前
  98392. if(Potree.settings.displayMode != 'showPanos') return
  98393. let info = videoInfo[e.toPano.pano.id]
  98394. if(info ){ //出现
  98395. setTimeout(()=>{
  98396. plane.visible = true;
  98397. plane.position.fromArray(info.position)
  98398. plane.rotation.fromArray(info.rotation)
  98399. video.src = Potree.resourcePath+`/video/${Potree.settings.number}/${e.toPano.pano.id}.mp4`
  98400. video.play();
  98401. video.currentTime = 0
  98402. Potree.settings.zoom.enabled = false
  98403. transitions.start(lerp.property(plane.material, "opacity", 1 ) , e.toPano.duration*0.4 , ()=>{
  98404. }, 0, easing['easeInOutQuad'])
  98405. }, e.toPano.duration*0.6) //时间上不能和消失的重叠 延迟
  98406. }
  98407. //消失
  98408. transitions.start(lerp.property(plane.material, "opacity", 0, ) , e.toPano.duration*0.4, ()=>{
  98409. if(!info){
  98410. plane.visible = false
  98411. video.pause()
  98412. Potree.settings.zoom.enabled = true
  98413. }
  98414. }, 0, easing['easeInOutQuad'])
  98415. })
  98416. this.images360.addEventListener('endChangeMode',(e)=>{ //暂时不处理初始加载时就在有视频的点位上的情况
  98417. if(e.mode == 'showPanos'){
  98418. let info = videoInfo[this.images360.currentPano.id]
  98419. if(info ){ //出现
  98420. plane.visible = true;
  98421. plane.position.fromArray(info.position)
  98422. plane.rotation.fromArray(info.rotation)
  98423. plane.material.opacity = 0
  98424. video.src = Potree.resourcePath+`/video/${Potree.settings.number}/${this.images360.currentPano.id}.mp4`
  98425. video.play();
  98426. video.currentTime = 0
  98427. Potree.settings.zoom.enabled = false
  98428. transitions.start(lerp.property(plane.material, "opacity", 1, (e)=>{console.log('fadeIn',e)}) , 300 , ()=>{
  98429. }, 0, easing['easeInOutQuad'])
  98430. }
  98431. }else{
  98432. plane.visible = false;
  98433. Potree.settings.zoom.enabled = true
  98434. }
  98435. })
  98436. */
  98437. }
  98438. addSprite(e){//api
  98439. let sprite;
  98440. if(e.text != void 0){
  98441. sprite = new TextSprite(e );
  98442. }else {
  98443. let map = texLoader.load(src);
  98444. e.map = map;
  98445. sprite = new Sprite(e );
  98446. }
  98447. return sprite
  98448. }
  98449. };
  98450. //------ CLIP 默认clipTask都是clipInside ----------------------
  98451. /*
  98452. 并集相当于加法,交集相当于乘法。 所有结果都能展开成多个乘积相加。
  98453. 假设有4个clipBoxes,ABCD, 如果是 A*B + C*D ,那么这是最终结果。 如果是 (A+B)*(C+D) = A*C+A*D+B*C+B*D
  98454. */
  98455. /*
  98456. let Clips = {
  98457. boxes : [],
  98458. unionGroups : [], //二维数组。最外层要求并集,里层要求交集(如果只有一个元素就是本身)。总结起来就是要求一堆交集的并集
  98459. shaderParams:{},
  98460. needsUpdate : true,
  98461. addClip(box, clipMethod){
  98462. //不允许重复
  98463. if(this.boxes.includes(box)){
  98464. return console.warn('addClip重复添加了box',box)
  98465. }
  98466. boxes.push(box)
  98467. if(clipMethod == 'any'){//并
  98468. this.unionGroups.push([box])
  98469. }else if(clipMethod == 'all'){//交
  98470. this.unionGroups.forEach(mixGroup=>mixGroup.push(box))
  98471. }
  98472. this.needsUpdate = true
  98473. },
  98474. removeClip(box){
  98475. if(!this.boxes.includes(box)){
  98476. return console.warn('removeClip没有找到该box',box)
  98477. }
  98478. var newGroups = [];
  98479. this.unionGroups.forEach(mixGroup=>{
  98480. if(mixGroup.length == 1 && mixGroup[0] == box)return;//直接删除
  98481. newGroups.push(mixGroup.filter(e=>e!=box));
  98482. })
  98483. this.unionGroups = newGroups;
  98484. this.needsUpdate = true
  98485. }
  98486. ,
  98487. clearClip(){
  98488. this.boxes = [];
  98489. this.unionGroups = []
  98490. this.needsUpdate = true
  98491. }
  98492. ,
  98493. updateShaderParams(){//没写完 - - 见 pointcloud clip.vs
  98494. //uniform mat4 clipBoxes[num_clipboxes];
  98495. //uniform int clipBoxGroupCount;
  98496. //uniform int mixClipIndices[clipboxGroupItemCount]; //把所有的要求都直接放到数组内
  98497. //这里需要转为Float32Array..? 参考material.setClipBoxes
  98498. let everyClipGroupCount = this.unionGroups.map(e=>e.length)
  98499. let mixClipIndices = []
  98500. this.unionGroups.forEach(e=>{
  98501. mixClipIndices.push(...e)
  98502. })
  98503. this.shaderParams = {
  98504. num_clipboxes : this.boxes.length,
  98505. clipBoxGroupCount : this.unionGroups.length,
  98506. everyClipGroupCount,
  98507. clipBoxIndexCount: mixClipIndices.length,
  98508. mixClipIndices
  98509. }
  98510. }
  98511. ,
  98512. getShaderParams(){//每次要传递参数到shader中,执行这个就好
  98513. if(this.needsUpdate){
  98514. this.updateShaderParams()
  98515. }
  98516. return this.shaderParams
  98517. }
  98518. }
  98519. */
  98520. /**
  98521. * @author mschuetz / http://mschuetz.at
  98522. *
  98523. * adapted from THREE.OrbitControls by
  98524. *
  98525. * @author qiao / https://github.com/qiao
  98526. * @author mrdoob / http://mrdoob.com
  98527. * @author alteredq / http://alteredqualia.com/
  98528. * @author WestLangley / http://github.com/WestLangley
  98529. * @author erich666 / http://erichaines.com
  98530. *
  98531. *
  98532. *
  98533. */
  98534. class OrbitControls$1 extends EventDispatcher$1{
  98535. constructor(viewer){
  98536. super();
  98537. this.viewer = viewer;
  98538. this.renderer = viewer.renderer;
  98539. this.scene = null;
  98540. this.sceneControls = new Scene();
  98541. this.rotationSpeed = 5;
  98542. this.fadeFactor = 20;
  98543. this.yawDelta = 0;
  98544. this.pitchDelta = 0;
  98545. this.panDelta = new Vector2(0, 0);
  98546. this.radiusDelta = 0;
  98547. this.doubleClockZoomEnabled = true;
  98548. this.tweens = [];
  98549. let drag = (e) => {
  98550. if (e.drag.object !== null) {
  98551. return;
  98552. }
  98553. if (e.drag.startHandled === undefined) {
  98554. e.drag.startHandled = true;
  98555. this.dispatchEvent({type: 'start'});
  98556. }
  98557. let ndrag = {
  98558. x: e.drag.lastDrag.x / this.renderer.domElement.clientWidth,
  98559. y: e.drag.lastDrag.y / this.renderer.domElement.clientHeight
  98560. };
  98561. if (e.drag.mouse === MOUSE$1.LEFT) {
  98562. this.yawDelta += ndrag.x * this.rotationSpeed;
  98563. this.pitchDelta += ndrag.y * this.rotationSpeed;
  98564. this.stopTweens();
  98565. } else if (e.drag.mouse === MOUSE$1.RIGHT) {
  98566. this.panDelta.x += ndrag.x;
  98567. this.panDelta.y += ndrag.y;
  98568. this.stopTweens();
  98569. }
  98570. };
  98571. let drop = e => {
  98572. this.dispatchEvent({type: 'end'});
  98573. };
  98574. let scroll = (e) => {
  98575. let resolvedRadius = this.scene.view.radius + this.radiusDelta;
  98576. this.radiusDelta += -e.delta * resolvedRadius * 0.1;
  98577. this.stopTweens();
  98578. };
  98579. let dblclick = (e) => {
  98580. if(this.doubleClockZoomEnabled){
  98581. this.zoomToLocation(e.mouse);
  98582. }
  98583. };
  98584. let previousTouch = null;
  98585. let touchStart = e => {
  98586. previousTouch = e;
  98587. };
  98588. let touchEnd = e => {
  98589. previousTouch = e;
  98590. };
  98591. let touchMove = e => {
  98592. if (e.touches.length === 2 && previousTouch.touches.length === 2){
  98593. let prev = previousTouch;
  98594. let curr = e;
  98595. let prevDX = prev.touches[0].pageX - prev.touches[1].pageX;
  98596. let prevDY = prev.touches[0].pageY - prev.touches[1].pageY;
  98597. let prevDist = Math.sqrt(prevDX * prevDX + prevDY * prevDY);
  98598. let currDX = curr.touches[0].pageX - curr.touches[1].pageX;
  98599. let currDY = curr.touches[0].pageY - curr.touches[1].pageY;
  98600. let currDist = Math.sqrt(currDX * currDX + currDY * currDY);
  98601. let delta = currDist / prevDist;
  98602. let resolvedRadius = this.scene.view.radius + this.radiusDelta;
  98603. let newRadius = resolvedRadius / delta;
  98604. this.radiusDelta = newRadius - resolvedRadius;
  98605. this.stopTweens();
  98606. }else if(e.touches.length === 3 && previousTouch.touches.length === 3){
  98607. let prev = previousTouch;
  98608. let curr = e;
  98609. let prevMeanX = (prev.touches[0].pageX + prev.touches[1].pageX + prev.touches[2].pageX) / 3;
  98610. let prevMeanY = (prev.touches[0].pageY + prev.touches[1].pageY + prev.touches[2].pageY) / 3;
  98611. let currMeanX = (curr.touches[0].pageX + curr.touches[1].pageX + curr.touches[2].pageX) / 3;
  98612. let currMeanY = (curr.touches[0].pageY + curr.touches[1].pageY + curr.touches[2].pageY) / 3;
  98613. let delta = {
  98614. x: (currMeanX - prevMeanX) / this.renderer.domElement.clientWidth,
  98615. y: (currMeanY - prevMeanY) / this.renderer.domElement.clientHeight
  98616. };
  98617. this.panDelta.x += delta.x;
  98618. this.panDelta.y += delta.y;
  98619. this.stopTweens();
  98620. }
  98621. previousTouch = e;
  98622. };
  98623. this.addEventListener('touchstart', touchStart);
  98624. this.addEventListener('touchend', touchEnd);
  98625. this.addEventListener('touchmove', touchMove);
  98626. this.addEventListener('drag', drag);
  98627. this.addEventListener('drop', drop);
  98628. this.addEventListener('mousewheel', scroll);
  98629. this.addEventListener('dblclick', dblclick);
  98630. }
  98631. setScene (scene) {
  98632. this.scene = scene;
  98633. }
  98634. stop(){
  98635. this.yawDelta = 0;
  98636. this.pitchDelta = 0;
  98637. this.radiusDelta = 0;
  98638. this.panDelta.set(0, 0);
  98639. }
  98640. zoomToLocation(mouse){
  98641. let camera = this.scene.getActiveCamera();
  98642. let I = Utils.getMousePointCloudIntersection(
  98643. mouse,
  98644. camera,
  98645. this.viewer,
  98646. this.scene.pointclouds,
  98647. {pickClipped: true});
  98648. if (I === null) {
  98649. return;
  98650. }
  98651. let targetRadius = 0;
  98652. {
  98653. let minimumJumpDistance = 0.2;
  98654. let domElement = this.renderer.domElement;
  98655. let ray = Utils.mouseToRay(mouse, camera, domElement.clientWidth, domElement.clientHeight);
  98656. let nodes = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, ray);
  98657. let lastNode = nodes[nodes.length - 1];
  98658. let radius = lastNode.getBoundingSphere(new Sphere()).radius;
  98659. targetRadius = Math.min(this.scene.view.radius, radius);
  98660. targetRadius = Math.max(minimumJumpDistance, targetRadius);
  98661. }
  98662. let d = this.scene.view.direction.multiplyScalar(-1);
  98663. let cameraTargetPosition = new Vector3().addVectors(I.location, d.multiplyScalar(targetRadius));
  98664. // TODO Unused: let controlsTargetPosition = I.location;
  98665. let animationDuration = 600;
  98666. let easing = TWEEN.Easing.Quartic.Out;
  98667. { // animate
  98668. let value = {x: 0};
  98669. let tween = new TWEEN.Tween(value).to({x: 1}, animationDuration);
  98670. tween.easing(easing);
  98671. this.tweens.push(tween);
  98672. let startPos = this.scene.view.position.clone();
  98673. let targetPos = cameraTargetPosition.clone();
  98674. let startRadius = this.scene.view.radius;
  98675. let targetRadius = cameraTargetPosition.distanceTo(I.location);
  98676. tween.onUpdate(() => {
  98677. let t = value.x;
  98678. this.scene.view.position.x = (1 - t) * startPos.x + t * targetPos.x;
  98679. this.scene.view.position.y = (1 - t) * startPos.y + t * targetPos.y;
  98680. this.scene.view.position.z = (1 - t) * startPos.z + t * targetPos.z;
  98681. this.scene.view.radius = (1 - t) * startRadius + t * targetRadius;
  98682. this.viewer.setMoveSpeed(this.scene.view.radius);
  98683. });
  98684. tween.onComplete(() => {
  98685. this.tweens = this.tweens.filter(e => e !== tween);
  98686. });
  98687. tween.start();
  98688. }
  98689. }
  98690. stopTweens () {
  98691. this.tweens.forEach(e => e.stop());
  98692. this.tweens = [];
  98693. }
  98694. update (delta) {
  98695. let view = this.scene.view;
  98696. { // apply rotation
  98697. let progression = Math.min(1, this.fadeFactor * delta);
  98698. let yaw = view.yaw;
  98699. let pitch = view.pitch;
  98700. let pivot = view.getPivot();
  98701. yaw -= progression * this.yawDelta;
  98702. pitch -= progression * this.pitchDelta;
  98703. view.yaw = yaw;
  98704. view.pitch = pitch;
  98705. let V = this.scene.view.direction.multiplyScalar(-view.radius);
  98706. let position = new Vector3().addVectors(pivot, V);
  98707. view.position.copy(position);
  98708. }
  98709. { // apply pan
  98710. let progression = Math.min(1, this.fadeFactor * delta);
  98711. let panDistance = progression * view.radius * 3;
  98712. let px = -this.panDelta.x * panDistance;
  98713. let py = this.panDelta.y * panDistance;
  98714. view.pan(px, py);
  98715. }
  98716. { // apply zoom
  98717. let progression = Math.min(1, this.fadeFactor * delta);
  98718. // let radius = view.radius + progression * this.radiusDelta * view.radius * 0.1;
  98719. let radius = view.radius + progression * this.radiusDelta;
  98720. let V = view.direction.multiplyScalar(-radius);
  98721. let position = new Vector3().addVectors(view.getPivot(), V);
  98722. view.radius = radius;
  98723. view.position.copy(position);
  98724. }
  98725. {
  98726. let speed = view.radius;
  98727. this.viewer.setMoveSpeed(speed);
  98728. }
  98729. { // decelerate over time
  98730. let progression = Math.min(1, this.fadeFactor * delta);
  98731. let attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  98732. this.yawDelta *= attenuation;
  98733. this.pitchDelta *= attenuation;
  98734. this.panDelta.multiplyScalar(attenuation);
  98735. // this.radiusDelta *= attenuation;
  98736. this.radiusDelta -= progression * this.radiusDelta;
  98737. }
  98738. }
  98739. };
  98740. /**
  98741. * @author mschuetz / http://mschuetz.at
  98742. *
  98743. * adapted from THREE.OrbitControls by
  98744. *
  98745. * @author qiao / https://github.com/qiao
  98746. * @author mrdoob / http://mrdoob.com
  98747. * @author alteredq / http://alteredqualia.com/
  98748. * @author WestLangley / http://github.com/WestLangley
  98749. * @author erich666 / http://erichaines.com
  98750. *
  98751. *
  98752. *
  98753. */
  98754. class FirstPersonControls$1 extends EventDispatcher$1 {//old
  98755. constructor (viewer) {
  98756. super();
  98757. this.viewer = viewer;
  98758. this.renderer = viewer.renderer;
  98759. this.scene = null;
  98760. this.sceneControls = new Scene();
  98761. this.rotationSpeed = 200;
  98762. this.moveSpeed = 10;
  98763. this.lockElevation = false;
  98764. this.keys = {
  98765. FORWARD: ['W'.charCodeAt(0), 38],
  98766. BACKWARD: ['S'.charCodeAt(0), 40],
  98767. LEFT: ['A'.charCodeAt(0), 37],
  98768. RIGHT: ['D'.charCodeAt(0), 39],
  98769. UP: ['R'.charCodeAt(0), 33],
  98770. DOWN: ['F'.charCodeAt(0), 34]
  98771. };
  98772. this.fadeFactor = 50;
  98773. this.yawDelta = 0;
  98774. this.pitchDelta = 0;
  98775. this.translationDelta = new Vector3(0, 0, 0);
  98776. this.translationWorldDelta = new Vector3(0, 0, 0);
  98777. this.tweens = [];
  98778. let drag = (e) => {
  98779. if (e.drag.object !== null) {
  98780. return;
  98781. }
  98782. if (e.drag.startHandled === undefined) {
  98783. e.drag.startHandled = true;
  98784. this.dispatchEvent({type: 'start'});
  98785. }
  98786. let moveSpeed = this.viewer.getMoveSpeed();
  98787. let ndrag = {
  98788. x: e.drag.lastDrag.x / this.renderer.domElement.clientWidth,
  98789. y: e.drag.lastDrag.y / this.renderer.domElement.clientHeight
  98790. };
  98791. if (e.drag.mouse === MOUSE$1.LEFT) {
  98792. this.yawDelta += ndrag.x * this.rotationSpeed;
  98793. this.pitchDelta += ndrag.y * this.rotationSpeed;
  98794. } else if (e.drag.mouse === MOUSE$1.RIGHT) {
  98795. this.translationDelta.x -= ndrag.x * moveSpeed * 100;
  98796. this.translationDelta.z += ndrag.y * moveSpeed * 100;
  98797. }
  98798. };
  98799. let drop = e => {
  98800. this.dispatchEvent({type: 'end'});
  98801. };
  98802. let scroll = (e) => {
  98803. let speed = this.viewer.getMoveSpeed();
  98804. if (e.delta < 0) {
  98805. speed = speed * 0.9;
  98806. } else if (e.delta > 0) {
  98807. speed = speed / 0.9;
  98808. }
  98809. speed = Math.max(speed, 0.1);
  98810. this.viewer.setMoveSpeed(speed);
  98811. };
  98812. let dblclick = (e) => {
  98813. this.zoomToLocation(e.mouse);
  98814. };
  98815. this.addEventListener('drag', drag);
  98816. this.addEventListener('drop', drop);
  98817. this.addEventListener('mousewheel', scroll);
  98818. this.addEventListener('dblclick', dblclick);
  98819. }
  98820. setScene (scene) {
  98821. this.scene = scene;
  98822. }
  98823. stop(){
  98824. this.yawDelta = 0;
  98825. this.pitchDelta = 0;
  98826. this.translationDelta.set(0, 0, 0);
  98827. }
  98828. zoomToLocation(mouse){
  98829. let camera = this.scene.getActiveCamera();
  98830. let I = Utils.getMousePointCloudIntersection(
  98831. mouse,
  98832. camera,
  98833. this.viewer,
  98834. this.scene.pointclouds);
  98835. if (I === null) {
  98836. return;
  98837. }
  98838. let targetRadius = 0;
  98839. {
  98840. let minimumJumpDistance = 0.2;
  98841. let domElement = this.renderer.domElement;
  98842. let ray = Utils.mouseToRay(mouse, camera, domElement.clientWidth, domElement.clientHeight);
  98843. let nodes = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, ray);
  98844. let lastNode = nodes[nodes.length - 1];
  98845. let radius = lastNode.getBoundingSphere(new Sphere()).radius;
  98846. targetRadius = Math.min(this.scene.view.radius, radius);
  98847. targetRadius = Math.max(minimumJumpDistance, targetRadius);
  98848. }
  98849. let d = this.scene.view.direction.multiplyScalar(-1);
  98850. let cameraTargetPosition = new Vector3().addVectors(I.location, d.multiplyScalar(targetRadius));
  98851. // TODO Unused: let controlsTargetPosition = I.location;
  98852. let animationDuration = 600;
  98853. let easing = TWEEN.Easing.Quartic.Out;
  98854. { // animate
  98855. let value = {x: 0};
  98856. let tween = new TWEEN.Tween(value).to({x: 1}, animationDuration);
  98857. tween.easing(easing);
  98858. this.tweens.push(tween);
  98859. let startPos = this.scene.view.position.clone();
  98860. let targetPos = cameraTargetPosition.clone();
  98861. let startRadius = this.scene.view.radius;
  98862. let targetRadius = cameraTargetPosition.distanceTo(I.location);
  98863. tween.onUpdate(() => {
  98864. let t = value.x;
  98865. this.scene.view.position.x = (1 - t) * startPos.x + t * targetPos.x;
  98866. this.scene.view.position.y = (1 - t) * startPos.y + t * targetPos.y;
  98867. this.scene.view.position.z = (1 - t) * startPos.z + t * targetPos.z;
  98868. this.scene.view.radius = (1 - t) * startRadius + t * targetRadius;
  98869. this.viewer.setMoveSpeed(this.scene.view.radius / 2.5);
  98870. });
  98871. tween.onComplete(() => {
  98872. this.tweens = this.tweens.filter(e => e !== tween);
  98873. });
  98874. tween.start();
  98875. }
  98876. }
  98877. update (delta) {
  98878. let view = this.scene.view;
  98879. { // cancel move animations on user input
  98880. let changes = [ this.yawDelta,
  98881. this.pitchDelta,
  98882. this.translationDelta.length(),
  98883. this.translationWorldDelta.length() ];
  98884. let changeHappens = changes.some(e => Math.abs(e) > 0.001);
  98885. if (changeHappens && this.tweens.length > 0) {
  98886. this.tweens.forEach(e => e.stop());
  98887. this.tweens = [];
  98888. }
  98889. }
  98890. { // accelerate while input is given
  98891. let ih = this.viewer.inputHandler;
  98892. let moveForward = this.keys.FORWARD.some(e => ih.pressedKeys[e]);
  98893. let moveBackward = this.keys.BACKWARD.some(e => ih.pressedKeys[e]);
  98894. let moveLeft = this.keys.LEFT.some(e => ih.pressedKeys[e]);
  98895. let moveRight = this.keys.RIGHT.some(e => ih.pressedKeys[e]);
  98896. let moveUp = this.keys.UP.some(e => ih.pressedKeys[e]);
  98897. let moveDown = this.keys.DOWN.some(e => ih.pressedKeys[e]);
  98898. if(this.lockElevation){
  98899. let dir = view.direction;
  98900. dir.z = 0;
  98901. dir.normalize();
  98902. if (moveForward && moveBackward) {
  98903. this.translationWorldDelta.set(0, 0, 0);
  98904. } else if (moveForward) {
  98905. this.translationWorldDelta.copy(dir.multiplyScalar(this.viewer.getMoveSpeed()));
  98906. } else if (moveBackward) {
  98907. this.translationWorldDelta.copy(dir.multiplyScalar(-this.viewer.getMoveSpeed()));
  98908. }
  98909. }else {
  98910. if (moveForward && moveBackward) {
  98911. this.translationDelta.y = 0;
  98912. } else if (moveForward) {
  98913. this.translationDelta.y = this.viewer.getMoveSpeed();
  98914. } else if (moveBackward) {
  98915. this.translationDelta.y = -this.viewer.getMoveSpeed();
  98916. }
  98917. }
  98918. if (moveLeft && moveRight) {
  98919. this.translationDelta.x = 0;
  98920. } else if (moveLeft) {
  98921. this.translationDelta.x = -this.viewer.getMoveSpeed();
  98922. } else if (moveRight) {
  98923. this.translationDelta.x = this.viewer.getMoveSpeed();
  98924. }
  98925. if (moveUp && moveDown) {
  98926. this.translationWorldDelta.z = 0;
  98927. } else if (moveUp) {
  98928. this.translationWorldDelta.z = this.viewer.getMoveSpeed();
  98929. } else if (moveDown) {
  98930. this.translationWorldDelta.z = -this.viewer.getMoveSpeed();
  98931. }
  98932. }
  98933. { // apply rotation
  98934. let yaw = view.yaw;
  98935. let pitch = view.pitch;
  98936. yaw -= this.yawDelta * delta;
  98937. pitch -= this.pitchDelta * delta;
  98938. view.yaw = yaw;
  98939. view.pitch = pitch;
  98940. }
  98941. { // apply translation
  98942. view.translate(
  98943. this.translationDelta.x * delta,
  98944. this.translationDelta.y * delta,
  98945. this.translationDelta.z * delta
  98946. );
  98947. view.translateWorld(
  98948. this.translationWorldDelta.x * delta,
  98949. this.translationWorldDelta.y * delta,
  98950. this.translationWorldDelta.z * delta
  98951. );
  98952. }
  98953. { // set view target according to speed
  98954. view.radius = 3 * this.viewer.getMoveSpeed();
  98955. }
  98956. { // decelerate over time
  98957. let attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  98958. this.yawDelta *= attenuation;
  98959. this.pitchDelta *= attenuation;
  98960. this.translationDelta.multiplyScalar(attenuation);
  98961. this.translationWorldDelta.multiplyScalar(attenuation);
  98962. }
  98963. }
  98964. };
  98965. OrthographicCamera.prototype.zoomTo = function( node, factor = 1){
  98966. if ( !node.geometry && !node.boundingBox) {
  98967. return;
  98968. }
  98969. // TODO
  98970. //let minWS = new THREE.Vector4(node.boundingBox.min.x, node.boundingBox.min.y, node.boundingBox.min.z, 1);
  98971. //let minVS = minWS.applyMatrix4(this.matrixWorldInverse);
  98972. //let right = node.boundingBox.max.x;
  98973. //let bottom = node.boundingBox.min.y;
  98974. //let top = node.boundingBox.max.y;
  98975. this.updateProjectionMatrix();
  98976. };
  98977. PerspectiveCamera.prototype.zoomTo = function (node, factor) {
  98978. if (!node.geometry && !node.boundingSphere && !node.boundingBox) {
  98979. return;
  98980. }
  98981. if (node.geometry && node.geometry.boundingSphere === null) {
  98982. node.geometry.computeBoundingSphere();
  98983. }
  98984. node.updateMatrixWorld();
  98985. let bs;
  98986. if (node.boundingSphere) {
  98987. bs = node.boundingSphere;
  98988. } else if (node.geometry && node.geometry.boundingSphere) {
  98989. bs = node.geometry.boundingSphere;
  98990. } else {
  98991. bs = node.boundingBox.getBoundingSphere(new Sphere());
  98992. }
  98993. let _factor = factor || 1;
  98994. bs = bs.clone().applyMatrix4(node.matrixWorld);
  98995. let radius = bs.radius;
  98996. let fovr = this.fov * Math.PI / 180;
  98997. if (this.aspect < 1) {
  98998. fovr = fovr * this.aspect;
  98999. }
  99000. let distanceFactor = Math.abs(radius / Math.sin(fovr / 2)) * _factor;
  99001. let offset = this.getWorldDirection(new Vector3()).multiplyScalar(-distanceFactor);
  99002. this.position.copy(bs.center.clone().add(offset));
  99003. };
  99004. Ray.prototype.distanceToPlaneWithNegative = function (plane) {
  99005. let denominator = plane.normal.dot(this.direction);
  99006. if (denominator === 0) {
  99007. // line is coplanar, return origin
  99008. if (plane.distanceToPoint(this.origin) === 0) {
  99009. return 0;
  99010. }
  99011. // Null is preferable to undefined since undefined means.... it is undefined
  99012. return null;
  99013. }
  99014. let t = -(this.origin.dot(plane.normal) + plane.constant) / denominator;
  99015. return t;
  99016. };
  99017. const workerPool = new WorkerPool();
  99018. const version = {
  99019. major: 1,
  99020. minor: 8,
  99021. suffix: '.0'
  99022. };
  99023. let lru = new LRU();
  99024. console.log('Potree ' + version.major + '.' + version.minor + version.suffix);
  99025. let pointBudget = 1 * 1000 * 1000;
  99026. let framenumber = 0;
  99027. let numNodesLoading = 0;
  99028. let maxNodesLoading = 4;
  99029. const debug = {};
  99030. exports.scriptPath = "";
  99031. if (document.currentScript && document.currentScript.src) {
  99032. exports.scriptPath = new URL(document.currentScript.src + '/..').href;
  99033. if (exports.scriptPath.slice(-1) === '/') {
  99034. exports.scriptPath = exports.scriptPath.slice(0, -1);
  99035. }
  99036. } else if(({ url: (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('potree.js', document.baseURI).href)) })){
  99037. exports.scriptPath = new URL((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('potree.js', document.baseURI).href)) + "/..").href;
  99038. if (exports.scriptPath.slice(-1) === '/') {
  99039. exports.scriptPath = exports.scriptPath.slice(0, -1);
  99040. }
  99041. }else {
  99042. console.error('Potree was unable to find its script path using document.currentScript. Is Potree included with a script tag? Does your browser support this function?');
  99043. }
  99044. let resourcePath = exports.scriptPath + '/resources';
  99045. //add:
  99046. async function loadFile(path, params , callback, onError){
  99047. params = params || {};
  99048. if(Potree.fileServer){
  99049. Potree.fileServer.get(path, { params }).then(data=>{
  99050. if(data.data)data = data.data;
  99051. if(data.data)data = data.data; //融合页面getdataset需要查找两次data
  99052. callback && callback(data);
  99053. }).catch(onError);
  99054. }else {
  99055. try{
  99056. if(Object.keys(params).length > 0){
  99057. path+='?';
  99058. let index = 0;
  99059. for(let i in params){
  99060. if(index>0) path += '&';
  99061. path+=i; path+='='; path+=params[i];
  99062. index ++;
  99063. }
  99064. }
  99065. let response = await fetch(path);
  99066. let text = await response.text();
  99067. var data = JSON.parse(text);
  99068. if(data.data) data = data.data;
  99069. callback && callback(data);
  99070. return data
  99071. }catch(e){
  99072. console.error('loadFile出错', path);
  99073. onError && onError(e);
  99074. }
  99075. }
  99076. //查询: http://192.168.0.26:8080/doc.html#/default/filter-%E6%BC%AB%E6%B8%B8%E7%82%B9/filterUsingGET
  99077. }
  99078. async function loadPanos( callback){
  99079. var path;
  99080. //let query = `?datasetId=${datasetId}` //`?lat=${center.lat}&lon=${center.lon}&radius=200000`
  99081. if(Potree.fileServer){
  99082. path = '/vision.json';
  99083. }else {
  99084. path = `${Potree.settings.urls.prefix1}/floor_0_webcloud/floor_0_vision.txt`; //'/floor_0_webcloud/floor_0_vision.txt' //`${Potree.settings.urls.prefix1}/vision.json`
  99085. }
  99086. return Potree.getRealUrl(path, (path)=>{
  99087. loadFile(path, { }, callback, );
  99088. })
  99089. //return loadFile(path, { }, callback)
  99090. }
  99091. function Log$1(){
  99092. let args = Array.from(arguments);
  99093. let params = args[args.length-1];
  99094. if(params && params.font) {params = params.font, args.pop();}
  99095. else params = {};
  99096. let str = '', color = params.color || '#13f', fontSize = params.fontSize || 12;
  99097. args.forEach((e,i)=>{
  99098. i > 0 && (str += ' , ' );
  99099. /* if(params.toFixed && typeof e == 'number'){
  99100. e = e.toFixed(params.toFixed)
  99101. } */
  99102. if(params.toFixed ){
  99103. e = Potree.math.toPrecision(e, params.toFixed);
  99104. }
  99105. str += e; //object可以JSON.stringify,但不是所有都行
  99106. });
  99107. console.warn(`%c${str}`, `color:${color};font-size:${fontSize}px`);
  99108. }
  99109. function getRealUrl(url, startLoad){
  99110. if(Potree.getFileUrl){//更换url
  99111. Potree.getFileUrl(url).then(realUrl => {
  99112. startLoad(realUrl);
  99113. });
  99114. }else {
  99115. startLoad(url);
  99116. }
  99117. }
  99118. function loadPointCloud$1(path, timeStamp, callback, onError){
  99119. let loaded = function(e){
  99120. e.pointcloud.name = Potree.settings.number;
  99121. //e.pointcloud.sceneCode = sceneCode //对应4dkk的场景码
  99122. callback(e);
  99123. };
  99124. let promise = new Promise( resolve => {
  99125. // load pointcloud
  99126. if (!path){
  99127. // TODO: callback? comment? Hello? Bueller? Anyone?
  99128. } else if (path.indexOf('ept.json') > 0) {
  99129. EptLoader.load(path, function(geometry) {
  99130. if (!geometry) {
  99131. console.error(new Error(`failed to load point cloud from URL: ${path}`));
  99132. }
  99133. else {
  99134. let pointcloud = new ExtendPointCloudOctree(geometry);
  99135. //loaded(pointcloud);
  99136. resolve({type: 'pointcloud_loaded', pointcloud: pointcloud});
  99137. }
  99138. });
  99139. } else if (path.indexOf('cloud.js') > 0) {
  99140. POCLoader.load(path, timeStamp, function (geometry) {
  99141. if (!geometry) {
  99142. //callback({type: 'loading_failed'});
  99143. console.error(new Error(`failed to load point cloud from URL: ${path}`));
  99144. onError && onError();
  99145. } else {
  99146. let pointcloud = new ExtendPointCloudOctree(geometry);
  99147. // loaded(pointcloud);
  99148. resolve({type: 'pointcloud_loaded', pointcloud: pointcloud});
  99149. }
  99150. });
  99151. } else if (path.indexOf('.vpc') > 0) {
  99152. PointCloudArena4DGeometry.load(path, function (geometry) {
  99153. if (!geometry) {
  99154. //callback({type: 'loading_failed'});
  99155. console.error(new Error(`failed to load point cloud from URL: ${path}`));
  99156. } else {
  99157. let pointcloud = new PointCloudArena4D(geometry);
  99158. // loaded(pointcloud);
  99159. resolve({type: 'pointcloud_loaded', pointcloud: pointcloud});
  99160. }
  99161. });
  99162. } else {
  99163. //callback({'type': 'loading_failed'});
  99164. console.error(new Error(`failed to load point cloud from URL: ${path}`));
  99165. }
  99166. });
  99167. if(callback){
  99168. promise.then(pointcloud => {
  99169. loaded(pointcloud);
  99170. });
  99171. }else {
  99172. return promise;
  99173. }
  99174. };
  99175. // add selectgroup
  99176. (function($){
  99177. $.fn.extend({
  99178. selectgroup: function(args = {}){
  99179. let elGroup = $(this);
  99180. let rootID = elGroup.prop("id");
  99181. let groupID = `${rootID}`;
  99182. let groupTitle = (args.title !== undefined) ? args.title : "";
  99183. let elButtons = [];
  99184. elGroup.find("option").each((index, value) => {
  99185. let buttonID = $(value).prop("id");
  99186. let label = $(value).html();
  99187. let optionValue = $(value).prop("value");
  99188. let elButton = $(`
  99189. <span style="flex-grow: 1; display: inherit">
  99190. <label for="${buttonID}" class="ui-button" style="width: 100%; padding: .4em .1em">${label}</label>
  99191. <input type="radio" name="${groupID}" id="${buttonID}" value="${optionValue}" style="display: none"/>
  99192. </span>
  99193. `);
  99194. let elLabel = elButton.find("label");
  99195. let elInput = elButton.find("input");
  99196. elInput.change( () => {
  99197. elGroup.find("label").removeClass("ui-state-active");
  99198. elGroup.find("label").addClass("ui-state-default");
  99199. if(elInput.is(":checked")){
  99200. elLabel.addClass("ui-state-active");
  99201. }else {
  99202. //elLabel.addClass("ui-state-default");
  99203. }
  99204. });
  99205. elButtons.push(elButton);
  99206. });
  99207. let elFieldset = $(`
  99208. <fieldset style="border: none; margin: 0px; padding: 0px">
  99209. <legend>${groupTitle}</legend>
  99210. <span style="display: flex">
  99211. </span>
  99212. </fieldset>
  99213. `);
  99214. let elButtonContainer = elFieldset.find("span");
  99215. for(let elButton of elButtons){
  99216. elButtonContainer.append(elButton);
  99217. }
  99218. elButtonContainer.find("label").each( (index, value) => {
  99219. $(value).css("margin", "0px");
  99220. $(value).css("border-radius", "0px");
  99221. $(value).css("border", "1px solid black");
  99222. $(value).css("border-left", "none");
  99223. });
  99224. elButtonContainer.find("label:first").each( (index, value) => {
  99225. $(value).css("border-radius", "4px 0px 0px 4px");
  99226. });
  99227. elButtonContainer.find("label:last").each( (index, value) => {
  99228. $(value).css("border-radius", "0px 4px 4px 0px");
  99229. $(value).css("border-left", "none");
  99230. });
  99231. elGroup.empty();
  99232. elGroup.append(elFieldset);
  99233. }
  99234. });
  99235. })(jQuery);
  99236. //在这之后export的内容才赋值到Potree中
  99237. exports.Action = Action;
  99238. exports.Annotation = Annotation;
  99239. exports.Box3Helper = Box3Helper$1;
  99240. exports.BoxVolume = BoxVolume$1;
  99241. exports.CameraMode = CameraMode;
  99242. exports.ClassificationScheme = ClassificationScheme;
  99243. exports.ClipMethod = ClipMethod;
  99244. exports.ClipTask = ClipTask;
  99245. exports.ClipVolume = ClipVolume;
  99246. exports.ClippingTool = ClippingTool;
  99247. exports.ElevationGradientRepeat = ElevationGradientRepeat;
  99248. exports.Enum = Enum;
  99249. exports.EnumItem = EnumItem;
  99250. exports.EptBinaryLoader = EptBinaryLoader;
  99251. exports.EptKey = EptKey;
  99252. exports.EptLaszipLoader = EptLaszipLoader;
  99253. exports.EptLazBatcher = EptLazBatcher;
  99254. exports.EptLoader = EptLoader;
  99255. exports.EptZstandardLoader = EptZstandardLoader;
  99256. exports.EventDispatcher = EventDispatcher$1;
  99257. exports.ExtendPointCloudMaterial = ExtendPointCloudMaterial;
  99258. exports.ExtendPointCloudOctree = ExtendPointCloudOctree;
  99259. exports.ExtendScene = ExtendScene;
  99260. exports.EyeDomeLightingMaterial = EyeDomeLightingMaterial;
  99261. exports.Features = Features;
  99262. exports.FirstPersonControls = FirstPersonControls$1;
  99263. exports.GeoPackageLoader = GeoPackageLoader;
  99264. exports.Geopackage = Geopackage$1;
  99265. exports.Gradients = Gradients;
  99266. exports.HierarchicalSlider = HierarchicalSlider;
  99267. exports.Images360 = Images360;
  99268. exports.KeyCodes = KeyCodes;
  99269. exports.LRU = LRU;
  99270. exports.LRUItem = LRUItem;
  99271. exports.LengthUnits = LengthUnits;
  99272. exports.Log = Log$1;
  99273. exports.MOUSE = MOUSE$1;
  99274. exports.Measure = Measure$1;
  99275. exports.MeasuringTool = MeasuringTool;
  99276. exports.Message = Message;
  99277. exports.NodeLoader = NodeLoader;
  99278. exports.NormalizationEDLMaterial = NormalizationEDLMaterial;
  99279. exports.NormalizationMaterial = NormalizationMaterial;
  99280. exports.OctreeLoader = OctreeLoader;
  99281. exports.OrbitControls = OrbitControls$1;
  99282. exports.OrientedImage = OrientedImage;
  99283. exports.OrientedImageLoader = OrientedImageLoader;
  99284. exports.OrientedImages = OrientedImages;
  99285. exports.POCLoader = POCLoader;
  99286. exports.PointAttribute = PointAttribute;
  99287. exports.PointAttributeTypes = PointAttributeTypes;
  99288. exports.PointAttributes = PointAttributes;
  99289. exports.PointCloudEptGeometry = PointCloudEptGeometry;
  99290. exports.PointCloudEptGeometryNode = PointCloudEptGeometryNode;
  99291. exports.PointCloudOctreeGeometry = PointCloudOctreeGeometry;
  99292. exports.PointCloudOctreeGeometryNode = PointCloudOctreeGeometryNode;
  99293. exports.PointCloudSM = PointCloudSM;
  99294. exports.PointCloudTree = PointCloudTree;
  99295. exports.PointCloudTreeNode = PointCloudTreeNode;
  99296. exports.PointShape = PointShape$1;
  99297. exports.PointSizeType = PointSizeType;
  99298. exports.Points = Points$1;
  99299. exports.PolygonClipVolume = PolygonClipVolume;
  99300. exports.Profile = Profile;
  99301. exports.ProfileData = ProfileData;
  99302. exports.ProfileRequest = ProfileRequest;
  99303. exports.ProfileTool = ProfileTool;
  99304. exports.Renderer = Renderer;
  99305. exports.ScreenBoxSelectTool = ScreenBoxSelectTool;
  99306. exports.ShapefileLoader = ShapefileLoader;
  99307. exports.SphereVolume = SphereVolume$2;
  99308. exports.SpotLightHelper = SpotLightHelper$1;
  99309. exports.TextSprite = TextSprite$2;
  99310. exports.TransformationTool = TransformationTool;
  99311. exports.TreeType = TreeType;
  99312. exports.Utils = Utils;
  99313. exports.Version = Version;
  99314. exports.Viewer = Viewer;
  99315. exports.Volume = Volume$1;
  99316. exports.VolumeTool = VolumeTool;
  99317. exports.WorkerPool = WorkerPool;
  99318. exports.XHRFactory = XHRFactory;
  99319. exports.config = config$1;
  99320. exports.debug = debug;
  99321. exports.framenumber = framenumber;
  99322. exports.getRealUrl = getRealUrl;
  99323. exports.loadFile = loadFile;
  99324. exports.loadPanos = loadPanos;
  99325. exports.loadPointCloud = loadPointCloud$1;
  99326. exports.loadProject = loadProject;
  99327. exports.lru = lru;
  99328. exports.maxNodesLoading = maxNodesLoading;
  99329. exports.numNodesLoading = numNodesLoading;
  99330. exports.pointBudget = pointBudget;
  99331. exports.resourcePath = resourcePath;
  99332. exports.saveProject = saveProject;
  99333. exports.settings = settings;
  99334. exports.start = start;
  99335. exports.version = version;
  99336. exports.workerPool = workerPool;
  99337. Object.defineProperty(exports, '__esModule', { value: true });
  99338. })));
  99339. //# sourceMappingURL=potree.js.map